Example #1
0
    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)
Example #2
0
    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)
Example #3
0
    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 )
Example #4
0
    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)        
Example #6
0
    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()
Example #7
0
    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
Example #8
0
    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)
Example #9
0
    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
Example #10
0
    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()
Example #11
0
    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()
Example #12
0
    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()
Example #13
0
    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')
Example #14
0
    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')
Example #16
0
    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')
Example #17
0
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
Example #18
0
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()
Example #20
0
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
Example #21
0
    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')