def testFFTCorrelate(self): for na in range(1, 20): for nb in range(1, 20): a1 = num.random.random(na) a2 = num.random.random(nb) t1 = trace.Trace(station='t1', ydata=a1) t2 = trace.Trace(station='t2', ydata=a2) for mode in 'full', 'same', 'valid': c1 = trace.correlate(t1, t2, mode=mode) c2 = trace.correlate(t1, t2, mode=mode, use_fft=True) c1.set_station('c1') c2.set_station('c2') assert c1.get_ydata().size == c2.get_ydata().size d = num.abs(c1.get_ydata() - c2.get_ydata()) if not num.all(d < 1e-5): assert mode == 'same' assert abs(abs(c1.tmin - c2.tmin) - 1.0) < 1e-5 assert abs(abs(c1.tmax - c2.tmax) - 1.0) < 1e-5 tmin = max(c1.tmin, c2.tmin) tmax = min(c1.tmax, c2.tmax) c1.chop(tmin, tmax, include_last=True) c2.chop(tmin, tmax, include_last=True) d = num.abs(c1.get_ydata() - c2.get_ydata()) assert (num.all(d < 1e-5)) else: assert num.all(d < 1e-5)
def testFFTCorrelate(self): for na in range(1,20): for nb in range(1,20): a1 = num.random.random(na) a2 = num.random.random(nb) t1 = trace.Trace(station='t1', ydata=a1) t2 = trace.Trace(station='t2', ydata=a2) for mode in 'full', 'same', 'valid': c1 = trace.correlate(t1,t2, mode=mode) c2 = trace.correlate(t1,t2, mode=mode, use_fft=True) c1.set_station('c1') c2.set_station('c2') d = num.abs(c1.get_ydata() - c2.get_ydata()) if not num.all(d < 1e-5) : assert mode == 'same' assert abs(abs(c1.tmin-c2.tmin) - 1.0) < 1e-5 assert abs(abs(c1.tmax-c2.tmax) - 1.0) < 1e-5 tmin = max(c1.tmin, c2.tmin) tmax = min(c1.tmax, c2.tmax) c1.chop(tmin, tmax, include_last=True) c2.chop(tmin, tmax, include_last=True) d = num.abs(c1.get_ydata() - c2.get_ydata()) assert(num.all(d< 1e-5)) else: assert num.all(d < 1e-5)
def testCorrelateNormalization(self): ya = floats([1,2,1]) yb = floats([0,0,0,0,0,0,0,0,1,2,3,2,1]) a = trace.Trace(tmin=sometime, deltat=0.1, ydata=ya) b = trace.Trace(tmin=sometime, deltat=0.1, ydata=yb) c_ab = trace.correlate(a,b) c_ab2 = trace.correlate(a,b, normalization='gliding') c_ba = trace.correlate(b,a) c_ba2 = trace.correlate(b,a, normalization='gliding') assert numeq( c_ab.ydata, c_ba.ydata[::-1], 0.001 ) assert numeq( c_ab2.ydata, c_ba2.ydata[::-1], 0.001 )
def testCorrelateNormalization(self): ya = floats([1, 2, 1]) yb = floats([0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1]) a = trace.Trace(tmin=sometime, deltat=0.1, ydata=ya) b = trace.Trace(tmin=sometime, deltat=0.1, ydata=yb) c_ab = trace.correlate(a, b) c_ab2 = trace.correlate(a, b, normalization='gliding') c_ba = trace.correlate(b, a) c_ba2 = trace.correlate(b, a, normalization='gliding') assert numeq(c_ab.ydata, c_ba.ydata[::-1], 0.001) assert numeq(c_ab2.ydata, c_ba2.ydata[::-1], 0.001)
def call(self): self.pviewer = self.get_viewer() self.cleanup() pile = self.get_pile chopped_pile = [] for trac in self.chopper_selected_traces(marker_selector=self.marker_selector('dummy')): for trac_i in trac: trac_i.copy() trac_i.set_location("rot") chopped_pile.append(trac_i) self.add_traces(chopped_pile) AllRotatedTraces = RotateAllTraces(self.deg, chopped_pile) correlationStatVal={} for deg in self.deg: for stationPair in getPairStationTool(AllRotatedTraces[deg]): try: correlationStatVal[stationPair[0].station].append([deg, correlate(stationPair[0], stationPair[1])]) except KeyError: correlationStatVal[stationPair[0].station]=[] printFormattedOutput(correlationStatVal)
def testCorrelate(self): for la, lb, mode, res in [([0, 1, .5, 0, 0], [0, 0, 0, 1, 0], 'same', 0.3), ([0, 1, .5, 0, 0, 0], [0, 1, 0], 'valid', 0.1), ([0, 1, .5], [0, 0, 0, 1, 0, 0], 'full', 0.3)]: for ia in range(5): for ib in range(5): ya = floats(la + [0] * ia) yb = floats(lb + [0] * ib) a = trace.Trace(tmin=10., deltat=0.1, ydata=ya) b = trace.Trace(tmin=10.1, deltat=0.1, ydata=yb) c = trace.correlate(a, b, mode=mode) if not numeq(c.max(), [res, 1.], 0.0001): print print mode print len(ya), ya print len(yb), yb print c.ydata, c.max()
def preprocess(self, trs, wmin, wmax, tpad_new, deltat_cf): tmin_masters = min(tr.tmin for tr in self.masters.values()) tmax_masters = max(tr.tmax for tr in self.masters.values()) tmaster = tmax_masters - tmin_masters tref = tmin_masters nsl_to_traces = defaultdict(list) for orig_b in trs: b = orig_b.copy() nslc = b.nslc_id a = self.masters.get(nslc, False) if not a: continue if self.downsample_rate is not None: downsample(b, 1./self.downsample_rate) b.highpass(4, self.fmin, demean=False) b.lowpass(4, self.fmax, demean=False) smin = round((wmin - tmaster) / b.deltat) * b.deltat smax = round((wmax + tmaster) / b.deltat) * b.deltat b.chop(smin, smax) normalization = self.normalization if normalization == 'off': normalization = None c = trace.correlate( a, b, mode='valid', normalization=normalization, use_fft=self.use_fft) c.shift(-c.tmin + b.tmin - (a.tmin - tref)) c.meta = {'tabu': True} if self.sum_square: c.ydata = c.ydata**2 c.chop(wmin - tpad_new, wmax + tpad_new) nsl_to_traces[nslc[:3]].append(c) dataset = [] for nsl, cs in nsl_to_traces.items(): csum = cs[0] for c in cs[1:]: csum.add(c) dataset.append((nsl, csum)) return dataset
def testCorrelate(self): for la, lb, mode, res in [ ([0, 1, .5, 0, 0], [0, 0, 0, 1, 0], 'same', 0.3), ([0, 1, .5, 0, 0, 0], [0, 1, 0], 'valid', 0.1), ([0, 1, .5], [0, 0, 0, 1, 0, 0], 'full', 0.3)]: for ia in range(5): for ib in range(5): ya = floats(la + [0] * ia) yb = floats(lb + [0] * ib) a = trace.Trace(tmin=10., deltat=0.1, ydata=ya) b = trace.Trace(tmin=10.1, deltat=0.1, ydata=yb) c = trace.correlate(a, b, mode=mode) assert numeq(c.max(), [res, 1.], 0.0001)
def testCorrelate(self): for la, lb, mode, res in [ ([0, 1, .5, 0, 0 ], [0, 0, 0, 1, 0 ], 'same', 0.3), ([0, 1, .5, 0, 0, 0 ], [0, 0, 0, 1, 0, 0 ], 'same', 0.3), ([0, 1, .5, 0, 0 ], [0, 0, 0, 1, 0, 0 ], 'same', 0.3), ([0, 1, .5, 0 ], [0, 0, 0, 1, 0, 0 ], 'same', 0.3), ([0, 1, .5, 0, 0, 0 ], [0, 0, 0, 1, 0 ], 'same', 0.3), ([0, 1, .5, 0, 0, 0 ], [0, 0, 0, 1, ], 'same', 0.3), ([0, 1, .5], [0, 0, 0, 1, 0, 0 ], 'valid', 0.3), ([0, 1, .5, 0], [0, 0, 0, 1, 0, 0 ], 'valid', 0.3), ([0, 1, .5, 0, 0, 0 ], [0, 1, 0 ], 'valid', 0.1), ([0, 1, .5, 0, 0, 0 ], [0, 1, 0, 0 ], 'valid', 0.1), ([0, 1, .5], [0, 0, 0, 1, 0, 0 ], 'full', 0.3), ([0, 1, .5, 0, 0, 0 ], [0, 1, 0 ], 'full', 0.1), ([0, 1, .5, 0], [0, 0, 0, 1, 0, 0 ], 'full', 0.3), ([0, 1, .5, 0, 0, 0 ], [0, 1, 0, 0 ], 'full', 0.1)]: for ia in range(4): for ib in range(4): ya = floats(la + [ 0 ] * ia) yb = floats(lb + [ 0 ] * ib) a = trace.Trace(tmin=10., deltat=0.1, ydata=ya) b = trace.Trace(tmin=10.1, deltat=0.1, ydata=yb) c = trace.correlate(a,b, mode=mode) if mode == 'valid' and c.ydata.size <=2: continue if not numeq(c.max(), [res, 1.], 0.0001): print mode print len(ya), ya print len(yb), yb print c.ydata, c.max() assert False
def call(self): self.cleanup() viewer = self.get_viewer() events = [m.get_event() for m in self.get_selected_event_markers()] for iev, ev in enumerate(events): ev.name = '%05i' % iev show_arrivals = False filters = [] for ident in ['high', 'low']: val = getattr(self, ident) if val != None: filters.append(trace.ButterworthResponse(corner=float(val), order=4, type=ident)) stations = self.get_stations() traces = list(self.chopper_selected_traces(fallback=True, trace_selector= viewer.trace_selector, load_data=False)) traces = [tr for trs in traces for tr in trs ] visible_nslcs = [tr.nslc_id for tr in traces] stations = [x for x in stations if util.match_nslcs( "%s.%s.%s.*" % x.nsl(), visible_nslcs)] # TODO option to choose other models mod = cake.load_model() nevents = len(events) pile = self.get_pile() targets = make_targets(pile, stations) if len(targets)==0: self.fail("No station available") ntargets = len(targets) self.cc = num.zeros((ntargets, nevents, nevents), dtype=num.float) self.similarity_matrix = SimilarityMatrix(targets=targets, events=events, filters=filters, padding=float(self.tpad), windowing_method=self.time_window_choice, vmax=float(self.vmax), vmin=float(self.vmin)) similarities = [] if self.save_traces : figure_dir = self.input_directory(caption='Select directory to store images') for itarget, target in enumerate(targets): print((itarget+1.)/float(ntargets)) ok_filtered = [] markers = [] for iev, ev in enumerate(events): dist = target.distance_to(ev) if self.time_window_choice=='vmin/vmax': tmin = ev.time + dist / self.vmax - self.tpad tmax = ev.time + dist / self.vmin + self.tpad elif self.time_window_choice=='P-phase': d = dist*cake.m2d z = ev.depth t = self.phase_cache.get((mod, d, z), False) if not t: rays = mod.arrivals( phases=[cake.PhaseDef(x) for x in 'p P'.split()], distances=[d], zstart=z) t = rays[0].t self.phase_cache[(mod, d, z)] = t tmin = ev.time + t - self.tpad * 0.1 tmax = ev.time + t + self.tpad * 0.9 trs = pile.chopper(tmin=tmin, tmax=tmax, trace_selector=viewer.trace_selector, want_incomplete=False) tr = [t for trss in trs for t in trss if t.nslc_id==target.codes] if len(tr)==0: continue elif len(tr)==1: tr = tr[0] else: self.fail('Something went wrong') if self.dt_wanted: tr.downsample_to(self.dt_wanted) tr2 = tr.copy() for f in filters: tr2 = tr2.transfer(transfer_function=f) tr2.chop(tmin, tmax) tr2.set_codes(location=ev.name+'f') tr.chop(tmin, tmax) tr.set_codes(location=ev.name+'r') ok_filtered.append((iev, ev, tr2)) ok = ok_filtered while ok: (ia, a_ev, a_tr) = ok.pop() for (ib, b_ev, b_tr) in ok: relamp = 0.0 if a_tr is not None and b_tr is not None: c_tr = trace.correlate(a_tr, b_tr, mode='full', normalization='normal') t_center = c_tr.tmin+(c_tr.tmax-c_tr.tmin)/2. c_tr_chopped = c_tr.chop(t_center-self.tdist, t_center+self.tdist, inplace=False) t_mini, v_mini = c_tr_chopped.min() t_maxi, v_maxi = c_tr_chopped.max() b_tr_shifted = b_tr.copy() if abs(v_mini) > abs(v_maxi): v_cc = v_mini time_lag = -t_mini else: time_lag = -t_maxi v_cc = v_maxi self.cc[itarget, ia, ib] = v_cc b_tr_shifted.shift(time_lag) if self.cc[itarget, ia, ib] != 0.0: tmin = max(a_tr.tmin, b_tr_shifted.tmin) tmax = min(a_tr.tmax, b_tr_shifted.tmax) try: a_tr_chopped = a_tr.chop(tmin, tmax, inplace=False) b_tr_chopped = b_tr_shifted.chop(tmin, tmax) except trace.NoData: logger.warn('NoData %s'%a_tr_chopped) continue ya = a_tr_chopped.ydata yb = b_tr_chopped.ydata relamp = num.sum(ya*yb) / num.sum(ya**2) if self.save_traces: fig, axes = plt.subplots(3,1) fig.suptitle('.'.join(target.codes)) axes[0].plot(a_tr_chopped.get_xdata(), a_tr_chopped.get_ydata()) axes[0].text(0, 1, "id: %s, time: %s" %(a_ev.name, util.time_to_str(a_ev.time)), transform=axes[0].transAxes, verticalalignment='top', horizontalalignment='left') axes[1].plot(b_tr_chopped.get_xdata(), b_tr_chopped.get_ydata()) axes[1].text(0, 1, "id: %s, time: %s" %(b_ev.name, util.time_to_str(b_ev.time)), transform=axes[1].transAxes, verticalalignment='top', horizontalalignment='left') axes[2].plot(c_tr.get_xdata(), c_tr.get_ydata()) axes[2].text(0, 1, 'cc_max: %1.4f' % v_cc, transform=axes[2].transAxes, verticalalignment='top', horizontalalignment='left') fn = op.join(figure_dir, 'cc_T%s.E%s.E%s.png' % (itarget, ia, ib)) fig.savefig(fn, pad_inches=0.1, bbox_inches='tight', tight_layout=True) sim = Similarity( ievent=ia, jevent=ib, itarget=itarget, cross_correlation=float(self.cc[itarget, ia, ib]), relative_amplitude=float(relamp), time_lag=float(-time_lag)) similarities.append(sim) if self.show_results: for itarget, target in enumerate(targets): if not num.any(self.cc[itarget]): continue fig = self.pylab(get='figure') fig.suptitle('.'.join(target.codes)) axes = fig.add_subplot(111) axes.set_xlabel('Event number') axes.set_ylabel('Event number') mesh = axes.pcolormesh(self.cc[itarget,:,:], cmap='RdBu', vmin=-1.0, vmax=1.0) cb = fig.colorbar(mesh, ax=axes) cb.set_label('Max correlation coefficient') fig.canvas.draw() self.similarity_matrix.similarities = similarities self.similarity_matrix.validate()
def call(self): self.cleanup() viewer = self.get_viewer() events = [m.get_event() for m in self.get_selected_event_markers()] for iev, ev in enumerate(events): ev.name = '%05i' % iev show_arrivals = False filters = [] for ident in ['high', 'low']: val = getattr(self, ident) if val != None: filters.append(trace.ButterworthResponse(corner=float(val), order=4, type=ident)) stations = self.get_stations() traces = list(self.chopper_selected_traces(fallback=True, trace_selector= viewer.trace_selector, load_data=False)) traces = [tr for trs in traces for tr in trs ] visible_nslcs = [tr.nslc_id for tr in traces] stations = filter(lambda s: util.match_nslcs("%s.%s.%s.*" % s.nsl(), visible_nslcs), stations) # TODO option to choose other models mod = cake.load_model() nevents = len(events) pile = self.get_pile() targets = make_targets(pile, stations) if len(targets)==0: self.fail("No station available") ntargets = len(targets) self.cc = num.zeros((ntargets, nevents, nevents), dtype=num.float) self.similarity_matrix = SimilarityMatrix(targets=targets, events=events, filters=filters, padding=float(self.tpad), windowing_method=self.time_window_choice, vmax=float(self.vmax), vmin=float(self.vmin)) similarities = [] trs2add = [] if self.save_traces : figure_dir = self.input_directory(caption='Select directory to store images') for itarget, target in enumerate(targets): print (itarget+1.)/float(ntargets) ok_filtered = [] markers = [] for iev, ev in enumerate(events): dist = target.distance_to(ev) if self.time_window_choice=='vmin/vmax': tmin = ev.time + dist / self.vmax - self.tpad tmax = ev.time + dist / self.vmin + self.tpad elif self.time_window_choice=='P-phase': d = dist*cake.m2d z = ev.depth t = self.phase_cache.get((mod, d, z), False) if not t: rays = mod.arrivals( phases=[cake.PhaseDef(x) for x in 'p P'.split()], distances=[d], zstart=z) t = rays[0].t self.phase_cache[(mod, d, z)] = t tmin = ev.time + t - self.tpad * 0.1 tmax = ev.time + t + self.tpad * 0.9 trs = pile.chopper(tmin=tmin, tmax=tmax, trace_selector=viewer.trace_selector, want_incomplete=False) tr = [t for trss in trs for t in trss if t.nslc_id==target.codes] if len(tr)==0: continue elif len(tr)==1: tr = tr[0] else: self.fail('Something went wrong') if self.dt_wanted: tr.downsample_to(self.dt_wanted) tr2 = tr.copy() for f in filters: tr2 = tr2.transfer(transfer_function=f) tr2.chop(tmin, tmax) tr2.set_codes(location=ev.name+'f') tr.chop(tmin, tmax) tr.set_codes(location=ev.name+'r') ok_filtered.append((iev, ev, tr2)) ok = ok_filtered while ok: (ia, a_ev, a_tr) = ok.pop() for (ib, b_ev, b_tr) in ok: relamp = 0.0 if a_tr is not None and b_tr is not None: c_tr = trace.correlate(a_tr, b_tr, mode='full', normalization='normal') t_center = c_tr.tmin+(c_tr.tmax-c_tr.tmin)/2. c_tr_chopped = c_tr.chop(t_center-self.tdist, t_center+self.tdist, inplace=False) t_mini, v_mini = c_tr_chopped.min() t_maxi, v_maxi = c_tr_chopped.max() b_tr_shifted = b_tr.copy() a_tr_shifted = a_tr.copy() if abs(v_mini) > abs(v_maxi): v_cc = v_mini time_lag = -t_mini else: time_lag = -t_maxi v_cc = v_maxi self.cc[itarget, ia, ib] = v_cc b_tr_shifted.shift(time_lag) if self.cc[itarget, ia, ib] != 0.0: tmin = max(a_tr.tmin, b_tr_shifted.tmin) tmax = min(a_tr.tmax, b_tr_shifted.tmax) try: a_tr_chopped = a_tr.chop(tmin, tmax, inplace=False) b_tr_chopped = b_tr_shifted.chop(tmin, tmax) except trace.NoData: logger.warn('NoData %s'%a_tr_chopped) continue ya = a_tr_chopped.ydata yb = b_tr_chopped.ydata relamp = num.sum(ya*yb) / num.sum(ya**2) if self.save_traces: fig, axes = plt.subplots(3,1) fig.suptitle('.'.join(target.codes)) axes[0].plot(a_tr_chopped.get_xdata(), a_tr_chopped.get_ydata()) axes[0].text(0, 1, "id: %s, time: %s" %(a_ev.name, util.time_to_str(a_ev.time)), transform=axes[0].transAxes, verticalalignment='top', horizontalalignment='left') axes[1].plot(b_tr_chopped.get_xdata(), b_tr_chopped.get_ydata()) axes[1].text(0, 1, "id: %s, time: %s" %(b_ev.name, util.time_to_str(b_ev.time)), transform=axes[1].transAxes, verticalalignment='top', horizontalalignment='left') axes[2].plot(c_tr.get_xdata(), c_tr.get_ydata()) axes[2].text(0, 1, 'cc_max: %1.4f' % v_cc, transform=axes[2].transAxes, verticalalignment='top', horizontalalignment='left') fn = op.join(figure_dir, 'cc_T%s.E%s.E%s.png' % (itarget, ia, ib)) fig.savefig(fn, pad_inches=0.1, bbox_inches='tight', tight_layout=True) sim = Similarity( ievent=ia, jevent=ib, itarget=itarget, cross_correlation=float(self.cc[itarget, ia, ib]), relative_amplitude=float(relamp), time_lag=float(-time_lag)) similarities.append(sim) if self.show_results: for itarget, target in enumerate(targets): if not num.any(self.cc[itarget]): continue fig = self.pylab(get='figure') fig.suptitle('.'.join(target.codes)) axes = fig.add_subplot(111) axes.set_xlabel('Event number') axes.set_ylabel('Event number') mesh = axes.pcolormesh(self.cc[itarget,:,:], cmap='RdBu', vmin=-1.0, vmax=1.0) cb = fig.colorbar(mesh, ax=axes) cb.set_label('Max correlation coefficient') fig.canvas.draw() self.similarity_matrix.similarities = similarities self.similarity_matrix.validate()
def call(self): self.cleanup() viewer = self.get_viewer() event = viewer.get_active_event() stations = self.get_stations() for s in stations: print(s.nsl()) nsl_to_station = dict((s.nsl(), s) for s in stations) if event is None: self.error('No active event set.') markers = self.get_selected_markers() if len(markers) != 1: self.error('Exactly one marker must be selected.') marker = markers[0] try: nslc = marker.one_nslc() except pmarker.MarkerOneNSLCRequired: self.error('Marker must be picked on a single trace.') marker_station = nsl_to_station[nslc[:3]] mod = cake.load_model() def traveltime(station): dist = event.distance_to(station) arrivals = mod.arrivals(zstart=event.depth, zstop=0., distances=[dist * cake.m2d], phases=[cake.PhaseDef(self.phasename)]) if not arrivals: raise NoArrival() return arrivals[0].t try: tt_marker_station = traveltime(marker_station) except NoArrival: self.error('Selected phase does not arrive at station.') nsl_to_delay = {} for station in stations: nsl_to_delay[station.nsl()] = \ traveltime(station) - tt_marker_station pile = self.get_pile() nsl_to_traces = {} nsl_to_tspan = {} fs = [f for f in [viewer.lowpass, viewer.highpass] if f is not None] if fs: tpad = 2.0 / min(fs) else: tpad = 0.0 deltats = set() for nsl in nsl_to_delay.keys(): delay = nsl_to_delay[nsl] tmin = marker.tmin + delay tmax = marker.tmax + delay nsl_to_tspan[nsl] = (tmin, tmax) trs = pile.all(tmin=tmin, tmax=tmax, tpad=tpad, trace_selector=lambda tr: tr.nslc_id[:3] == nsl, want_incomplete=False) for tr in trs: if viewer.lowpass is not None: tr.lowpass(4, viewer.lowpass) if viewer.highpass is not None: tr.highpass(4, viewer.highpass) tr.chop(tr.wmin, tr.wmax) deltats.add(tr.deltat) if trs: nsl_to_traces[nsl] = trs if len(deltats) != 1: self.error('All traces must have same sampling rate.') # add markers for nsl in nsl_to_traces.keys(): tmin, tmax = nsl_to_tspan[nsl] for tr in nsl_to_traces[nsl]: mark = PhaseMarker([tr.nslc_id], tmin=tmin, tmax=tmax, kind=1, phasename=self.phasename) self.add_marker(mark) # cross correlations nsls = sorted(list(nsl_to_traces.keys())) pair_corrs = [] for nsl_a in nsls: trs_a = nsl_to_traces[nsl_a] if self.channels_relamp == 'All': comps = sorted(set([tr.channel[-1] for tr in trs_a])) else: comps = [c.strip() for c in self.channels_relamp.split(',')] for nsl_b in nsls: trs_b = nsl_to_traces[nsl_b] for comp in comps: try: tr_a = get_trace(trs_a, lambda tr: tr.channel.endswith(comp)) tr_b = get_trace(trs_b, lambda tr: tr.channel.endswith(comp)) except NotFound: continue if tr_a is tr_b: continue tr_cor = trace.correlate(tr_a, tr_b, mode='full', normalization='normal') delaymax, ccmax = tr_cor.max() delaymin, ccmin = tr_cor.min() delay_syn = nsl_to_delay[nsl_b] - nsl_to_delay[nsl_a] if abs(ccmin) < abs(ccmax): delay = delaymax ccabsmax = abs(ccmax) ccsignedmax = ccmax else: delay = delaymin ccabsmax = abs(ccmin) ccsignedmax = ccmin tr_b_shifted = tr_b.copy() tr_b_shifted.shift(-delay) tmin_com = max(tr_b_shifted.tmin, tr_a.tmin) tmax_com = min(tr_b_shifted.tmax, tr_a.tmax) tr_a_chopped = tr_a.chop(tmin_com, tmax_com, inplace=False) tr_b_chopped = tr_b_shifted.chop(tmin_com, tmax_com, inplace=False) ya = tr_a_chopped.ydata yb = tr_b_chopped.ydata relamp1 = num.sum(ya * yb) / num.sum(yb**2) relamp2 = num.sum(ya * yb) / num.sum(ya**2) if nsl_a[1] == 'LYKK': print(ccabsmax, relamp1, relamp2, abs((relamp1 / (1.0 / relamp2) - 1.0))) if ccabsmax < self.cc_min: continue if abs((relamp1 / (1.0 / relamp2) - 1.0)) > 0.2: continue relamp = (relamp1 + 1. / relamp2) * 0.5 pair_corrs.append((tr_a.nslc_id, tr_b.nslc_id, ccsignedmax, relamp, delay, delay_syn)) nslc_to_relamp = invert_relative_amplitudes(pair_corrs) self._nslc_to_relamp = nslc_to_relamp nsl_to_xy = {} for nsl in nsl_to_traces.keys(): trs = nsl_to_traces[nsl] try: cc = [c.strip() for c in self.channels_polar.split(',')] tr_y, tr_x = [ get_trace(trs, lambda tr: tr.channel.endswith(c)) for c in cc ] x = tr_x.get_ydata() y = tr_y.get_ydata() nsl_to_xy[nsl] = (x, y) except NotFound: pass nsls = sorted(list(nsl_to_xy.keys())) n = len(nsls) xs_l = [nsl_to_xy[nsl][0] for nsl in nsls] ys_l = [nsl_to_xy[nsl][1] for nsl in nsls] nsamp = min(min(x.size for x in xs_l), min(y.size for y in ys_l)) xs = num.vstack(x[:nsamp] for x in xs_l) ys = num.vstack(y[:nsamp] for y in ys_l) amps = num.sqrt(xs**2 + ys**2) amp_maxs = num.max(amps, axis=1) xs = xs / amp_maxs[:, num.newaxis] ys = ys / amp_maxs[:, num.newaxis] nphi = 73 phis = num.linspace(-180., 180., nphi) d = num.zeros((n, n, nphi)) for ia in range(n): for iphi, phi in enumerate(phis): x = xs[ia, :] y = ys[ia, :] xrot = num.cos(phi * d2r) * x + num.sin(phi * d2r) * y yrot = -num.sin(phi * d2r) * x + num.cos(phi * d2r) * y d[ia, :, iphi] = num.sqrt( num.sum((xrot[num.newaxis, :] - xs)**2 + (yrot[num.newaxis, :] - ys)**2, axis=1)) imins = num.argmin(d, axis=2) dmins = num.min(d, axis=2) dmin_median = num.median(dmins) phimins = phis[imins] nsl_to_rot = {} for nsl in nsls: nsl_to_rot[nsl] = 0. failed = set() for i in range(n): mean_min_error = num.mean(dmins[i, :] / dmin_median) print(mean_min_error, nsls[i]) if mean_min_error > 3.0: failed.add(nsls[i]) while True: ia_worst = num.argmax(num.mean(num.abs(phimins), axis=1)) phimod = ((phis[num.newaxis, :] + phimins[ia_worst, :, num.newaxis] + 180.) % 360.) - 180. phirot = phis[num.argmin(num.mean(num.abs(phimod), axis=0))] if abs(phirot) < 10.: break nsl = nsls[ia_worst] mean_min_error = num.mean(dmins[ia_worst, :] / dmin_median) phimins[ia_worst, :] = ( (phimins[ia_worst, :] + phirot) + 180.) % 360. - 180. phimins[:, ia_worst] = ( (phimins[:, ia_worst] - phirot) + 180.) % 360. - 180. if nsl not in failed: print('%-20s %8.0f' % ('.'.join(nsl), phirot)) nsl_to_rot[nsl] += phirot fframe = self.figure_frame() fig = fframe.gcf() fig.clf() if n == 0: self.error('No matching traces found.') ncols = 1 while ncols**2 < n: ncols += 1 nrows = ncols axes = fig.add_subplot(1, 2, 1, aspect=1.0) axes.axison = False axes.set_xlim(-0.05 - ncols, ncols + 0.05) axes.set_ylim(-0.05 - nrows, nrows + 0.05) axes.set_title('Event: %s, Phase: %s' % (event.name, self.phasename)) for insl, nsl in enumerate(nsls): irow = insl // ncols icol = insl % ncols trs = nsl_to_traces[nsl] try: x, y = nsl_to_xy[nsl] cc = [c.strip() for c in self.channels_polar.split(',')] tr_y, tr_x = [ get_trace(trs, lambda tr: tr.channel.endswith(c)) for c in cc ] xpos = icol * 2 - ncols + 1 ypos = -irow * 2 + nrows - 1 x = tr_x.get_ydata() y = tr_y.get_ydata() a = num.sqrt(x**2 + y**2) amax = num.max(a) phi = nsl_to_rot[nsl] color = 'black' if num.abs(phi) > 0: color = mpl_color('chocolate2') if num.abs(phi) > 30: color = mpl_color('orange2') if nsl in failed: color = mpl_color('scarletred2') axes.plot(x / amax + xpos, y / amax + ypos, color=color, alpha=0.7) if nsl not in failed: xrot = num.cos(phi * d2r) * x - num.sin(phi * d2r) * y yrot = num.sin(phi * d2r) * x + num.cos(phi * d2r) * y axes.plot(xrot / amax + xpos, yrot / amax + ypos, color='black', alpha=0.5) # axes.plot( # [xpos, num.sin(phi*d2r) + xpos], # [ypos, num.cos(phi*d2r) + ypos], # color=color, alpha=0.5) axes.annotate('.'.join(_ for _ in nsl if _), xy=(icol * 2 - ncols + 1, -irow * 2 + nrows - 2), xycoords='data', xytext=(0, 0), textcoords='offset points', verticalalignment='center', horizontalalignment='center', rotation=0.) except NotFound: pass axes = fig.add_subplot(1, 2, 2) nslcs = sorted(nslc_to_relamp.keys()) pdata = [] for inslc, nslc in enumerate(nslcs): nsl = nslc[:3] cha = nslc[3] tr = get_trace(nsl_to_traces[nsl], lambda tr: tr.channel == cha).copy() tr.shift(-(event.time + tt_marker_station + nsl_to_delay[nsl])) relamp = nslc_to_relamp[nslc] tr.ydata /= relamp color = 'black' if abs(num.log10(relamp)) > num.log10(1.1): color = mpl_color('chocolate2') if abs(num.log10(relamp)) > num.log10(2.0): color = mpl_color('orange2') if abs(num.log10(relamp)) > num.log10(10.0): color = mpl_color('scarletred2') pdata.append((tr, relamp, color, inslc, nslc)) ranges = trace.minmax([aa[0] for aa in pdata], lambda tr: None) ymin, ymax = ranges[None] yabsmax = max(abs(ymin), abs(ymax)) for (tr, relamp, color, inslc, nslc) in pdata: axes.plot(tr.get_xdata(), inslc + tr.get_ydata() / yabsmax, color=color) axes.annotate('.'.join(_ for _ in nslc if _), xy=(0, inslc), xycoords=('axes fraction', 'data'), xytext=(-5, 0), textcoords='offset points', verticalalignment='center', horizontalalignment='right', rotation=0., color=color) axes.annotate('x %g' % (1.0 / relamp), xy=(1., inslc), xycoords=('axes fraction', 'data'), xytext=(+5, 0), textcoords='offset points', verticalalignment='center', horizontalalignment='left', rotation=0., color=color) axes.get_yaxis().set_visible(False) for which in ['top', 'right', 'left']: axes.spines[which].set_visible(False) axes.set_xlabel('Time [s]') fframe.draw()
def call(self): '''Main work routine of the snuffling.''' self.cleanup() period_highpass = 1./self.corner_highpass tpad = period_highpass try: viewer = self.get_viewer() markers = viewer.selected_markers() if not markers: return if len(markers) != 1: return marker = markers[0] master_tmin, master_tmax = marker.tmin, marker.tmax if master_tmin >= master_tmax: return except NoViewerSet: viewer = None master_tmin, master_tmax = self.master_tmin, self.master_tmax pile = self.get_pile() masters = {} for tr in pile.all(tmin=master_tmin, tmax=master_tmax, tpad=tpad): if self.downsample is not None: tr.downsample_to(1./self.downsample) tr.highpass(4, self.corner_highpass) tr.lowpass(4, self.corner_lowpass) tr.chop(tr.wmin, tr.wmax) masters[tr.nslc_id] = tr if self.apply_to_all: tmin, tmax = pile.get_tmin()+tpad, pile.get_tmax() else: tmin, tmax = self.get_viewer().get_time_range() tmaster = master_tmax-master_tmin tinc = min(20*tmaster, max(tmaster, tmax-tmin)) for traces in pile.chopper(tmin=tmin, tmax=tmax, tinc=tinc, tpad=tmaster+tpad, want_incomplete=False): scc = None sccn = 0 for b in traces: nslc = b.nslc_id if nslc in masters: a = masters[nslc] if self.downsample is not None: b.downsample_to(1./self.downsample) b.highpass(4, self.corner_highpass) tr.lowpass(4, self.corner_lowpass) normalization = {'Off': None, 'Normal': 'normal', 'Gliding': 'gliding'}[self.normalization] c = trace.correlate(a,b, mode='valid', normalization=normalization) c.shift(-c.tmin + b.tmin) c.meta = { 'tabu' : True } if scc is None: scc = c.copy() scc.wmin = b.wmin scc.wmax = b.wmax scc.set_codes(network='', station='Sum Cross Correlation', location='', channel='') sccn = 1 else: scc.add(c) sccn += 1 if scc is not None: scc.ydata /= sccn scc.chop(scc.wmin, scc.wmax) markers = [] for t, a in zip(*scc.peaks(self.threshold, tsearch=2./self.corner_highpass)): m = EventMarker(model.Event(time=t, lat=0., lon=0., name='Event(%.2g)' % a)) markers.append(m) if viewer: self.add_traces([scc]) self.add_markers(markers) else: io.save([scc], self.out_path, format='from_extension')
def call(self): self.cleanup() viewer = self.get_viewer() master = viewer.get_active_event() if master is None: self.fail('no master event selected') stations = list(viewer.stations.values()) stations.sort(key=lambda s: (s.network, s.station)) if not stations: self.fail('no station information available') # gather events to be processed events = [] for m in viewer.markers: if isinstance(m, EventMarker): if m.kind == 0: events.append(m.get_event()) events.sort(key=lambda ev: ev.time) event_to_number = {} for iev, ev in enumerate(events): event_to_number[ev] = iev if self.model_select.startswith('Global'): model_key = 'global' else: model_key = master.lat, master.lon if model_key != self.model_key: if self.model_select.startswith('Global'): self.model = cake.load_model() else: latlon = master.lat, master.lon profile = crust2x2.get_profile(*latlon) profile.set_layer_thickness(crust2x2.LWATER, 0.0) self.model = cake.LayeredModel.from_scanlines( cake.from_crust2x2_profile(profile)) self.model_key = model_key phases = { 'P': ([cake.PhaseDef(x) for x in 'P p'.split()], 'Z'), 'S': ([cake.PhaseDef(x) for x in 'S s'.split()], 'NE'), } phasenames = list(phases.keys()) phasenames.sort() # synthetic arrivals and ray geometry for master event master_depth = master.depth if self.master_depth_km is not None: master_depth = self.master_depth_km * km tt = {} g = {} for iphase, phasename in enumerate(phasenames): for istation, station in enumerate(stations): dist = orthodrome.distance_accurate50m(master, station) azi = orthodrome.azimuth(master, station) arrivals = self.model.arrivals(phases=phases[phasename][0], distances=[dist * cake.m2d], zstart=master_depth, zstop=0.0) if arrivals: first = arrivals[0] tt[station.network, station.station, phasename] = first.t takeoff = first.takeoff_angle() u = first.path.first_straight().u_in(first.endgaps) g[iphase, istation] = num.array([ math.cos(azi * d2r) * math.sin(takeoff * d2r) * u, math.sin(azi * d2r) * math.sin(takeoff * d2r) * u, math.cos(takeoff * d2r) * u ]) # gather picks for each event for ev in events: picks = {} for m2 in viewer.markers: if isinstance(m2, PhaseMarker) and m2.kind == 0: if m2.get_event() == ev: net, sta, _, _ = m2.one_nslc() picks[net, sta, m2.get_phasename()] = (m2.tmax + m2.tmin) / 2.0 ev.picks = picks # time corrections for extraction windows dataobs = [] datasyn = [] for phasename in phasenames: for station in stations: nsp = station.network, station.station, phasename datasyn.append(tt.get(nsp, None)) for ev in events: if nsp in ev.picks: ttobs = ev.picks[nsp] - ev.time else: ttobs = None dataobs.append(ttobs) ttsyn = num.array(datasyn, dtype=num.float).reshape( (len(phasenames), len(stations))) ttobs = num.array(dataobs, dtype=num.float).reshape( (len(phasenames), len(stations), len(events))) ttres = ttobs - ttsyn[:, :, num.newaxis] tt_corr_event = num.nansum( ttres, axis=1) / \ num.nansum( num.isfinite(ttres), axis=1 ) tt_corr_event = num.where(num.isfinite(tt_corr_event), tt_corr_event, 0.) ttres -= tt_corr_event[:, num.newaxis, :] tt_corr_station = num.nansum( ttres, axis=2) / \ num.nansum( num.isfinite(ttres), axis=2 ) tt_corr_station = num.where(num.isfinite(tt_corr_station), tt_corr_station, 0.) ttres -= tt_corr_station[:, :, num.newaxis] tevents_raw = num.array([ev.time for ev in events]) tevents_corr = tevents_raw + num.mean(tt_corr_event, axis=0) # print timing information print('timing stats') for iphasename, phasename in enumerate(phasenames): data = [] for ev in events: iev = event_to_number[ev] for istation, station in enumerate(stations): nsp = station.network, station.station, phasename if nsp in tt and nsp in ev.picks: tarr = ev.time + tt[nsp] tarr_ec = tarr + tt_corr_event[iphasename, iev] tarr_ec_sc = tarr_ec + tt_corr_station[iphasename, istation] tobs = ev.picks[nsp] data.append( (tobs - tarr, tobs - tarr_ec, tobs - tarr_ec_sc)) if data: data = num.array(data, dtype=num.float).T print('event %10s %3s %3i %15.2g %15.2g %15.2g' % ((ev.name, phasename, data.shape[1]) + tuple(num.mean(num.abs(x)) for x in data))) else: print('event %10s %3s no picks' % (ev.name, phasename)) # extract and preprocess waveforms tpad = 0.0 for f in self.corner_highpass, self.corner_lowpass: if f is not None: tpad = max(tpad, 1.0 / f) pile = self.get_pile() waveforms = {} for ev in events: iev = event_to_number[ev] markers = [] for iphasename, phasename in enumerate(phasenames): for istation, station in enumerate(stations): nsp = station.network, station.station, phasename if nsp in tt: tarr = ev.time + tt[nsp] nslcs = [(station.network, station.station, '*', '*')] marker = PhaseMarker(nslcs, tarr, tarr, 1, event=ev, phasename=phasename) markers.append(marker) tarr2 = tarr + tt_corr_station[iphasename, istation] + \ tt_corr_event[iphasename, iev] marker = PhaseMarker(nslcs, tarr2, tarr2, 2, event=ev, phasename=phasename) markers.append(marker) tmin = tarr2 + self.tstart tmax = tarr2 + self.tend marker = PhaseMarker(nslcs, tmin, tmax, 3, event=ev, phasename=phasename) markers.append(marker) trs = pile.all(tmin, tmax, tpad=tpad, trace_selector=lambda tr: tr.nslc_id[:2] == nsp[:2], want_incomplete=False) trok = [] for tr in trs: if num.all(tr.ydata[0] == tr.ydata): continue if self.corner_highpass: tr.highpass(4, self.corner_highpass) if self.corner_lowpass: tr.lowpass(4, self.corner_lowpass) tr.chop(tmin, tmax) tr.set_location(ev.name) #tr.shift( - (tmin - master.time) ) if num.all(num.isfinite(tr.ydata)): trok.append(tr) waveforms[nsp + (iev, )] = trok self.add_markers(markers) def get_channel(trs, cha): for tr in trs: if tr.channel == cha: return tr return None nevents = len(events) nstations = len(stations) nphases = len(phasenames) # correlate waveforms coefs = num.zeros((nphases, nstations, nevents, nevents)) coefs.fill(num.nan) tshifts = coefs.copy() tshifts_picked = coefs.copy() for iphase, phasename in enumerate(phasenames): for istation, station in enumerate(stations): nsp = station.network, station.station, phasename for a in events: ia = event_to_number[a] for b in events: ib = event_to_number[b] if ia == ib: continue if nsp in a.picks and nsp in b.picks: tshifts_picked[iphase,istation,ia,ib] = \ b.picks[nsp] - a.picks[nsp] wa = waveforms[nsp + (ia, )] wb = waveforms[nsp + (ib, )] channels = list(set([tr.channel for tr in wa + wb])) channels.sort() tccs = [] for cha in channels: if cha[-1] not in phases[phasename][1]: continue ta = get_channel(wa, cha) tb = get_channel(wb, cha) if ta is None or tb is None: continue tcc = trace.correlate(ta, tb, mode='full', normalization='normal', use_fft=True) tccs.append(tcc) if not tccs: continue tc = None for tcc in tccs: if tc is None: tc = tcc else: tc.add(tcc) tc.ydata *= 1. / len(tccs) tmid = tc.tmin * 0.5 + tc.tmax * 0.5 tlen = (tc.tmax - tc.tmin) * 0.5 tc_cut = tc.chop(tmid - tlen * 0.5, tmid + tlen * 0.5, inplace=False) tshift, coef = tc_cut.max() if (tshift < tc.tmin + 0.5 * tc.deltat or tc.tmax - 0.5 * tc.deltat < tshift): continue coefs[iphase, istation, ia, ib] = coef tshifts[iphase, istation, ia, ib] = tshift if self.show_correlation_traces: tc.shift(master.time - (tc.tmax + tc.tmin) / 2.) self.add_trace(tc) #tshifts = tshifts_picked coefssum_sta = num.nansum(coefs, axis=2) / num.sum(num.isfinite(coefs), axis=2) csum_sta = num.nansum(coefssum_sta, axis=2) / num.sum( num.isfinite(coefssum_sta), axis=2) for iphase, phasename in enumerate(phasenames): for istation, station in enumerate(stations): print('station %-5s %s %15.2g' % (station.station, phasename, csum_sta[iphase, istation])) coefssum = num.nansum(coefs, axis=1) / num.sum(num.isfinite(coefs), axis=1) csumevent = num.nansum(coefssum, axis=2) / num.sum( num.isfinite(coefssum), axis=2) above = num.where(num.isfinite(coefs), coefs >= self.min_corr, 0) csumabove = num.sum(num.sum(above, axis=1), axis=2) coefssum = num.ma.masked_invalid(coefssum) print('correlation stats') for iphase, phasename in enumerate(phasenames): for ievent, event in enumerate(events): print('event %10s %3s %8i %15.2g' % (event.name, phasename, csumabove[iphase, ievent], csumevent[iphase, ievent])) # plot event correlation matrix fframe = self.figure_frame() fig = fframe.gcf() for iphase, phasename in enumerate(phasenames): p = fig.add_subplot(1, nphases, iphase + 1) p.set_xlabel('Event number') p.set_ylabel('Event number') mesh = p.pcolormesh(coefssum[iphase]) cb = fig.colorbar(mesh, ax=p) cb.set_label('Max correlation coefficient') if self.save: fig.savefig(self.output_filename(dir='correlation.pdf')) fig.canvas.draw() # setup and solve linear system data = [] rows = [] weights = [] for iphase in range(nphases): for istation in range(nstations): for ia in range(nevents): for ib in range(ia + 1, nevents): k = iphase, istation, ia, ib w = coefs[k] if not num.isfinite(tshifts[k]) \ or not num.isfinite(w) or w < self.min_corr: continue row = num.zeros(nevents * 4) row[ia * 4:ia * 4 + 3] = g[iphase, istation] row[ia * 4 + 3] = -1.0 row[ib * 4:ib * 4 + 3] = -g[iphase, istation] row[ib * 4 + 3] = 1.0 weights.append(w) rows.append(row) data.append(tshifts[iphase, istation, ia, ib]) nsamp = len(data) for i in range(4): row = num.zeros(nevents * 4) row[i::4] = 1. rows.append(row) data.append(0.0) if self.fix_depth: for ievent in range(nevents): row = num.zeros(nevents * 4) row[ievent * 4 + 2] = 1.0 rows.append(row) data.append(0.0) a = num.array(rows, dtype=num.float) d = num.array(data, dtype=num.float) w = num.array(weights, dtype=num.float) if self.weighting == 'equal': w[:nsamp] = 1.0 elif self.weighting == 'linear': pass elif self.weighting == 'quadratic': w[:nsamp] = w[:nsamp]**2 a[:nsamp, :] *= w[:, num.newaxis] d[:nsamp] *= w[:nsamp] x, residuals, rank, singular = num.linalg.lstsq(a, d) x0 = num.zeros(nevents * 4) x0[3::4] = tevents_corr mean_abs_residual0 = num.mean( num.abs((num.dot(a[:nsamp], x0) - d[:nsamp]) / w[:nsamp])) mean_abs_residual = num.mean( num.abs((num.dot(a[:nsamp], x) - d[:nsamp]) / w[:nsamp])) print(mean_abs_residual0, mean_abs_residual) # distorted solutions npermutations = 100 noiseamount = mean_abs_residual xdistorteds = [] for i in range(npermutations): dnoisy = d.copy() dnoisy[:nsamp] += num.random.normal( size=nsamp) * noiseamount * w[:nsamp] xdistorted, residuals, rank, singular = num.linalg.lstsq(a, dnoisy) xdistorteds.append(xdistorted) mean_abs_residual = num.mean( num.abs(num.dot(a, xdistorted)[:nsamp] - dnoisy[:nsamp])) tmean = num.mean([e.time for e in events]) north = x[0::4] east = x[1::4] down = x[2::4] etime = x[3::4] + tmean def plot_range(x): mi, ma = num.percentile(x, [10., 90.]) ext = (ma - mi) / 5. mi -= ext ma += ext return mi, ma lat, lon = orthodrome.ne_to_latlon(master.lat, master.lon, north, east) events_out = [] for ievent, event in enumerate(events): event_out = model.Event(time=etime[ievent], lat=lat[ievent], lon=lon[ievent], depth=down[ievent] + master_depth, name=event.name) mark = EventMarker(event_out, kind=4) self.add_marker(mark) events_out.append(event_out) model.Event.dump_catalog(events_out, 'events.relocated.txt') # plot results ned_orig = [] for event in events: n, e = orthodrome.latlon_to_ne(master, event) d = event.depth ned_orig.append((n, e, d)) ned_orig = num.array(ned_orig) ned_orig[:, 0] -= num.mean(ned_orig[:, 0]) ned_orig[:, 1] -= num.mean(ned_orig[:, 1]) ned_orig[:, 2] -= num.mean(ned_orig[:, 2]) north0, east0, down0 = ned_orig.T north2, east2, down2, time2 = num.hstack(xdistorteds).reshape( (-1, 4)).T fframe = self.figure_frame() fig = fframe.gcf() color_sym = (0.1, 0.1, 0.0) color_scat = (0.3, 0.5, 1.0, 0.2) d = u'\u0394 ' if not self.fix_depth: p = fig.add_subplot(2, 2, 1, aspect=1.0) else: p = fig.add_subplot(1, 1, 1, aspect=1.0) mi_north, ma_north = plot_range(north) mi_east, ma_east = plot_range(east) mi_down, ma_down = plot_range(down) p.set_xlabel(d + 'East [km]') p.set_ylabel(d + 'North [km]') p.plot(east2 / km, north2 / km, '.', color=color_scat, markersize=2) p.plot(east / km, north / km, '+', color=color_sym) p.plot(east0 / km, north0 / km, 'x', color=color_sym) p0 = p for i, ev in enumerate(events): p.text(east[i] / km, north[i] / km, ev.name, clip_on=True) if not self.fix_depth: p = fig.add_subplot(2, 2, 2, sharey=p0, aspect=1.0) p.set_xlabel(d + 'Depth [km]') p.set_ylabel(d + 'North [km]') p.plot(down2 / km, north2 / km, '.', color=color_scat, markersize=2) p.plot(down / km, north / km, '+', color=color_sym) for i, ev in enumerate(events): p.text(down[i] / km, north[i] / km, ev.name, clip_on=True) p1 = p p = fig.add_subplot(2, 2, 3, sharex=p0, aspect=1.0) p.set_xlabel(d + 'East [km]') p.set_ylabel(d + 'Depth [km]') p.plot(east2 / km, down2 / km, '.', color=color_scat, markersize=2) p.plot(east / km, down / km, '+', color=color_sym) for i, ev in enumerate(events): p.text(east[i] / km, down[i] / km, ev.name, clip_on=True) p.invert_yaxis() p2 = p p0.set_xlim(mi_east / km, ma_east / km) p0.set_ylim(mi_north / km, ma_north / km) if not self.fix_depth: p1.set_xlim(mi_down / km, ma_down / km) p2.set_ylim(mi_down / km, ma_down / km) if self.save: fig.savefig(self.output_filename(dir='locations.pdf')) fig.canvas.draw()
def call(self): self.cleanup() try: viewer = self.get_viewer() lowpass = viewer.lowpass highpass = viewer.highpass markers = viewer.selected_markers() if not markers: return if len(markers) != 1: return marker = markers[0] master_tmin, master_tmax = marker.tmin, marker.tmax if master_tmin >= master_tmax: return except NoViewerSet: viewer = None master_tmin, master_tmax = self.master_tmin, self.master_tmax tpad = 0. if highpass: tpad = 1. / highpass pile = self.get_pile() masters = {} def preprocess(_tr): if self.downsample: _tr.downsample_to(1. / self.downsample) if highpass: _tr.highpass(4, highpass) if lowpass: _tr.lowpass(4, lowpass) for tr in pile.all(tmin=master_tmin, tmax=master_tmax, tpad=tpad): for m in markers: if m.match_nslc(tr.nslc_id): preprocess(tr) tr.chop(tr.wmin, tr.wmax) masters[tr.nslc_id] = tr break if self.apply_to_all: tmin, tmax = pile.get_tmin() + tpad, pile.get_tmax() else: tmin, tmax = self.get_viewer().get_time_range() normalization = { 'Off': None, 'Normal': 'normal', 'Gliding': 'gliding' }[self.normalization] for traces in pile.chopper(tmin=tmin, tmax=tmax, want_incomplete=True): sccs = defaultdict() sccn = defaultdict() for b in traces: nslc = b.nslc_id if nslc in masters: a = masters[nslc] preprocess(b) c = trace.correlate(a, b, mode='valid', normalization=normalization, use_fft=self.use_fft) c.shift(-c.tmin + b.tmin) c.meta = {'tabu': True} scc = sccs.get(nslc, None) if not scc: scc = c.copy() scc.meta = {'tabu': True} scc.wmin = b.wmin scc.wmax = b.wmax scc.set_codes(location=scc.location + '_SUM') sccn[nslc] = 1 else: sccn[nslc] += 1 sccs[nslc] = scc for nslc_id, scc in sccs.items(): scc.ydata /= sccn[nslc_id] scc.chop(scc.wmin, scc.wmax) markers = [] for t, a in zip( *scc.peaks(self.threshold, tsearch=self.tsearch)): m = PhaseMarker(tmin=t, tmax=t, phasename='%1.3f' % a, kind=3, nslc_ids=(nslc_id, )) markers.append(m) if viewer: self.add_traces([scc]) self.add_markers(markers) else: io.save([scc], self.out_path, format='from_extension')
def call(self): self.cleanup() try: viewer = self.get_viewer() lowpass = viewer.lowpass highpass = viewer.highpass markers = viewer.selected_markers() if not markers: return if len(markers) != 1: return marker = markers[0] master_tmin, master_tmax = marker.tmin, marker.tmax if master_tmin >= master_tmax: return except NoViewerSet: viewer = None master_tmin, master_tmax = self.master_tmin, self.master_tmax tpad = 0. if highpass: tpad = 1. / highpass pile = self.get_pile() masters = {} def preprocess(_tr): if self.downsample: _tr.downsample_to(1./self.downsample) if highpass: _tr.highpass(4, highpass) if lowpass: _tr.lowpass(4, lowpass) for tr in pile.all(tmin=master_tmin, tmax=master_tmax, tpad=tpad): for m in markers: if m.match_nslc(tr.nslc_id): preprocess(tr) tr.chop(tr.wmin, tr.wmax) masters[tr.nslc_id] = tr break if self.apply_to_all: tmin, tmax = pile.get_tmin()+tpad, pile.get_tmax() else: tmin, tmax = self.get_viewer().get_time_range() normalization = {'Off': None, 'Normal': 'normal', 'Gliding': 'gliding'}[self.normalization] for traces in pile.chopper(tmin=tmin, tmax=tmax, want_incomplete=True): sccs = defaultdict() sccn = defaultdict() for b in traces: nslc = b.nslc_id if nslc in masters: a = masters[nslc] preprocess(b) c = trace.correlate( a, b, mode='valid', normalization=normalization, use_fft=self.use_fft) c.shift(-c.tmin + b.tmin) c.meta = {'tabu': True} scc = sccs.get(nslc, None) if not scc: scc = c.copy() scc.meta = {'tabu': True} scc.wmin = b.wmin scc.wmax = b.wmax scc.set_codes(location=scc.location+'_SUM') sccn[nslc] = 1 else: sccn[nslc] += 1 sccs[nslc] = scc for nslc_id, scc in sccs.items(): scc.ydata /= sccn[nslc_id] scc.chop(scc.wmin, scc.wmax) markers = [] for t, a in zip(*scc.peaks(self.threshold, tsearch=self.tsearch)): m = PhaseMarker(tmin=t, tmax=t, phasename='%1.3f' % a, kind=3, nslc_ids=(nslc_id,)) markers.append(m) if viewer: self.add_traces([scc]) self.add_markers(markers) else: io.save([scc], self.out_path, format='from_extension')
def ccs_allstats_one_event(i_ev, ev, stat_list, all_stations, p_obs, p_syn, out_dir, bp, arrT_array, cc_thresh, debug_mode=False): """ for one event: call cc_single_stat_single_event for each station, collect optimal time shifts return list with timeshift, fixed order of stations! """ ev_t_str = util.time_to_str(ev.time).replace(' ', '_') #p_obs = pile.make_pile(datapath+ev_t_str, show_progress=False) #p_syn = pile.make_pile(syndatapath+ev_t_str, show_progress=False) tshift_list = [] if p_obs and p_syn: for i_st, st in enumerate(stat_list): try: s = st.station n = st.network l = 'not_set' except: n, s, l, c = st i_ast = [ i_ast for i_ast, ast in enumerate(all_stations) if ast.network == n and ast.station == s ] if len(i_ast) >= 1: ii_ast = i_ast[0] tmin = arrT_array[i_ev, ii_ast] - 30 elif len(i_ast) == 0: logging.warning('station %s.%s not in all station list' % (n, s)) continue if l != 'not_set': tr_obs = p_obs.all( trace_selector=lambda tr: tr.network == n and tr.station == s and tr.location == l and tr.channel == 'Z', tmin=tmin, tmax=tmin + 300, want_incomplete=True) else: tr_obs = p_obs.all(trace_selector=lambda tr: tr.network == n and tr.station == s and tr.channel == 'Z', tmin=tmin, tmax=tmin + 300, want_incomplete=True) tr_syn = p_syn.all(trace_selector=lambda tr: tr.network == n and tr .station == s and tr.channel == 'Z', tmin=tmin, tmax=tmin + 300, want_incomplete=True) if len(tr_obs) != 0 and len(tr_syn) != 0: tr_syn = tr_syn[0] tr_obs = tr_obs[0] tr_obs.bandpass(bp[0], bp[1], bp[2]) tr_syn.bandpass(bp[0], bp[1], bp[2]) c = trace.correlate(tr_syn, tr_obs, mode='same', normalization='normal') t, coef = c.max() if debug_mode is True: logging.debug('%s %s' % (t, coef)) trace.snuffle([tr_syn, tr_obs]) trace.snuffle([c]) if coef > cc_thresh: tshift_list.append(t) else: tshift_list.append(num.nan) else: tshift_list.append(num.nan) return tshift_list
def prep_orient(datapath, st, loc, catalog, dir_ro, v_rayleigh, bp, dt_start, dt_stop, ccmin=0.80, plot_heatmap=False, plot_distr=False, debug=False): """ Perform orientation analysis using Rayleigh waves, main function. time wdw: 20s before 4.0km/s arrival and 600 s afterwards (Stachnik et al. 2012) - compute radial component for back values of 0 to 360 deg - for each c-c of hilbert(R) with Z comp. - call plotting functions and/or write results to file :param datapath: path to rrd data :param st: current station (pyrocko station object) :param catalog: list of pyrocko events used for analysis :param dir_ro: output directory :param plot_heatmap: bool, optional :param plot_distr: bool, optional """ logs = logging.getLogger('prep_orient') st_data_pile = pile.make_pile(datapath, regex='%s_%s_' % (st.network, st.station), show_progress=False) n_ev = len(catalog) if st_data_pile.tmin is not None and st_data_pile.tmax is not None: # calculate dist between all events and current station r_arr_by_ev = num.empty(n_ev) ev_lats = num.asarray([ev.lat for ev in catalog]) ev_lons = num.asarray([ev.lon for ev in catalog]) dists = distance_accurate50m_numpy(a_lats=ev_lats, a_lons=ev_lons, b_lats=st.lat, b_lons=st.lon, implementation='c') r_arr_by_ev = (dists / 1000.) / v_rayleigh cc_i_ev_vs_rota = num.empty((n_ev, 360)) rot_angles = range(-180, 180, 1) for i_ev, ev in enumerate(catalog): arrT = ev.time + r_arr_by_ev[i_ev] start_twd1 = ev.time end_twd1 = arrT + 1800 trZ = get_tr_by_cha(st_data_pile, start_twd1, end_twd1, loc, 'Z') trR = get_tr_by_cha(st_data_pile, start_twd1, end_twd1, loc, 'R') trT = get_tr_by_cha(st_data_pile, start_twd1, end_twd1, loc, 'T') start_twd2 = ev.time + r_arr_by_ev[i_ev] - dt_start end_twd2 = arrT + dt_stop if len(trZ) == 1 and len(trR) == 1 and len(trT) == 1: trZ = trZ[0] trR = trR[0] trT = trT[0] # debugging - window selection: if debug is True: trace.snuffle([trZ, trR, trT], markers=[ pm.Marker(nslc_ids=[ trZ.nslc_id, trR.nslc_id, trT.nslc_id ], tmin=start_twd2, tmax=end_twd2), pm.Marker(nslc_ids=[ trZ.nslc_id, trR.nslc_id, trT.nslc_id ], tmin=arrT, tmax=arrT + 3) ]) else: cc_i_ev_vs_rota[i_ev, :] = num.nan continue try: trZ.bandpass(bp[0], bp[1], bp[2]) trZ.chop(tmin=start_twd2, tmax=end_twd2) except trace.NoData: logs.warning('no data %s %s %s' % (trZ, trR, trT)) continue for i_r, r in enumerate(rot_angles): print('rotation angle [deg]: %5d' % r, end='\r') rot_2, rot_3 = trace.rotate(traces=[trR, trT], azimuth=r, in_channels=['R', 'T'], out_channels=['2', '3']) rot_2_y = rot_2.ydata rot_2_hilb = num.imag(trace.hilbert(rot_2_y, len(rot_2_y))) rot_2_hilb_tr = trace.Trace(deltat=rot_2.deltat, ydata=rot_2_hilb, tmin=rot_2.tmin) # problem: rot_2 and rot_2_hilb look exactly the same! # --> no phase shift. why? should be num.imag!!! # trace.snuffle([rot_2, rot_2_hilb_tr]) rot_2_hilb_tr.bandpass(bp[0], bp[1], bp[2]) rot_2_hilb_tr.chop(tmin=start_twd2, tmax=end_twd2) # if st.station == 'RORO' and r == 0: # trace.snuffle([rot_2_hilb_tr, trZ]) # normalize traces trZ.ydata /= abs(max(trZ.ydata)) rot_2_hilb_tr.ydata /= abs(max(rot_2_hilb_tr.ydata)) c = trace.correlate(trZ, rot_2_hilb_tr, mode='valid', normalization='normal') t, coef = c.max() t2, coef2 = max_or_min(c) ''' if st.station == 'MATE' and r == 0: print(i_ev, ev.name, ev.depth) print(r, t, coef, t2, coef2) trace.snuffle([trZ, trR, rot_2_hilb_tr]) ''' cc_i_ev_vs_rota[i_ev, i_r] = coef ''' if st.station == 'MATE': for i_ev in range(n_ev): print(num.argmax(cc_i_ev_vs_rota[i_ev,:]), num.max(cc_i_ev_vs_rota[i_ev,:])) ''' if plot_heatmap is True: fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(8, 2)) cax = ax.imshow(cc_i_ev_vs_rota, interpolation='nearest', vmin=-1.0, vmax=1.0, aspect='auto', extent=[-180, 180, n_ev, 0], cmap='binary') ax.set_ylabel('i_ev') ax.set_xlabel('Correction angle (deg)') ax.set_title('%s %s' % (st.network, st.station)) cbar = fig.colorbar(cax, ticks=[0, 0.5, 1.0], orientation='horizontal', fraction=0.05, pad=0.5) cbar.ax.set_xticklabels(['0', '0.5', '1.0']) plt.tight_layout() # plt.show(fig) fig.savefig( os.path.join( dir_ro, '%s_%s_%s_rot_cc_heatmap.png' % (st.network, st.station, loc))) plt.close() if plot_distr is True: plot_ccdistr_each_event(cc_i_ev_vs_rota, catalog, rot_angles, st, loc, dir_ro) median_a, mean_a, std_a, switched, n_ev =\ get_m_angle_switched(cc_i_ev_vs_rota, catalog, st, ccmin) dict_ev_angle = get_m_angle_all(cc_i_ev_vs_rota, catalog, st, ccmin) return median_a, mean_a, std_a, switched, dict_ev_angle, n_ev
def call(self): self.cleanup() viewer = self.get_viewer() master = viewer.get_active_event() if master is None: self.fail('no master event selected') stations = list(viewer.stations.values()) stations.sort(key=lambda s: (s.network,s.station)) if not stations: self.fail('no station information available') # gather events to be processed events = [] for m in viewer.markers: if isinstance(m, EventMarker): if m.kind == 0: events.append( m.get_event() ) events.sort(key=lambda ev: ev.time) event_to_number = {} for iev, ev in enumerate(events): event_to_number[ev] = iev if self.model_select.startswith('Global'): model_key = 'global' else: model_key = master.lat, master.lon if model_key != self.model_key: if self.model_select.startswith('Global'): self.model = cake.load_model() else: latlon = master.lat, master.lon profile = crust2x2.get_profile(*latlon) profile.set_layer_thickness(crust2x2.LWATER, 0.0) self.model = cake.LayeredModel.from_scanlines( cake.from_crust2x2_profile(profile)) self.model_key = model_key phases = { 'P': ([ cake.PhaseDef(x) for x in 'P p'.split() ], 'Z'), 'S': ([ cake.PhaseDef(x) for x in 'S s'.split() ], 'NE'), } phasenames = phases.keys() phasenames.sort() # synthetic arrivals and ray geometry for master event master_depth = master.depth if self.master_depth_km is not None: master_depth = self.master_depth_km * km tt = {} g = {} for iphase, phasename in enumerate(phasenames): for istation, station in enumerate(stations): dist = orthodrome.distance_accurate50m(master, station) azi = orthodrome.azimuth(master, station) arrivals = self.model.arrivals( phases=phases[phasename][0], distances=[ dist*cake.m2d ], zstart = master_depth, zstop = 0.0) if arrivals: first = arrivals[0] tt[station.network, station.station, phasename] = first.t takeoff = first.takeoff_angle() u = first.path.first_straight().u_in(first.endgaps) g[iphase, istation] = num.array([ math.cos(azi*d2r) * math.sin(takeoff*d2r) * u, math.sin(azi*d2r) * math.sin(takeoff*d2r) * u, math.cos(takeoff*d2r) * u ]) # gather picks for each event for ev in events: picks = {} for m2 in viewer.markers: if isinstance(m2, PhaseMarker) and m2.kind == 0: if m2.get_event() == ev: net, sta, _, _ = m2.one_nslc() picks[net,sta,m2.get_phasename()] = (m2.tmax + m2.tmin) / 2.0 ev.picks = picks # time corrections for extraction windows dataobs = [] datasyn = [] for phasename in phasenames: for station in stations: nsp = station.network, station.station, phasename datasyn.append(tt.get(nsp,None)) for ev in events: if nsp in ev.picks: ttobs = ev.picks[nsp] - ev.time else: ttobs = None dataobs.append(ttobs) ttsyn = num.array(datasyn, dtype=num.float).reshape(( len(phasenames), len(stations))) ttobs = num.array(dataobs, dtype=num.float).reshape(( len(phasenames), len(stations), len(events))) ttres = ttobs - ttsyn[:,:,num.newaxis] tt_corr_event = num.nansum( ttres, axis=1) / \ num.nansum( num.isfinite(ttres), axis=1 ) tt_corr_event = num.where(num.isfinite(tt_corr_event), tt_corr_event, 0.) ttres -= tt_corr_event[:,num.newaxis,:] tt_corr_station = num.nansum( ttres, axis=2) / \ num.nansum( num.isfinite(ttres), axis=2 ) tt_corr_station = num.where(num.isfinite(tt_corr_station), tt_corr_station, 0.) ttres -= tt_corr_station[:,:, num.newaxis] tevents_raw = num.array( [ ev.time for ev in events ] ) tevents_corr = tevents_raw + num.mean(tt_corr_event, axis=0) # print timing information print 'timing stats' for iphasename, phasename in enumerate(phasenames): data = [] for ev in events: iev = event_to_number[ev] for istation, station in enumerate(stations): nsp = station.network, station.station, phasename if nsp in tt and nsp in ev.picks: tarr = ev.time + tt[nsp] tarr_ec = tarr + tt_corr_event[iphasename, iev] tarr_ec_sc = tarr_ec + tt_corr_station[iphasename, istation] tobs = ev.picks[nsp] data.append((tobs-tarr, tobs-tarr_ec, tobs-tarr_ec_sc)) if data: data = num.array(data, dtype=num.float).T print 'event %10s %3s %3i %15.2g %15.2g %15.2g' % ( (ev.name, phasename, data.shape[1]) + tuple( num.mean(num.abs(x)) for x in data )) else: print 'event %10s %3s no picks' % (ev.name, phasename) # extract and preprocess waveforms tpad = 0.0 for f in self.corner_highpass, self.corner_lowpass: if f is not None: tpad = max(tpad, 1.0/f) pile = self.get_pile() waveforms = {} for ev in events: iev = event_to_number[ev] markers = [] for iphasename, phasename in enumerate(phasenames): for istation, station in enumerate(stations): nsp = station.network, station.station, phasename if nsp in tt: tarr = ev.time + tt[nsp] nslcs = [ ( station.network, station.station, '*', '*' ) ] marker = PhaseMarker( nslcs, tarr, tarr, 1, event=ev, phasename=phasename) markers.append(marker) tarr2 = tarr + tt_corr_station[iphasename, istation] + \ tt_corr_event[iphasename, iev] marker = PhaseMarker( nslcs, tarr2, tarr2, 2, event=ev, phasename=phasename) markers.append(marker) tmin = tarr2+self.tstart tmax = tarr2+self.tend marker = PhaseMarker( nslcs, tmin, tmax, 3, event=ev, phasename=phasename) markers.append(marker) trs = pile.all(tmin, tmax, tpad=tpad, trace_selector= lambda tr: tr.nslc_id[:2] == nsp[:2], want_incomplete=False) trok = [] for tr in trs: if num.all(tr.ydata[0] == tr.ydata): continue if self.corner_highpass: tr.highpass(4, self.corner_highpass) if self.corner_lowpass: tr.lowpass(4, self.corner_lowpass) tr.chop(tmin, tmax) tr.set_location(ev.name) #tr.shift( - (tmin - master.time) ) if num.all(num.isfinite(tr.ydata)): trok.append(tr) waveforms[nsp+(iev,)] = trok self.add_markers(markers) def get_channel(trs, cha): for tr in trs: if tr.channel == cha: return tr return None nevents = len(events) nstations = len(stations) nphases = len(phasenames) # correlate waveforms coefs = num.zeros((nphases, nstations, nevents, nevents)) coefs.fill(num.nan) tshifts = coefs.copy() tshifts_picked = coefs.copy() for iphase, phasename in enumerate(phasenames): for istation, station in enumerate(stations): nsp = station.network, station.station, phasename for a in events: ia = event_to_number[a] for b in events: ib = event_to_number[b] if ia == ib: continue if nsp in a.picks and nsp in b.picks: tshifts_picked[iphase,istation,ia,ib] = \ b.picks[nsp] - a.picks[nsp] wa = waveforms[nsp+(ia,)] wb = waveforms[nsp+(ib,)] channels = list(set([ tr.channel for tr in wa + wb ])) channels.sort() tccs = [] for cha in channels: if cha[-1] not in phases[phasename][1]: continue ta = get_channel(wa, cha) tb = get_channel(wb, cha) if ta is None or tb is None: continue tcc = trace.correlate(ta,tb, mode='full', normalization='normal', use_fft=True) tccs.append(tcc) if not tccs: continue tc = None for tcc in tccs: if tc is None: tc = tcc else: tc.add(tcc) tc.ydata *= 1./len(tccs) tmid = tc.tmin*0.5 + tc.tmax*0.5 tlen = (tc.tmax - tc.tmin)*0.5 tc_cut = tc.chop(tmid-tlen*0.5, tmid+tlen*0.5, inplace=False) tshift, coef = tc_cut.max() if (tshift < tc.tmin + 0.5*tc.deltat or tc.tmax - 0.5*tc.deltat < tshift): continue coefs[iphase,istation,ia,ib] = coef tshifts[iphase,istation,ia,ib] = tshift if self.show_correlation_traces: tc.shift(master.time - (tc.tmax + tc.tmin)/2.) self.add_trace(tc) #tshifts = tshifts_picked coefssum_sta = num.nansum(coefs, axis=2) / num.sum(num.isfinite(coefs), axis=2) csum_sta = num.nansum(coefssum_sta, axis=2) / num.sum(num.isfinite(coefssum_sta), axis=2) for iphase, phasename in enumerate(phasenames): for istation, station in enumerate(stations): print 'station %-5s %s %15.2g' % (station.station, phasename, csum_sta[iphase,istation]) coefssum = num.nansum(coefs, axis=1) / num.sum(num.isfinite(coefs), axis=1) csumevent = num.nansum(coefssum, axis=2) / num.sum(num.isfinite(coefssum), axis=2) above = num.where(num.isfinite(coefs), coefs >= self.min_corr, 0) csumabove = num.sum(num.sum(above, axis=1), axis=2) coefssum = num.ma.masked_invalid(coefssum) print 'correlation stats' for iphase, phasename in enumerate(phasenames): for ievent, event in enumerate(events): print 'event %10s %3s %8i %15.2g' % ( event.name, phasename, csumabove[iphase,ievent], csumevent[iphase,ievent]) # plot event correlation matrix fframe = self.figure_frame() fig = fframe.gcf() for iphase, phasename in enumerate(phasenames): p = fig.add_subplot(1,nphases,iphase+1) p.set_xlabel('Event number') p.set_ylabel('Event number') mesh = p.pcolormesh(coefssum[iphase]) cb = fig.colorbar(mesh, ax=p) cb.set_label('Max correlation coefficient') if self.save: fig.savefig(self.output_filename(dir='correlation.pdf')) fig.canvas.draw() # setup and solve linear system data = [] rows = [] weights = [] for iphase in xrange(nphases): for istation in xrange(nstations): for ia in xrange(nevents): for ib in xrange(ia+1,nevents): k = iphase, istation, ia, ib w = coefs[k] if not num.isfinite(tshifts[k]) \ or not num.isfinite(w) or w < self.min_corr: continue row = num.zeros(nevents*4) row[ia*4:ia*4+3] = g[iphase,istation] row[ia*4+3] = -1.0 row[ib*4:ib*4+3] = -g[iphase,istation] row[ib*4+3] = 1.0 weights.append(w) rows.append(row) data.append(tshifts[iphase,istation,ia,ib]) nsamp = len(data) for i in range(4): row = num.zeros(nevents*4) row[i::4] = 1. rows.append(row) data.append(0.0) if self.fix_depth: for ievent in range(nevents): row = num.zeros(nevents*4) row[ievent*4+2] = 1.0 rows.append(row) data.append(0.0) a = num.array(rows, dtype=num.float) d = num.array(data, dtype=num.float) w = num.array(weights, dtype=num.float) if self.weighting == 'equal': w[:nsamp] = 1.0 elif self.weighting == 'linear': pass elif self.weighting == 'quadratic': w[:nsamp] = w[:nsamp]**2 a[:nsamp,:] *= w[:,num.newaxis] d[:nsamp] *= w[:nsamp] x, residuals, rank, singular = num.linalg.lstsq(a,d) x0 = num.zeros(nevents*4) x0[3::4] = tevents_corr mean_abs_residual0 = num.mean( num.abs((num.dot(a[:nsamp], x0) - d[:nsamp])/w[:nsamp])) mean_abs_residual = num.mean( num.abs((num.dot(a[:nsamp],x) - d[:nsamp])/w[:nsamp])) print mean_abs_residual0, mean_abs_residual # distorted solutions npermutations = 100 noiseamount = mean_abs_residual xdistorteds = [] for i in range(npermutations): dnoisy = d.copy() dnoisy[:nsamp] += num.random.normal(size=nsamp)*noiseamount*w[:nsamp] xdistorted, residuals, rank, singular = num.linalg.lstsq(a,dnoisy) xdistorteds.append(xdistorted) mean_abs_residual = num.mean(num.abs(num.dot(a,xdistorted)[:nsamp] - dnoisy[:nsamp])) tmean = num.mean([ e.time for e in events ]) north = x[0::4] east = x[1::4] down = x[2::4] etime = x[3::4] + tmean def plot_range(x): mi, ma = num.percentile(x, [10., 90.]) ext = (ma-mi)/5. mi -= ext ma += ext return mi, ma lat, lon = orthodrome.ne_to_latlon(master.lat, master.lon, north, east) events_out = [] for ievent, event in enumerate(events): event_out = model.Event(time=etime[ievent], lat=lat[ievent], lon=lon[ievent], depth=down[ievent] + master_depth, name = event.name) mark = EventMarker(event_out, kind=4) self.add_marker(mark) events_out.append(event_out) model.Event.dump_catalog(events_out, 'events.relocated.txt') # plot results ned_orig = [] for event in events: n, e = orthodrome.latlon_to_ne(master, event) d = event.depth ned_orig.append((n,e,d)) ned_orig = num.array(ned_orig) ned_orig[:,0] -= num.mean(ned_orig[:,0]) ned_orig[:,1] -= num.mean(ned_orig[:,1]) ned_orig[:,2] -= num.mean(ned_orig[:,2]) north0, east0, down0 = ned_orig.T north2, east2, down2, time2 = num.hstack(xdistorteds).reshape((-1,4)).T fframe = self.figure_frame() fig = fframe.gcf() color_sym = (0.1,0.1,0.0) color_scat = (0.3,0.5,1.0,0.2) d = u'\u0394 ' if not self.fix_depth: p = fig.add_subplot(2,2,1, aspect=1.0) else: p = fig.add_subplot(1,1,1, aspect=1.0) mi_north, ma_north = plot_range(north) mi_east, ma_east = plot_range(east) mi_down, ma_down = plot_range(down) p.set_xlabel(d+'East [km]') p.set_ylabel(d+'North [km]') p.plot(east2/km, north2/km, '.', color=color_scat, markersize=2) p.plot(east/km, north/km, '+', color=color_sym) p.plot(east0/km, north0/km, 'x', color=color_sym) p0 = p for i,ev in enumerate(events): p.text(east[i]/km, north[i]/km, ev.name, clip_on=True) if not self.fix_depth: p = fig.add_subplot(2,2,2, sharey=p0, aspect=1.0) p.set_xlabel(d+'Depth [km]') p.set_ylabel(d+'North [km]') p.plot(down2/km, north2/km, '.', color=color_scat, markersize=2) p.plot(down/km, north/km, '+', color=color_sym) for i,ev in enumerate(events): p.text(down[i]/km, north[i]/km, ev.name, clip_on=True) p1 = p p = fig.add_subplot(2,2,3, sharex=p0, aspect=1.0) p.set_xlabel(d+'East [km]') p.set_ylabel(d+'Depth [km]') p.plot(east2/km, down2/km, '.', color=color_scat, markersize=2) p.plot(east/km, down/km, '+', color=color_sym) for i,ev in enumerate(events): p.text(east[i]/km, down[i]/km, ev.name, clip_on=True) p.invert_yaxis() p2 = p p0.set_xlim(mi_east/km, ma_east/km) p0.set_ylim(mi_north/km, ma_north/km) if not self.fix_depth: p1.set_xlim(mi_down/km, ma_down/km) p2.set_ylim(mi_down/km, ma_down/km) if self.save: fig.savefig(self.output_filename(dir='locations.pdf')) fig.canvas.draw()
def misfit(tr_obs, tr_syn, taper, domain, exponent, tautoshift_max, autoshift_penalty_max, flip, result_mode='sparse', subtargets=[]): ''' Calculate misfit between observed and synthetic trace. :param tr_obs: observed trace as :py:class:`pyrocko.trace.Trace` :param tr_syn: synthetic trace as :py:class:`pyrocko.trace.Trace` :param taper: taper applied in timedomain as :py:class:`pyrocko.trace.Taper` :param domain: how to calculate difference, see :py:class:`DomainChoice` :param exponent: exponent of Lx type norms :param tautoshift_max: if non-zero, return lowest misfit when traces are allowed to shift against each other by up to +/- ``tautoshift_max`` :param autoshift_penalty_max: if non-zero, a penalty misfit is added for for non-zero shift values. The penalty value is ``autoshift_penalty_max * normalization_factor * \ tautoshift**2 / tautoshift_max**2`` :param flip: ``bool``, if set to ``True``, normalization factor is computed against *tr_syn* rather than *tr_obs* :param result_mode: ``'full'``, include traces and spectra or ``'sparse'``, include only misfit and normalization factor in result :returns: object of type :py:class:`WaveformMisfitResult` ''' trace.assert_same_sampling_rate(tr_obs, tr_syn) deltat = tr_obs.deltat tmin, tmax = taper.time_span() tr_proc_obs, trspec_proc_obs = _process(tr_obs, tmin, tmax, taper, domain) tr_proc_syn, trspec_proc_syn = _process(tr_syn, tmin, tmax, taper, domain) piggyback_results = [] for subtarget in subtargets: piggyback_results.append( subtarget.evaluate(tr_proc_obs, trspec_proc_obs, tr_proc_syn, trspec_proc_syn)) tshift = None ctr = None deltat = tr_proc_obs.deltat if domain in ('time_domain', 'envelope', 'absolute'): a, b = tr_proc_syn.ydata, tr_proc_obs.ydata if flip: b, a = a, b nshift_max = max( 0, min(a.size - 1, int(math.floor(tautoshift_max / deltat)))) if nshift_max == 0: m, n = trace.Lx_norm(a, b, norm=exponent) else: mns = [] for ishift in range(-nshift_max, nshift_max + 1): if ishift < 0: a_cut = a[-ishift:] b_cut = b[:ishift] elif ishift == 0: a_cut = a b_cut = b elif ishift > 0: a_cut = a[:-ishift] b_cut = b[ishift:] mns.append(trace.Lx_norm(a_cut, b_cut, norm=exponent)) ms, ns = num.array(mns).T iarg = num.argmin(ms) tshift = (iarg - nshift_max) * deltat m, n = ms[iarg], ns[iarg] m += autoshift_penalty_max * n * tshift**2 / tautoshift_max**2 elif domain == 'cc_max_norm': ctr = trace.correlate(tr_proc_syn, tr_proc_obs, mode='same', normalization='normal') tshift, cc_max = ctr.max() m = 0.5 - 0.5 * cc_max n = 0.5 elif domain == 'frequency_domain': a, b = trspec_proc_syn.ydata, trspec_proc_obs.ydata if flip: b, a = a, b m, n = trace.Lx_norm(num.abs(a), num.abs(b), norm=exponent) elif domain == 'log_frequency_domain': a, b = trspec_proc_syn.ydata, trspec_proc_obs.ydata if flip: b, a = a, b a = num.abs(a) b = num.abs(b) eps = (num.mean(a) + num.mean(b)) * 1e-7 if eps == 0.0: eps = 1e-7 a = num.log(a + eps) b = num.log(b + eps) m, n = trace.Lx_norm(a, b, norm=exponent) if result_mode == 'full': result = WaveformMisfitResult(misfits=num.array([[m, n]], dtype=num.float), processed_obs=tr_proc_obs, processed_syn=tr_proc_syn, filtered_obs=tr_obs.copy(), filtered_syn=tr_syn, spectrum_obs=trspec_proc_obs, spectrum_syn=trspec_proc_syn, taper=taper, tshift=tshift, cc=ctr) elif result_mode == 'sparse': result = WaveformMisfitResult( misfits=num.array([[m, n]], dtype=num.float)) else: assert False result.piggyback_subresults = piggyback_results return result
def call(self): '''Main work routine of the snuffling.''' self.cleanup() period_highpass = 1. / self.corner_highpass tpad = period_highpass try: viewer = self.get_viewer() markers = viewer.selected_markers() if not markers: return if len(markers) != 1: return marker = markers[0] master_tmin, master_tmax = marker.tmin, marker.tmax if master_tmin >= master_tmax: return except NoViewerSet: viewer = None master_tmin, master_tmax = self.master_tmin, self.master_tmax pile = self.get_pile() masters = {} for tr in pile.all(tmin=master_tmin, tmax=master_tmax, tpad=tpad): if self.downsample is not None: tr.downsample_to(1. / self.downsample) tr.highpass(4, self.corner_highpass) tr.lowpass(4, self.corner_lowpass) tr.chop(tr.wmin, tr.wmax) masters[tr.nslc_id] = tr if self.apply_to_all: tmin, tmax = pile.get_tmin() + tpad, pile.get_tmax() else: tmin, tmax = self.get_viewer().get_time_range() tmaster = master_tmax - master_tmin tinc = min(20 * tmaster, max(tmaster, tmax - tmin)) for traces in pile.chopper(tmin=tmin, tmax=tmax, tinc=tinc, tpad=tmaster + tpad, want_incomplete=False): scc = None sccn = 0 for b in traces: nslc = b.nslc_id if nslc in masters: a = masters[nslc] if self.downsample is not None: b.downsample_to(1. / self.downsample) b.highpass(4, self.corner_highpass) tr.lowpass(4, self.corner_lowpass) normalization = { 'Off': None, 'Normal': 'normal', 'Gliding': 'gliding' }[self.normalization] c = trace.correlate(a, b, mode='valid', normalization=normalization) c.shift(-c.tmin + b.tmin) c.meta = {'tabu': True} if scc is None: scc = c.copy() scc.wmin = b.wmin scc.wmax = b.wmax scc.set_codes(network='', station='Sum Cross Correlation', location='', channel='') sccn = 1 else: scc.add(c) sccn += 1 if scc is not None: scc.ydata /= sccn scc.chop(scc.wmin, scc.wmax) markers = [] for t, a in zip(*scc.peaks(self.threshold, tsearch=2. / self.corner_highpass)): m = EventMarker( model.Event(time=t, lat=0., lon=0., name='Event(%.2g)' % a)) markers.append(m) if viewer: self.add_traces([scc]) self.add_markers(markers) else: io.save([scc], self.out_path, format='from_extension')