Commit 9b2460cd authored by Sebastian Heimann's avatar Sebastian Heimann
Browse files

add ManualPickIFC and options to ease use of it

parent 548a58a8
...@@ -24,6 +24,14 @@ class Config(Object): ...@@ -24,6 +24,14 @@ class Config(Object):
String.T(), String.T(),
help='list of directories paths to search for data') help='list of directories paths to search for data')
events_path = String.T(
optional=True,
help='limit processing to time windows around given events')
event_time_window_factor = Float.T(
default=2.,
help='controls length of time windows for event-wise processing')
blacklist = List.T( blacklist = List.T(
String.T(), String.T(),
help='codes in the form NET.STA.LOC of receivers to be excluded') help='codes in the form NET.STA.LOC of receivers to be excluded')
...@@ -70,6 +78,7 @@ class Config(Object): ...@@ -70,6 +78,7 @@ class Config(Object):
Object.__init__(self, *args, **kwargs) Object.__init__(self, *args, **kwargs)
self._receivers = None self._receivers = None
self._grid = None self._grid = None
self._events = None
def get_receivers(self): def get_receivers(self):
'''Aggregate receivers from different sources.''' '''Aggregate receivers from different sources.'''
...@@ -86,6 +95,15 @@ class Config(Object): ...@@ -86,6 +95,15 @@ class Config(Object):
return self._receivers return self._receivers
def get_events(self):
if self.events_path is None:
return None
if self._events is None:
self._events = model.load_events(self.events_path)
return self._events
def get_grid(self): def get_grid(self):
'''Get grid or make default grid.''' '''Get grid or make default grid.'''
......
import sys
import os import os
import logging import logging
import os.path as op import os.path as op
...@@ -28,7 +27,8 @@ def scan( ...@@ -28,7 +27,8 @@ def scan(
os.unlink(config.detections_path) os.unlink(config.detections_path)
else: else:
raise common.LassieError( raise common.LassieError(
'detections file already exists: %s' % config.detections_path) 'detections file already exists: %s'
% config.detections_path)
util.ensuredirs(config.detections_path) util.ensuredirs(config.detections_path)
...@@ -37,7 +37,6 @@ def scan( ...@@ -37,7 +37,6 @@ def scan(
norm_map = gridmod.geometrical_normalization(grid, receivers) norm_map = gridmod.geometrical_normalization(grid, receivers)
for data_path in config.data_paths: for data_path in config.data_paths:
if not op.exists(data_path): if not op.exists(data_path):
raise common.LassieError( raise common.LassieError(
...@@ -79,154 +78,174 @@ def scan( ...@@ -79,154 +78,174 @@ def scan(
tmin = override_tmin or config.tmin tmin = override_tmin or config.tmin
tmax = override_tmax or config.tmax tmax = override_tmax or config.tmax
for trs in p.chopper(
tmin=tmin, tmax=tmax, tinc=tinc, tpad=tpad, events = config.get_events()
want_incomplete=False, twindows = []
trace_selector=lambda tr: tr.nslc_id[:3] in station_index): if events is not None:
for ev in events:
if not trs: if tmin <= ev.time <= tmax:
continue twindows.append((
ev.time - tshift_max * config.event_time_window_factor,
logger.info('processing time window %s - %s' % ( ev.time + tshift_max * config.event_time_window_factor))
util.time_to_str(trs[0].wmin),
util.time_to_str(trs[0].wmax))) else:
twindows.append((tmin, tmax))
wmin = trs[0].wmin
wmax = trs[0].wmax for tmin_win, tmax_win in twindows:
for trs in p.chopper(
frames = None tmin=tmin_win, tmax=tmax_win, tinc=tinc, tpad=tpad,
pdata = [] want_incomplete=False,
trs_debug = [] trace_selector=lambda tr: tr.nslc_id[:3] in station_index):
shift_maxs = []
for iifc, ifc in enumerate(ifcs): if not trs:
dataset = ifc.preprocess(trs, wmin, wmax, tshift_max)
if not dataset:
continue continue
nstations_selected = len(dataset) logger.info('processing time window %s - %s' % (
util.time_to_str(trs[0].wmin),
util.time_to_str(trs[0].wmax)))
nsls_selected, trs_selected = zip(*dataset) wmin = trs[0].wmin
wmax = trs[0].wmax
trs_debug.extend(trs + list(trs_selected)) frames = None
pdata = []
trs_debug = []
shift_maxs = []
for iifc, ifc in enumerate(ifcs):
dataset = ifc.preprocess(trs, wmin, wmax, tshift_max)
if not dataset:
continue
deltat_cf = trs_selected[0].deltat nstations_selected = len(dataset)
t0 = (wmin / deltat_cf) * deltat_cf nsls_selected, trs_selected = zip(*dataset)
istations_selected = num.array( trs_debug.extend(trs + list(trs_selected))
[station_index[nsl] for nsl in nsls_selected], dtype=num.int)
arrays = [tr.ydata.astype(num.float) for tr in trs_selected] deltat_cf = trs_selected[0].deltat
offsets = num.array( t0 = (wmin / deltat_cf) * deltat_cf
[int(round((tr.tmin-t0) / deltat_cf)) for tr in trs_selected],
dtype=num.int32)
w = num.array( istations_selected = num.array(
[station_weights.get(nsl, 1.0) for nsl in nsls_selected], [station_index[nsl] for nsl in nsls_selected],
dtype=num.float) dtype=num.int)
arrays = [tr.ydata.astype(num.float) for tr in trs_selected]
weights = num.ones((ngridpoints, nstations_selected)) offsets = num.array(
weights *= w[num.newaxis, :] [int(round((tr.tmin-t0) / deltat_cf))
weights *= ifc.weight for tr in trs_selected],
dtype=num.int32)
shift_table = shift_tables[iifc] w = num.array(
[station_weights.get(nsl, 1.0) for nsl in nsls_selected],
dtype=num.float)
shifts = -num.round( weights = num.ones((ngridpoints, nstations_selected))
shift_table[:, istations_selected] / weights *= w[num.newaxis, :]
deltat_cf).astype(num.int32) weights *= ifc.weight
pdata.append((list(trs_selected), shift_table, ifc)) shift_table = shift_tables[iifc]
iwmin = int(round((wmin-t0) / deltat_cf)) shifts = -num.round(
iwmax = int(round((wmax-t0) / deltat_cf)) shift_table[:, istations_selected] /
deltat_cf).astype(num.int32)
lengthout = iwmax - iwmin + 1 pdata.append((list(trs_selected), shift_table, ifc))
shift_maxs.append(num.max(-shifts) * deltat_cf) iwmin = int(round((wmin-t0) / deltat_cf))
iwmax = int(round((wmax-t0) / deltat_cf))
frames, ioff = parstack( lengthout = iwmax - iwmin + 1
arrays, offsets, shifts, weights, 0,
offsetout=iwmin,
lengthout=lengthout,
result=frames,
impl='openmp')
shift_max = max(shift_maxs) shift_maxs.append(num.max(-shifts) * deltat_cf)
if config.sharpness_normalization: frames, ioff = parstack(
frame_maxs = frames.max(axis=0) arrays, offsets, shifts, weights, 0,
frame_means = num.abs(frames).mean(axis=0) offsetout=iwmin,
frames *= (frame_maxs / frame_means)[num.newaxis, :] lengthout=lengthout,
frames *= norm_map[:, num.newaxis] result=frames,
impl='openmp')
frame_maxs = frames.max(axis=0) shift_max = max(shift_maxs)
tmin_frames = t0 + ioff * deltat_cf if config.sharpness_normalization:
frame_maxs = frames.max(axis=0)
frame_means = num.abs(frames).mean(axis=0)
frames *= (frame_maxs / frame_means)[num.newaxis, :]
frames *= norm_map[:, num.newaxis]
tr_stackmax = trace.Trace( frame_maxs = frames.max(axis=0)
'', 'SMAX', '', '',
tmin=tmin_frames,
deltat=deltat_cf,
ydata=frame_maxs)
trs_debug.append(tr_stackmax) tmin_frames = t0 + ioff * deltat_cf
# trace.snuffle(trs_debug) tr_stackmax = trace.Trace(
'', 'SMAX', '', '',
tmin=tmin_frames,
deltat=deltat_cf,
ydata=frame_maxs)
ydata_window = tr_stackmax.chop(wmin, wmax, inplace=False).get_ydata() trs_debug.append(tr_stackmax)
logger.info('CF stats: min %g, max %g, median %g' % ( # trace.snuffle(trs_debug)
num.min(ydata_window),
num.max(ydata_window),
num.median(ydata_window)))
tpeaks, apeaks = tr_stackmax.peaks( ydata_window = tr_stackmax.chop(
config.detector_threshold, shift_max + 1.0/fsmooth_min) wmin, wmax, inplace=False).get_ydata()
for (tpeak, apeak) in zip(tpeaks, apeaks): logger.info('CF stats: min %g, max %g, median %g' % (
if not (wmin <= tpeak and tpeak < wmax): num.min(ydata_window),
continue num.max(ydata_window),
num.median(ydata_window)))
tpeaks, apeaks = tr_stackmax.peaks(
config.detector_threshold, shift_max + 1.0/fsmooth_min)
for (tpeak, apeak) in zip(tpeaks, apeaks):
if not (wmin <= tpeak and tpeak < wmax):
continue
logger.info('detection: %s %g' % ( logger.info('detection: %s %g' % (
util.time_to_str(tpeak), util.time_to_str(tpeak),
apeak)) apeak))
iframe = int(round(((tpeak-t0) - ioff*deltat_cf) / deltat_cf)) iframe = int(round(((tpeak-t0) - ioff*deltat_cf) / deltat_cf))
frame = frames[:, iframe] frame = frames[:, iframe]
imax = num.argmax(frame) imax = num.argmax(frame)
latpeak, lonpeak, xpeak, ypeak, zpeak = grid.index_to_location(imax) latpeak, lonpeak, xpeak, ypeak, zpeak = \
grid.index_to_location(imax)
idetection += 1 idetection += 1
if config.detections_path: if config.detections_path:
f = open(config.detections_path, 'a') f = open(config.detections_path, 'a')
f.write('%06i %s %g %g %g %g %g %g\n' % ( f.write('%06i %s %g %g %g %g %g %g\n' % (
idetection, idetection,
util.time_to_str(tpeak, format='%Y-%m-%d %H:%M:%S.6FRAC'), util.time_to_str(
apeak, tpeak,
latpeak, lonpeak, xpeak, ypeak, zpeak)) format='%Y-%m-%d %H:%M:%S.6FRAC'),
apeak,
latpeak, lonpeak, xpeak, ypeak, zpeak))
f.close() f.close()
if show_detections: if show_detections:
fmin = min(ifc.fmin for ifc in ifcs) fmin = min(ifc.fmin for ifc in ifcs)
fmax = min(ifc.fmax for ifc in ifcs) fmax = min(ifc.fmax for ifc in ifcs)
plot.plot_detection( plot.plot_detection(
grid, receivers, frames, tmin_frames, grid, receivers, frames, tmin_frames,
deltat_cf, imax, iframe, fsmooth_min, xpeak, ypeak, zpeak, deltat_cf, imax, iframe, fsmooth_min, xpeak, ypeak,
tr_stackmax, tpeaks, apeaks, config.detector_threshold, zpeak,
pdata, trs, fmin, fmax, idetection, tr_stackmax, tpeaks, apeaks, config.detector_threshold,
grid_station_shift_max=shift_max, pdata, trs, fmin, fmax, idetection,
movie=show_movie) grid_station_shift_max=shift_max,
movie=show_movie)
if stop_after_first: if stop_after_first:
return return
tr_stackmax.chop(wmin, wmax) tr_stackmax.chop(wmin, wmax)
io.save([tr_stackmax], 'stackmax/trace_%(tmin)s.mseed') io.save([tr_stackmax], 'stackmax/trace_%(tmin)s.mseed')
__all__ = [ __all__ = [
......
...@@ -4,6 +4,7 @@ from collections import defaultdict ...@@ -4,6 +4,7 @@ from collections import defaultdict
import numpy as num import numpy as num
from pyrocko.guts import Object, String, Float, Bool, StringChoice from pyrocko.guts import Object, String, Float, Bool, StringChoice
from pyrocko import trace, autopick, util, model, gui_util from pyrocko import trace, autopick, util, model, gui_util
from pyrocko import marker as pmarker
from lassie import shifter, common, geo from lassie import shifter, common, geo
logger = logging.getLogger('lassie.ifc') logger = logging.getLogger('lassie.ifc')
...@@ -170,7 +171,8 @@ class OnsetIFC(IFC): ...@@ -170,7 +171,8 @@ class OnsetIFC(IFC):
sumtr.set_ydata(sumtr.get_ydata().astype(num.float32)) sumtr.set_ydata(sumtr.get_ydata().astype(num.float32))
autopick.recursive_stalta(swin, lwin, 1.0, 4.0, 3.0, sumtr) autopick.recursive_stalta(swin, lwin, 1.0, 4.0, 3.0, sumtr)
sumtr.shift(-(swin + n/2.*sumtr.deltat)) #sumtr.shift(-(swin + n/2.*sumtr.deltat))
sumtr.shift(-swin)
ntap = int(num.round(1./fsmooth / tr.deltat)) ntap = int(num.round(1./fsmooth / tr.deltat))
taper = num.hanning(ntap) taper = num.hanning(ntap)
...@@ -315,7 +317,7 @@ class TemplateMatchingIFC(IFC): ...@@ -315,7 +317,7 @@ class TemplateMatchingIFC(IFC):
c.shift(-c.tmin + b.tmin - (a.tmin - tref)) c.shift(-c.tmin + b.tmin - (a.tmin - tref))
c.meta = {'tabu': True} c.meta = {'tabu': True}
#c.set_codes(location='cc') # c.set_codes(location='cc')
if self.sum_square: if self.sum_square:
c.ydata = c.ydata**2 c.ydata = c.ydata**2
...@@ -334,6 +336,112 @@ class TemplateMatchingIFC(IFC): ...@@ -334,6 +336,112 @@ class TemplateMatchingIFC(IFC):
return dataset return dataset
class ManualPickIFC(IFC):
'''
An image function based on manual picks.
'''
fsmooth = Float.T(default=0.1)
picks_path = String.T()
picks_phasename = String.T()
def __init__(self, *args, **kwargs):
IFC.__init__(self, *args, **kwargs)
markers = pmarker.load_markers(self.picks_path)
nsl_to_index = {}
picked_index = []
picked_times = []
index = -1
for marker in markers:
if isinstance(marker, pmarker.PhaseMarker) \
and marker.get_phasename() == self.picks_phasename:
nsl = marker.one_nslc()[:3]
if nsl not in nsl_to_index:
index += 1
nsl_to_index[nsl] = index
ind = nsl_to_index[nsl]
picked_index.append(ind)
picked_times.append((marker.tmin + marker.tmax) * 0.5)
self._nsl_to_index = nsl_to_index
self._picked_index = num.array(picked_index, dtype=num.int64)
self._picked_times = num.array(picked_times, dtype=num.float)
def get_fsmooth(self):
return self.fsmooth
def preprocess(self, trs, wmin, wmax, tpad_new):
fsmooth = self.fsmooth
if not trs:
return []
deltat_cf = trs[0].deltat
while deltat_cf * 2 < 0.25 / self.fmin:
deltat_cf *= 2
mask = num.logical_and(
wmin <= self._picked_times,
wmax >= self._picked_times)
picked_times = self._picked_times[mask]
picked_index = self._picked_index[mask]
trs_filt = []
for orig_tr in trs:
tr = orig_tr.copy()
nsl = tr.nslc_id[:3]
try:
index = self._nsl_to_index[nsl]
ts = picked_times[picked_index == index]
its = (num.round((ts - tr.tmin)/ tr.deltat)).astype(num.int64)
its = its[num.logical_and(0 <= its, its < tr.data_len())]
ydata = num.zeros(tr.data_len())
ydata[its] = 1.0
tr.set_ydata(ydata)
trs_filt.append(tr)
except KeyError:
pass
trs_by_nsl = common.grouped_by(trs_filt, lambda tr: tr.nslc_id[:3])
dataset = []
for nsl in sorted(trs_by_nsl.keys()):
sumtr = None
sumn = 0
for tr in trs_by_nsl[nsl]:
if sumtr is None:
sumtr = tr.copy()
sumtr.set_codes(channel='CF')
sumn = 1
else:
sumtr.add(tr)
sumn += 1
sumtr.ydata /= sumn
ntap = int(num.round(1./fsmooth / tr.deltat))
taper = num.hanning(ntap)
sumtr.shift(-(ntap/2.*tr.deltat))
sumtr.set_ydata(
num.convolve(sumtr.get_ydata()/len(trs_by_nsl), taper))
sumtr.downsample_to(deltat_cf, snap=True, demean=False)
sumtr.chop(wmin - tpad_new, wmax + tpad_new)
if num.any(sumtr != 0.):
dataset.append((nsl, sumtr))
return dataset
__all__ = [ __all__ = [
'IFC', 'IFC',
'WavePacketIFC', 'WavePacketIFC',
......
...@@ -226,25 +226,25 @@ def plot_detection( ...@@ -226,25 +226,25 @@ def plot_detection(
dist + scalefactor*amp + ishifter*scalefactor*0.1, dist + scalefactor*amp + ishifter*scalefactor*0.1,
color=color) color=color)
for tr in trs_raw: for tr in trs_raw:
istation = station_index[tr.nslc_id[:3]] istation = station_index[tr.nslc_id[:3]]
dist = distances[imax, istation] dist = distances[imax, istation]
shift = shift_table[imax, istation] shift = shift_table[imax, istation]
tr = tr.copy() tr = tr.copy()
tr.highpass(4, fmin, demean=True) tr.highpass(4, fmin, demean=True)
tr.lowpass(4, fmax, demean=False) tr.lowpass(4, fmax, demean=False)
tr.chop( tr.chop(
tpeak_current - 0.5*tduration + shift_min, tpeak_current - 0.5*tduration + shift_min,
tpeak_current + 0.5*tduration + shift_max) tpeak_current + 0.5*tduration + shift_max)
t = tr.get_xdata() t = tr.get_xdata()
amp = tr.get_ydata().astype(num.float) amp = tr.get_ydata().astype(num.float)
amp = amp / num.max(num.abs(amp)) amp = amp / num.max(num.abs(amp))
axes4.plot(t-t0, dist + scalefactor*amp, color='black') axes4.plot(t-t0, dist + scalefactor*amp, color='black', alpha=0.5)
axes4.plot(shift, dist, '|', mew=2, mec=color, ms=10) axes4.plot(shift, dist, '|', mew=2, mec=color, ms=10)
nframes = frames.shape[1] nframes = frames.shape[1]
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment