Skip to content

Commit afa69dc

Browse files
committed
New config option event_data_path
To specify the path to a local directory with waveform files organized per event.
1 parent 8805e74 commit afa69dc

File tree

8 files changed

+298
-85
lines changed

8 files changed

+298
-85
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ to the latest version.
1818
attribute specified in `--colorby` is used.
1919
- New option `--range` to manually specify the range of values for the color
2020
scale
21-
- Option `waveform_data_path` renamed to `sds_data_path`
21+
- Config option `waveform_data_path` renamed to `sds_data_path`
22+
- New config option `event_data_path` to specify the path to a local directory
23+
with waveform files organized per event
2224
- Add missing `street` map style for `map_families`
2325
- Initial support for plotting families found with template scan
2426
- Improved reading of CSV catalog files:

requake/config/configspec.conf

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ fdsn_dataselect_url = string(default=http://example.com)
1717
## Alternatively, you can provide the path to a local SDS waveform archive
1818
## (see https://docs.obspy.org/packages/autogen/obspy.clients.filesystem.sds.html)
1919
sds_data_path = string(default=None)
20+
## Or, specify a local directory with waveform files organized per event
21+
## This directory should contain subdirectories named after the eventid, each
22+
## containing waveform files in any format supported by ObsPy
23+
## (e.g., SAC, miniSEED). The eventid should be the same as in the catalog.
24+
event_data_path = string(default=None)
2025

2126
#### Catalog-based scan
2227
### The following parameters are for a catalog-based scan:
@@ -88,9 +93,10 @@ time_chunk_overlap = float(default=60)
8893
min_cc_mad_ratio = float(default=50)
8994

9095
#### Processing parameters
91-
## Seconds before P arrival to cut trace (only used for catalog search)
96+
## Seconds before P arrival to cut trace
97+
## (only used for catalog search and continuous data)
9298
cc_pre_P = float(default=5)
93-
## Trace length in seconds (only used for catalog search)
99+
## Trace length in seconds (only used for catalog search and continuous data)
94100
cc_trace_length = float(default=120)
95101
## Frequency range for computing cross-correlation (Hz)
96102
cc_freq_min = float(default=2)

requake/config/rq_setup.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -160,14 +160,16 @@ def _connect_station_dataselect():
160160
logger.info(
161161
f'Connected to FDSN station server: {config.fdsn_station_url}'
162162
)
163+
config.dataselect_client = None
163164
if config.sds_data_path is not None:
164165
_connect_sds()
165-
else:
166-
config.dataselect_client = FDSNClient(config.fdsn_dataselect_url)
167-
logger.info(
168-
'Connected to FDSN dataselect server: '
169-
f'{config.fdsn_dataselect_url}'
170-
)
166+
if config.event_data_path is not None:
167+
return
168+
config.dataselect_client = FDSNClient(config.fdsn_dataselect_url)
169+
logger.info(
170+
'Connected to FDSN dataselect server: '
171+
f'{config.fdsn_dataselect_url}'
172+
)
171173

172174

173175
def _connect_sds():

requake/config/utils.py

Lines changed: 27 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -195,36 +195,32 @@ def manage_uncaught_exception(exception):
195195
import scipy as sp
196196
import obspy
197197
import matplotlib
198-
sys.stderr.write("""
199-
# BEGIN TRACEBACK #############################################################
200-
""")
201-
sys.stderr.write('\n')
202-
traceback.print_exc()
203-
sys.stderr.write("""
204-
# END TRACEBACK ###############################################################
205-
""")
206-
sys.stderr.write("""
207-
208-
Congratulations, you've found a bug in Requake! 🐞
209-
210-
Please report it on https://github.com/SeismicSource/requake/issues
211-
or by email to [email protected].
212-
213-
Include the following information in your report:
214-
215-
""")
216-
sys.stderr.write(f' Requake version: {__version__}\n')
217-
sys.stderr.write(f' Python version: {sys.version}\n')
218-
sys.stderr.write(f' NumPy version: {np.__version__}\n')
219-
sys.stderr.write(f' SciPy version: {sp.__version__}\n')
220-
sys.stderr.write(f' ObsPy version: {obspy.__version__}\n')
221-
sys.stderr.write(f' Matplotlib version: {matplotlib.__version__}\n')
222-
sys.stderr.write(f' Platform: {sys.platform}\n')
223-
sys.stderr.write(f' Command line: {" ".join(sys.argv)}\n')
224-
sys.stderr.write(f' Error message: {str(exception)}\n')
225-
sys.stderr.write('\n')
198+
import pygments
199+
from pygments.lexers.python import PythonLexer
200+
from pygments.formatters.terminal import TerminalFormatter
201+
tb_str = ''.join(
202+
traceback.format_exception(
203+
type(exception), exception, exception.__traceback__))
204+
colored_tb = pygments.highlight(tb_str, PythonLexer(), TerminalFormatter())
226205
sys.stderr.write(
227-
'Also, please copy and paste the traceback above in your '
228-
'report.\n\n')
229-
sys.stderr.write('Thank you for your help!\n\n')
206+
f'\n# BEGIN TRACEBACK {"#" * 62}\n'
207+
f'\n{colored_tb}'
208+
f'\n# END TRACEBACK {"#" * 62}\n\n'
209+
"Congratulations, you've found a bug in Requake! 🐞\n\n"
210+
'Please report it on https://github.com/SeismicSource/requake/issues\n'
211+
'or by email to [email protected].\n\n'
212+
'Include the following information in your report:\n\n'
213+
f' Requake version: {__version__}\n'
214+
f' Python version: {sys.version}\n'
215+
f' NumPy version: {np.__version__}\n'
216+
f' SciPy version: {sp.__version__}\n'
217+
f' ObsPy version: {obspy.__version__}\n'
218+
f' Matplotlib version: {matplotlib.__version__}\n'
219+
f' Platform: {sys.platform}\n'
220+
f' Command line: {" ".join(sys.argv)}\n'
221+
f' Error message: {str(exception)}\n'
222+
'\n'
223+
'Also, please copy and paste the traceback above in your report.\n\n'
224+
'Thank you for your help!\n\n'
225+
)
230226
sys.exit(1)

requake/scan/scan_templates.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
FamilyNotFoundError
2020
)
2121
from ..waveforms import (
22-
get_waveform, cc_waveform_pair, get_arrivals,
22+
get_waveform_from_client, cc_waveform_pair, get_arrivals,
2323
NoWaveformError
2424
)
2525
from ..catalog import RequakeEvent, generate_evid
@@ -78,7 +78,7 @@ def _scan_family_template(template, catalog_file, t0, t1):
7878
tr = trace_cache[key]
7979
except KeyError:
8080
try:
81-
tr = get_waveform(trace_id, t0, t1)
81+
tr = get_waveform_from_client(trace_id, t0, t1)
8282
trace_cache[key] = tr
8383
except NoWaveformError as err:
8484
raise NoWaveformError(

requake/waveforms/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
(https://www.gnu.org/licenses/gpl-3.0-standalone.html)
1111
"""
1212
from .waveforms import ( # noqa
13-
get_waveform, get_event_waveform,
13+
get_waveform_from_client, get_event_waveform,
1414
get_waveform_pair, cc_waveform_pair,
1515
process_waveforms,
1616
align_pair, align_traces,

requake/waveforms/station_metadata.py

Lines changed: 76 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ def _download_metadata():
160160
)
161161

162162

163-
def get_traceid_coords(orig_time=None):
163+
def get_traceid_coords_old(orig_time=None):
164164
"""
165165
Get coordinates for the trace_ids specified in config file.
166166
@@ -177,13 +177,85 @@ def get_traceid_coords(orig_time=None):
177177
_download_metadata()
178178
traceid_coords = {}
179179
for trace_id in config.catalog_trace_id:
180+
net, sta, loc, chan = trace_id.split('.')
181+
net = net or '@@'
182+
_trace_id = f'{net}.{sta}.{loc}.{chan}'
180183
try:
181-
coords = config.inventory.get_coordinates(trace_id, orig_time)
182-
except Exception as err:
184+
coords = config.inventory.get_coordinates(_trace_id, orig_time)
185+
# pylint: disable=broad-except
186+
except Exception:
183187
# note: get_coordinaets raises a generic Exception
188+
# try again with empty channel code
189+
try:
190+
_trace_id = f'{net}.{sta}.{loc}.'
191+
coords = config.inventory.get_coordinates(_trace_id, orig_time)
192+
except Exception as err:
193+
raise MetadataMismatchError(
194+
f'Unable to find coordinates for trace {trace_id} '
195+
f'at time {orig_time}'
196+
) from err
197+
traceid_coords[trace_id] = coords
198+
return traceid_coords
199+
200+
201+
def _fetch_coordinates(net, sta, loc, chan, orig_time):
202+
"""
203+
Fetch coordinates for a trace_id at a given time.
204+
205+
Attempt to retrieve coordinates, first with full trace_id,
206+
then without channel.
207+
208+
:param net: network code
209+
:type net: str
210+
:param sta: station code
211+
:type sta: str
212+
:param loc: location code
213+
:type loc: str
214+
:param chan: channel code
215+
:type chan: str
216+
:param orig_time: origin time
217+
:type orig_time: obspy.UTCDateTime
218+
219+
:return: coordinates or None
220+
:rtype: dict
221+
"""
222+
for ch in [chan, '']:
223+
_trace_id = f'{net}.{sta}.{loc}.{ch}'
224+
try:
225+
return config.inventory.get_coordinates(_trace_id, orig_time)
226+
# pylint: disable=broad-except
227+
# note: get_coordinaets raises a generic Exception
228+
except Exception:
229+
# Try next option if it fails
230+
continue
231+
# If both attempts fail, return None
232+
return None
233+
234+
235+
def get_traceid_coords(orig_time=None):
236+
"""
237+
Get coordinates for the trace_ids specified in config file.
238+
239+
:param orig_time: origin time
240+
:type orig_time: obspy.UTCDateTime
241+
:return: a dictionary with trace_id as key and coordinates as value
242+
:rtype: dict
243+
244+
:raises MetadataMismatchError: if coordinates are not found
245+
"""
246+
if config.inventory is None:
247+
_read_station_metadata()
248+
if config.inventory is None:
249+
_download_metadata()
250+
traceid_coords = {}
251+
for trace_id in config.catalog_trace_id:
252+
net, sta, loc, chan = trace_id.split('.')
253+
net = net or '@@'
254+
coords = _fetch_coordinates(net, sta, loc, chan, orig_time)
255+
if coords is None:
184256
raise MetadataMismatchError(
185257
f'Unable to find coordinates for trace {trace_id} '
186258
f'at time {orig_time}'
187-
) from err
259+
)
188260
traceid_coords[trace_id] = coords
189261
return traceid_coords

0 commit comments

Comments
 (0)