Пример #1
0
    def call(self):
        '''Main work routine of the snuffling.'''

        # to select a reasonable increment for the chopping, the smallest
        # sampling interval in the pile is looked at. this is only done,
        # the first time the snuffling is called.
        if self.tinc is None:
            self.tinc = self.get_pile().get_deltats()[0] * 10000.

        # the chopper yields lists of traces but for minmax() below, an
        # iterator yielding single traces is needed; using a converter:
        def iter_single_traces():
            for traces in self.chopper_selected_traces(
                    tinc=self.tinc, degap=False, fallback=True):

                for tr in traces:
                    yield tr

        # the function minmax() in the trace module can get minima and maxima
        # grouped by (network,station,location,channel):
        mima = trace.minmax(iter_single_traces())

        for nslc in sorted(mima.keys()):
            p2p = mima[nslc][1] - mima[nslc][0]
            print '%s.%s.%s.%s: %12.5g %12.5g %12.5g' % (
                nslc + mima[nslc] + (p2p,))
Пример #2
0
    def call(self):
        '''Main work routine of the snuffling.'''

        # to select a reasonable increment for the chopping, the smallest
        # sampling interval in the pile is looked at. this is only done,
        # the first time the snuffling is called.
        if self.tinc is None:
            self.tinc = self.get_pile().get_deltats()[0] * 10000.

        # the chopper yields lists of traces but for minmax() below, an
        # iterator yielding single traces is needed; using a converter:
        def iter_single_traces():
            for traces in self.chopper_selected_traces(tinc=self.tinc,
                                                       degap=False,
                                                       fallback=True):

                for tr in traces:
                    yield tr

        # the function minmax() in the trace module can get minima and maxima
        # grouped by (network,station,location,channel):
        mima = trace.minmax(iter_single_traces())

        for nslc in sorted(mima.keys()):
            p2p = mima[nslc][1] - mima[nslc][0]
            print('%s.%s.%s.%s: %12.5g %12.5g %12.5g' % (nslc + mima[nslc] +
                                                         (p2p, )))
Пример #3
0
    def draw_figures(self, ds, history, optimiser):

        fontsize = self.font_size
        fontsize_title = self.font_size_title

        nxmax = self.nx
        nymax = self.ny

        problem = history.problem

        for target in problem.targets:
            target.set_dataset(ds)

        target_index = {}
        i = 0
        for target in problem.targets:
            target_index[target] = i, i+target.nmisfits
            i += target.nmisfits

        xbest = history.get_best_model()
        misfits = history.misfits[history.get_sorted_misfits_idx(chain=0), ...]

        ws = problem.get_target_weights()

        gcms = problem.combine_misfits(
            misfits[:1, :, :],
            extra_correlated_weights=optimiser.get_correlated_weights(problem),
            get_contributions=True)[0, :]

        w_max = num.nanmax(ws)
        gcm_max = num.nanmax(gcms)

        source = problem.get_source(xbest)

        target_to_result = {}
        all_syn_trs = []
        all_syn_specs = []
        results = problem.evaluate(xbest)

        dtraces = []
        for target, result in zip(problem.targets, results):
            if not isinstance(result, WaveformMisfitResult):
                dtraces.extend([None] * target.nmisfits)
                continue

            itarget, itarget_end = target_index[target]
            assert itarget_end == itarget + 1

            w = target.get_combined_weight()

            if target.misfit_config.domain == 'cc_max_norm':
                tref = (
                    result.filtered_obs.tmin + result.filtered_obs.tmax) * 0.5
                for tr_filt, tr_proc, tshift in (
                        (result.filtered_obs,
                         result.processed_obs,
                         0.),
                        (result.filtered_syn,
                         result.processed_syn,
                         result.tshift)):

                    norm = num.sum(num.abs(tr_proc.ydata)) / tr_proc.data_len()
                    tr_filt.ydata /= norm
                    tr_proc.ydata /= norm

                    tr_filt.shift(tshift)
                    tr_proc.shift(tshift)

                ctr = result.cc
                ctr.shift(tref)

                dtrace = ctr

            else:
                for tr in (
                        result.filtered_obs,
                        result.filtered_syn,
                        result.processed_obs,
                        result.processed_syn):

                    tr.ydata *= w

                for spec in (
                        result.spectrum_obs,
                        result.spectrum_syn):

                    if spec is not None:
                        spec.ydata *= w

                if result.tshift is not None and result.tshift != 0.0:
                    # result.filtered_syn.shift(result.tshift)
                    result.processed_syn.shift(result.tshift)

                dtrace = make_norm_trace(
                    result.processed_syn, result.processed_obs,
                    problem.norm_exponent)

            target_to_result[target] = result

            dtrace.meta = dict(
                normalisation_family=target.normalisation_family,
                path=target.path)
            dtraces.append(dtrace)

            result.processed_syn.meta = dict(
                normalisation_family=target.normalisation_family,
                path=target.path)

            all_syn_trs.append(result.processed_syn)

            if result.spectrum_syn:
                result.spectrum_syn.meta = dict(
                    normalisation_family=target.normalisation_family,
                    path=target.path)

                all_syn_specs.append(result.spectrum_syn)

        if not all_syn_trs:
            logger.warn('No traces to show!')
            return

        def skey(tr):
            return tr.meta['normalisation_family'], tr.meta['path']

        trace_minmaxs = trace.minmax(all_syn_trs, skey)

        amp_spec_maxs = amp_spec_max(all_syn_specs, skey)

        dminmaxs = trace.minmax([x for x in dtraces if x is not None], skey)

        for tr in dtraces:
            if tr:
                dmin, dmax = dminmaxs[skey(tr)]
                tr.ydata /= max(abs(dmin), abs(dmax))

        cg_to_targets = meta.gather(
            problem.waveform_targets,
            lambda t: (t.path, t.codes[3]),
            filter=lambda t: t in target_to_result)

        cgs = sorted(cg_to_targets.keys())

        for cg in cgs:
            targets = cg_to_targets[cg]

            frame_to_target, nx, ny, nxx, nyy = layout(
                source, targets, nxmax, nymax)

            figures = {}
            for iy in range(ny):
                for ix in range(nx):
                    if (iy, ix) not in frame_to_target:
                        continue

                    ixx = ix // nxmax
                    iyy = iy // nymax
                    if (iyy, ixx) not in figures:
                        title = '_'.join(x for x in cg if x)
                        item = PlotItem(
                            name='fig_%s_%i_%i' % (title, ixx, iyy))
                        item.attributes['targets'] = []
                        figures[iyy, ixx] = (
                            item, plt.figure(figsize=self.size_inch))

                        figures[iyy, ixx][1].subplots_adjust(
                            left=0.03,
                            right=1.0 - 0.03,
                            bottom=0.03,
                            top=1.0 - 0.06,
                            wspace=0.2,
                            hspace=0.2)

                    item, fig = figures[iyy, ixx]

                    target = frame_to_target[iy, ix]

                    item.attributes['targets'].append(target.string_id())

                    amin, amax = trace_minmaxs[
                        target.normalisation_family, target.path]
                    absmax = max(abs(amin), abs(amax))

                    ny_this = nymax  # min(ny, nymax)
                    nx_this = nxmax  # min(nx, nxmax)
                    i_this = (iy % ny_this) * nx_this + (ix % nx_this) + 1

                    axes2 = fig.add_subplot(ny_this, nx_this, i_this)

                    space = 0.5
                    space_factor = 1.0 + space
                    axes2.set_axis_off()
                    axes2.set_ylim(-1.05 * space_factor, 1.05)

                    axes = axes2.twinx()
                    axes.set_axis_off()

                    if target.misfit_config.domain == 'cc_max_norm':
                        axes.set_ylim(-10. * space_factor, 10.)
                    else:
                        axes.set_ylim(
                            -absmax * 1.33 * space_factor, absmax * 1.33)

                    itarget, itarget_end = target_index[target]
                    assert itarget_end == itarget + 1

                    result = target_to_result[target]

                    dtrace = dtraces[itarget]

                    tap_color_annot = (0.35, 0.35, 0.25)
                    tap_color_edge = (0.85, 0.85, 0.80)
                    tap_color_fill = (0.95, 0.95, 0.90)

                    plot_taper(
                        axes2, result.processed_obs.get_xdata(), result.taper,
                        fc=tap_color_fill, ec=tap_color_edge)

                    obs_color = mpl_color('aluminium5')
                    obs_color_light = light(obs_color, 0.5)

                    syn_color = mpl_color('scarletred2')
                    syn_color_light = light(syn_color, 0.5)

                    misfit_color = mpl_color('scarletred2')
                    weight_color = mpl_color('chocolate2')

                    cc_color = mpl_color('aluminium5')

                    if target.misfit_config.domain == 'cc_max_norm':
                        tref = (result.filtered_obs.tmin +
                                result.filtered_obs.tmax) * 0.5

                        plot_dtrace(
                            axes2, dtrace, space, -1., 1.,
                            fc=light(cc_color, 0.5),
                            ec=cc_color)

                        plot_dtrace_vline(
                            axes2, tref, space, color=tap_color_annot)

                    elif target.misfit_config.domain == 'frequency_domain':

                        asmax = amp_spec_maxs[
                            target.normalisation_family, target.path]
                        fmin, fmax = \
                            target.misfit_config.get_full_frequency_range()

                        plot_spectrum(
                            axes2,
                            result.spectrum_syn,
                            result.spectrum_obs,
                            fmin, fmax,
                            space, 0., asmax,
                            syn_color=syn_color,
                            obs_color=obs_color,
                            syn_lw=1.0,
                            obs_lw=0.75,
                            color_vline=tap_color_annot,
                            fontsize=fontsize)

                    else:
                        plot_dtrace(
                            axes2, dtrace, space, 0., 1.,
                            fc=light(misfit_color, 0.3),
                            ec=misfit_color)

                    plot_trace(
                        axes, result.filtered_syn,
                        color=syn_color_light, lw=1.0)

                    plot_trace(
                        axes, result.filtered_obs,
                        color=obs_color_light, lw=0.75)

                    plot_trace(
                        axes, result.processed_syn,
                        color=syn_color, lw=1.0)

                    plot_trace(
                        axes, result.processed_obs,
                        color=obs_color, lw=0.75)

                    # xdata = result.filtered_obs.get_xdata()

                    tmarks = [
                        result.processed_obs.tmin,
                        result.processed_obs.tmax]

                    for tmark in tmarks:
                        axes2.plot(
                            [tmark, tmark], [-0.9, 0.1], color=tap_color_annot)

                    dur = tmarks[1] - tmarks[0]
                    for tmark, text, ha in [
                            (tmarks[0],
                             '$\\,$ ' + meta.str_duration(
                                 tmarks[0] - source.time),
                             'left'),
                            (tmarks[1],
                             '$\\Delta$ ' + meta.str_duration(dur),
                             'right')]:

                        axes2.annotate(
                            text,
                            xy=(tmark, -0.9),
                            xycoords='data',
                            xytext=(
                                fontsize * 0.4 * [-1, 1][ha == 'left'],
                                fontsize * 0.2),
                            textcoords='offset points',
                            ha=ha,
                            va='bottom',
                            color=tap_color_annot,
                            fontsize=fontsize)

                    axes2.set_xlim(tmarks[0] - dur*0.1, tmarks[1] + dur*0.1)

                    rel_w = ws[itarget] / w_max
                    rel_c = gcms[itarget] / gcm_max

                    sw = 0.25
                    sh = 0.1
                    ph = 0.01

                    for (ih, rw, facecolor, edgecolor) in [
                            (0, rel_w, light(weight_color, 0.5),
                             weight_color),
                            (1, rel_c, light(misfit_color, 0.5),
                             misfit_color)]:

                        bar = patches.Rectangle(
                            (1.0 - rw * sw, 1.0 - (ih + 1) * sh + ph),
                            rw * sw,
                            sh - 2 * ph,
                            facecolor=facecolor, edgecolor=edgecolor,
                            zorder=10,
                            transform=axes.transAxes, clip_on=False)

                        axes.add_patch(bar)

                    scale_string = None

                    if target.misfit_config.domain == 'cc_max_norm':
                        scale_string = 'Syn/obs scales differ!'

                    infos = []
                    if scale_string:
                        infos.append(scale_string)

                    if self.nx == 1 and self.ny == 1:
                        infos.append(target.string_id())
                    else:
                        infos.append('.'.join(x for x in target.codes if x))

                    dist = source.distance_to(target)
                    azi = source.azibazi_to(target)[0]
                    infos.append(meta.str_dist(dist))
                    infos.append('%.0f\u00B0' % azi)
                    infos.append('%.3g' % ws[itarget])
                    infos.append('%.3g' % gcms[itarget])
                    axes2.annotate(
                        '\n'.join(infos),
                        xy=(0., 1.),
                        xycoords='axes fraction',
                        xytext=(2., 2.),
                        textcoords='offset points',
                        ha='left',
                        va='top',
                        fontsize=fontsize,
                        fontstyle='normal')

                    if (self.nx == 1 and self.ny == 1):
                        yield item, fig
                        del figures[iyy, ixx]

            if not (self.nx == 1 and self.ny == 1):
                for (iyy, ixx), (_, fig) in figures.items():
                    title = '.'.join(x for x in cg if x)
                    if len(figures) > 1:
                        title += ' (%i/%i, %i/%i)' % (
                            iyy + 1, nyy, ixx + 1, nxx)

                    fig.suptitle(title, fontsize=fontsize_title)

            for item, fig in figures.values():
                yield item, fig
Пример #4
0
    def draw_figures(self, ds, history, optimiser):

        color_parameter = self.color_parameter
        misfit_cutoff = self.misfit_cutoff
        fontsize = self.font_size
        fontsize_title = self.font_size_title

        nxmax = self.nx
        nymax = self.ny

        problem = history.problem

        for target in problem.targets:
            target.set_dataset(ds)

        target_index = {}
        i = 0
        for target in problem.targets:
            target_index[target] = i, i+target.nmisfits
            i += target.nmisfits

        gms = history.get_sorted_primary_misfits()[::-1]
        models = history.get_sorted_primary_models()[::-1]

        if misfit_cutoff is not None:
            ibest = gms < misfit_cutoff
            gms = gms[ibest]
            models = models[ibest]

        gms = gms[::10]
        models = models[::10]

        nmodels = models.shape[0]
        if color_parameter == 'dist':
            mx = num.mean(models, axis=0)
            cov = num.cov(models.T)
            mdists = core.mahalanobis_distance(models, mx, cov)
            icolor = meta.ordersort(mdists)

        elif color_parameter == 'misfit':
            iorder = num.arange(nmodels)
            icolor = iorder

        elif color_parameter in problem.parameter_names:
            ind = problem.name_to_index(color_parameter)
            icolor = problem.extract(models, ind)

        target_to_results = defaultdict(list)
        all_syn_trs = []

        dtraces = []
        for imodel in range(nmodels):
            model = models[imodel, :]

            source = problem.get_source(model)
            results = problem.evaluate(model)

            dtraces.append([])

            for target, result in zip(problem.targets, results):
                w = target.get_combined_weight()

                if isinstance(result, gf.SeismosizerError) or \
                        not isinstance(target, WaveformMisfitTarget) or \
                        not num.all(num.isfinite(w)):

                    dtraces[-1].extend([None] * target.nmisfits)
                    continue

                itarget, itarget_end = target_index[target]
                assert itarget_end == itarget + 1

                if target.misfit_config.domain == 'cc_max_norm':
                    tref = (
                        result.filtered_obs.tmin + result.filtered_obs.tmax) \
                        * 0.5

                    for tr_filt, tr_proc, tshift in (
                            (result.filtered_obs,
                             result.processed_obs,
                             0.),
                            (result.filtered_syn,
                             result.processed_syn,
                             result.tshift)):

                        norm = num.sum(num.abs(tr_proc.ydata)) \
                            / tr_proc.data_len()
                        tr_filt.ydata /= norm
                        tr_proc.ydata /= norm

                        tr_filt.shift(tshift)
                        tr_proc.shift(tshift)

                    ctr = result.cc
                    ctr.shift(tref)

                    dtrace = ctr

                else:
                    for tr in (
                            result.filtered_obs,
                            result.filtered_syn,
                            result.processed_obs,
                            result.processed_syn):

                        tr.ydata *= w

                    if result.tshift is not None and result.tshift != 0.0:
                        # result.filtered_syn.shift(result.tshift)
                        result.processed_syn.shift(result.tshift)

                    dtrace = make_norm_trace(
                        result.processed_syn, result.processed_obs,
                        problem.norm_exponent)

                target_to_results[target].append(result)

                dtrace.meta = dict(
                    normalisation_family=target.normalisation_family,
                    path=target.path)

                dtraces[-1].append(dtrace)

                result.processed_syn.meta = dict(
                    normalisation_family=target.normalisation_family,
                    path=target.path)

                all_syn_trs.append(result.processed_syn)

        if not all_syn_trs:
            logger.warn('No traces to show!')
            return

        def skey(tr):
            return tr.meta['normalisation_family'], tr.meta['path']

        trace_minmaxs = trace.minmax(all_syn_trs, skey)

        dtraces_all = []
        for dtraces_group in dtraces:
            dtraces_all.extend(dtraces_group)

        dminmaxs = trace.minmax([
            dtrace_ for dtrace_ in dtraces_all if dtrace_ is not None], skey)

        for tr in dtraces_all:
            if tr:
                dmin, dmax = dminmaxs[skey(tr)]
                tr.ydata /= max(abs(dmin), abs(dmax))

        cg_to_targets = meta.gather(
            problem.waveform_targets,
            lambda t: (t.path, t.codes[3]),
            filter=lambda t: t in target_to_results)

        cgs = sorted(cg_to_targets.keys())

        from matplotlib import colors
        cmap = cm.ScalarMappable(
            norm=colors.Normalize(vmin=num.min(icolor), vmax=num.max(icolor)),
            cmap=plt.get_cmap('coolwarm'))

        imodel_to_color = []
        for imodel in range(nmodels):
            imodel_to_color.append(cmap.to_rgba(icolor[imodel]))

        for cg in cgs:
            targets = cg_to_targets[cg]

            frame_to_target, nx, ny, nxx, nyy = layout(
                source, targets, nxmax, nymax)

            figures = {}
            for iy in range(ny):
                for ix in range(nx):
                    if (iy, ix) not in frame_to_target:
                        continue

                    ixx = ix // nxmax
                    iyy = iy // nymax
                    if (iyy, ixx) not in figures:
                        title = '_'.join(x for x in cg if x)
                        item = PlotItem(
                            name='fig_%s_%i_%i' % (title, ixx, iyy))
                        item.attributes['targets'] = []
                        figures[iyy, ixx] = (
                            item, plt.figure(figsize=self.size_inch))

                        figures[iyy, ixx][1].subplots_adjust(
                            left=0.03,
                            right=1.0 - 0.03,
                            bottom=0.03,
                            top=1.0 - 0.06,
                            wspace=0.2,
                            hspace=0.2)

                    item, fig = figures[iyy, ixx]

                    target = frame_to_target[iy, ix]

                    item.attributes['targets'].append(target.string_id())

                    amin, amax = trace_minmaxs[
                        target.normalisation_family, target.path]
                    absmax = max(abs(amin), abs(amax))

                    ny_this = nymax  # min(ny, nymax)
                    nx_this = nxmax  # min(nx, nxmax)
                    i_this = (iy % ny_this) * nx_this + (ix % nx_this) + 1

                    axes2 = fig.add_subplot(ny_this, nx_this, i_this)

                    space = 0.5
                    space_factor = 1.0 + space
                    axes2.set_axis_off()
                    axes2.set_ylim(-1.05 * space_factor, 1.05)

                    axes = axes2.twinx()
                    axes.set_axis_off()

                    if target.misfit_config.domain == 'cc_max_norm':
                        axes.set_ylim(-10. * space_factor, 10.)
                    else:
                        axes.set_ylim(-absmax*1.33 * space_factor, absmax*1.33)

                    itarget, itarget_end = target_index[target]
                    assert itarget_end == itarget + 1

                    for imodel, result in enumerate(target_to_results[target]):

                        syn_color = imodel_to_color[imodel]

                        dtrace = dtraces[imodel][itarget]

                        tap_color_annot = (0.35, 0.35, 0.25)
                        tap_color_edge = (0.85, 0.85, 0.80)
                        tap_color_fill = (0.95, 0.95, 0.90)

                        plot_taper(
                            axes2,
                            result.processed_obs.get_xdata(),
                            result.taper,
                            fc=tap_color_fill, ec=tap_color_edge, alpha=0.2)

                        obs_color = mpl_color('aluminium5')
                        obs_color_light = light(obs_color, 0.5)

                        plot_dtrace(
                            axes2, dtrace, space, 0., 1.,
                            fc='none',
                            ec=syn_color)

                        # plot_trace(
                        #     axes, result.filtered_syn,
                        #     color=syn_color_light, lw=1.0)

                        if imodel == 0:
                            plot_trace(
                                axes, result.filtered_obs,
                                color=obs_color_light, lw=0.75)

                        plot_trace(
                            axes, result.processed_syn,
                            color=syn_color, lw=1.0, alpha=0.3)

                        plot_trace(
                            axes, result.processed_obs,
                            color=obs_color, lw=0.75, alpha=0.3)

                        if imodel != 0:
                            continue
                        xdata = result.filtered_obs.get_xdata()
                        axes.set_xlim(xdata[0], xdata[-1])

                        tmarks = [
                            result.processed_obs.tmin,
                            result.processed_obs.tmax]

                        for tmark in tmarks:
                            axes2.plot(
                                [tmark, tmark], [-0.9, 0.1],
                                color=tap_color_annot)

                        dur = tmarks[1] - tmarks[0]
                        for tmark, text, ha in [
                                (tmarks[0],
                                 '$\\,$ ' + meta.str_duration(
                                    tmarks[0] - source.time),
                                 'left'),
                                (tmarks[1],
                                 '$\\Delta$ ' + meta.str_duration(
                                    dur),
                                 'right')]:

                            axes2.annotate(
                                text,
                                xy=(tmark, -0.9),
                                xycoords='data',
                                xytext=(
                                    fontsize*0.4 * [-1, 1][ha == 'left'],
                                    fontsize*0.2),
                                textcoords='offset points',
                                ha=ha,
                                va='bottom',
                                color=tap_color_annot,
                                fontsize=fontsize)

                        axes2.set_xlim(
                            tmarks[0] - dur*0.1, tmarks[1] + dur*0.1)

                    scale_string = None

                    if target.misfit_config.domain == 'cc_max_norm':
                        scale_string = 'Syn/obs scales differ!'

                    infos = []
                    if scale_string:
                        infos.append(scale_string)

                    if self.nx == 1 and self.ny == 1:
                        infos.append(target.string_id())
                    else:
                        infos.append('.'.join(x for x in target.codes if x))
                    dist = source.distance_to(target)
                    azi = source.azibazi_to(target)[0]
                    infos.append(meta.str_dist(dist))
                    infos.append(u'%.0f\u00B0' % azi)
                    axes2.annotate(
                        '\n'.join(infos),
                        xy=(0., 1.),
                        xycoords='axes fraction',
                        xytext=(2., 2.),
                        textcoords='offset points',
                        ha='left',
                        va='top',
                        fontsize=fontsize,
                        fontstyle='normal')

                    if (self.nx == 1 and self.ny == 1):
                        yield item, fig
                        del figures[iyy, ixx]

            if not (self.nx == 1 and self.ny == 1):
                for (iyy, ixx), (_, fig) in figures.items():
                    title = '.'.join(x for x in cg if x)
                    if len(figures) > 1:
                        title += ' (%i/%i, %i/%i)' % (iyy+1, nyy, ixx+1, nxx)

                    fig.suptitle(title, fontsize=fontsize_title)

            for item, fig in figures.values():
                yield item, fig
Пример #5
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()
Пример #6
0
 def yminmax(self, traces):
     return trace.minmax(traces, key=self.map_yscaling)
Пример #7
0
def seismic_fits(problem, stage, plot_options):
    """
    Modified from grond. Plot synthetic and data waveforms and the misfit for
    the selected posterior model.
    """

    fontsize = 8
    fontsize_title = 10

    target_index = dict(
        (target, i) for (i, target) in enumerate(problem.stargets))

    po = plot_options

    population, _, llk = stage.step.select_end_points(stage.mtrace)

    posterior_idxs = get_fit_indexes(llk)
    idx = posterior_idxs[po.post_llk]

    n_steps = problem.config.sampler_config.parameters.n_steps - 1
    d = stage.mtrace.point(idx=n_steps, chain=idx)
    gcms = d['seis_like']
    gcm_max = d['like']

    out_point = population[idx]

    results = problem.assemble_seismic_results(out_point)
    source = problem.sources[0]

    logger.info('Plotting waveforms ...')
    target_to_result = {}
    all_syn_trs = []
    dtraces = []
    for target in problem.stargets:
        i = target_index[target]
        target_to_result[target] = results[i]

        all_syn_trs.append(results[i].processed_syn)
        dtraces.append(results[i].processed_res)

    skey = lambda tr: tr.channel

    trace_minmaxs = trace.minmax(all_syn_trs, skey)
    dminmaxs = trace.minmax(dtraces, skey)

    for tr in dtraces:
        if tr:
            dmin, dmax = dminmaxs[skey(tr)]
            tr.ydata /= max(abs(dmin), abs(dmax))

    cg_to_targets = utility.gather(
        problem.stargets,
        lambda t: t.codes[3],
        filter=lambda t: t in target_to_result)

    cgs = cg_to_targets.keys()

    figs = []

    for cg in cgs:
        targets = cg_to_targets[cg]

        # can keep from here ... until
        nframes = len(targets)

        nx = int(math.ceil(math.sqrt(nframes)))
        ny = (nframes - 1) / nx + 1

        nxmax = 4
        nymax = 4

        nxx = (nx - 1) / nxmax + 1
        nyy = (ny - 1) / nymax + 1

        xs = num.arange(nx) / ((max(2, nx) - 1.0) / 2.)
        ys = num.arange(ny) / ((max(2, ny) - 1.0) / 2.)

        xs -= num.mean(xs)
        ys -= num.mean(ys)

        fxs = num.tile(xs, ny)
        fys = num.repeat(ys, nx)

        data = []

        for target in targets:
            azi = source.azibazi_to(target)[0]
            dist = source.distance_to(target)
            x = dist * num.sin(num.deg2rad(azi))
            y = dist * num.cos(num.deg2rad(azi))
            data.append((x, y, dist))

        gxs, gys, dists = num.array(data, dtype=num.float).T

        iorder = num.argsort(dists)

        gxs = gxs[iorder]
        gys = gys[iorder]
        targets_sorted = [targets[ii] for ii in iorder]

        gxs -= num.mean(gxs)
        gys -= num.mean(gys)

        gmax = max(num.max(num.abs(gys)), num.max(num.abs(gxs)))
        if gmax == 0.:
            gmax = 1.

        gxs /= gmax
        gys /= gmax

        dists = num.sqrt(
            (fxs[num.newaxis, :] - gxs[:, num.newaxis]) ** 2 +
            (fys[num.newaxis, :] - gys[:, num.newaxis]) ** 2)

        distmax = num.max(dists)

        availmask = num.ones(dists.shape[1], dtype=num.bool)
        frame_to_target = {}
        for itarget, target in enumerate(targets_sorted):
            iframe = num.argmin(
                num.where(availmask, dists[itarget], distmax + 1.))
            availmask[iframe] = False
            iy, ix = num.unravel_index(iframe, (ny, nx))
            frame_to_target[iy, ix] = target

        figures = {}
        for iy in xrange(ny):
            for ix in xrange(nx):
                if (iy, ix) not in frame_to_target:
                    continue

                ixx = ix / nxmax
                iyy = iy / nymax
                if (iyy, ixx) not in figures:
                    figures[iyy, ixx] = plt.figure(
                        figsize=mpl_papersize('a4', 'landscape'))

                    figures[iyy, ixx].subplots_adjust(
                        left=0.03,
                        right=1.0 - 0.03,
                        bottom=0.03,
                        top=1.0 - 0.06,
                        wspace=0.2,
                        hspace=0.2)

                    figs.append(figures[iyy, ixx])

                fig = figures[iyy, ixx]

                target = frame_to_target[iy, ix]

                amin, amax = trace_minmaxs[target.codes[3]]
                absmax = max(abs(amin), abs(amax))

                ny_this = nymax  # min(ny, nymax)
                nx_this = nxmax  # min(nx, nxmax)
                i_this = (iy % ny_this) * nx_this + (ix % nx_this) + 1

                axes2 = fig.add_subplot(ny_this, nx_this, i_this)

                space = 0.5
                space_factor = 1.0 + space
                axes2.set_axis_off()
                axes2.set_ylim(-1.05 * space_factor, 1.05)

                axes = axes2.twinx()
                axes.set_axis_off()

                axes.set_ylim(- absmax * 1.33 * space_factor, absmax * 1.33)

                itarget = target_index[target]
                result = target_to_result[target]

                dtrace = dtraces[itarget]

                tap_color_annot = (0.35, 0.35, 0.25)
                tap_color_edge = (0.85, 0.85, 0.80)
                tap_color_fill = (0.95, 0.95, 0.90)

                plot_taper(
                    axes2, result.processed_obs.get_xdata(), result.taper,
                    fc=tap_color_fill, ec=tap_color_edge)

                obs_color = scolor('aluminium5')
                obs_color_light = light(obs_color, 0.5)

                syn_color = scolor('scarletred2')
                syn_color_light = light(syn_color, 0.5)

                misfit_color = scolor('scarletred2')

                plot_dtrace(
                    axes2, dtrace, space, 0., 1.,
                    fc=light(misfit_color, 0.3),
                    ec=misfit_color)

                plot_trace(
                    axes, result.filtered_syn,
                    color=syn_color_light, lw=1.0)

                plot_trace(
                    axes, result.filtered_obs,
                    color=obs_color_light, lw=0.75)

                plot_trace(
                    axes, result.processed_syn,
                    color=syn_color, lw=1.0)

                plot_trace(
                    axes, result.processed_obs,
                    color=obs_color, lw=0.75)

                xdata = result.filtered_obs.get_xdata()
                axes.set_xlim(xdata[0], xdata[-1])

                tmarks = [
                    result.processed_obs.tmin,
                    result.processed_obs.tmax]

                for tmark in tmarks:
                    axes2.plot(
                        [tmark, tmark], [-0.9, 0.1], color=tap_color_annot)

                for tmark, text, ha, va in [
                        (tmarks[0],
                         '$\,$ ' + str_duration(tmarks[0] - source.time),
                         'right',
                         'bottom'),
                        (tmarks[1],
                         '$\Delta$ ' + str_duration(tmarks[1] - tmarks[0]),
                         'left',
                         'top')]:

                    axes2.annotate(
                        text,
                        xy=(tmark, -0.9),
                        xycoords='data',
                        xytext=(
                            fontsize * 0.4 * [-1, 1][ha == 'left'],
                            fontsize * 0.2),
                        textcoords='offset points',
                        ha=ha,
                        va=va,
                        color=tap_color_annot,
                        fontsize=fontsize)

#                rel_c = num.exp(gcms[itarget] - gcm_max)

#                sw = 0.25
#                sh = 0.1
#                ph = 0.01

#                for (ih, rw, facecolor, edgecolor) in [
#                        (1, rel_c,  light(misfit_color, 0.5), misfit_color)]:

#                    bar = patches.Rectangle(
#                        (1.0 - rw * sw, 1.0 - (ih + 1) * sh + ph),
#                        rw * sw,
#                        sh - 2 * ph,
#                        facecolor=facecolor, edgecolor=edgecolor,
#                        zorder=10,
#                        transform=axes.transAxes, clip_on=False)

#                    axes.add_patch(bar)

                scale_string = None

                infos = []
                if scale_string:
                    infos.append(scale_string)

                infos.append('.'.join(x for x in target.codes if x))
                dist = source.distance_to(target)
                azi = source.azibazi_to(target)[0]
                infos.append(str_dist(dist))
                infos.append(u'%.0f\u00B0' % azi)
                infos.append('%.3f' % gcms[itarget])
                axes2.annotate(
                    '\n'.join(infos),
                    xy=(0., 1.),
                    xycoords='axes fraction',
                    xytext=(2., 2.),
                    textcoords='offset points',
                    ha='left',
                    va='top',
                    fontsize=fontsize,
                    fontstyle='normal')

        for (iyy, ixx), fig in figures.iteritems():
            title = '.'.join(x for x in cg if x)
            if len(figures) > 1:
                title += ' (%i/%i, %i/%i)' % (iyy + 1, nyy, ixx + 1, nxx)

            fig.suptitle(title, fontsize=fontsize_title)

    return figs
Пример #8
0
    def draw_figures(self, ds, history):

        fontsize = self.font_size
        fontsize_title = self.font_size_title

        problem = history.problem

        for target in problem.targets:
            target.set_dataset(ds)

        target_index = dict(
            (target, i) for (i, target) in enumerate(problem.targets))

        gms = problem.combine_misfits(history.misfits)
        isort = num.argsort(gms)
        gms = gms[isort]
        models = history.models[isort, :]
        misfits = history.misfits[isort, :]

        xbest = models[0, :]

        ws = problem.get_target_weights()

        gcms = problem.combine_misfits(misfits[:1, :, :],
                                       get_contributions=True)[0, :]

        w_max = num.nanmax(ws)
        gcm_max = num.nanmax(gcms)

        source = problem.get_source(xbest)

        target_to_result = {}
        all_syn_trs = []
        all_syn_specs = []
        results = problem.evaluate(xbest)

        dtraces = []
        for target, result in zip(problem.targets, results):
            if not isinstance(result, WaveformMisfitResult):
                dtraces.append(None)
                continue

            itarget = target_index[target]
            w = target.get_combined_weight()

            if target.misfit_config.domain == 'cc_max_norm':
                tref = (result.filtered_obs.tmin +
                        result.filtered_obs.tmax) * 0.5
                for tr_filt, tr_proc, tshift in ((result.filtered_obs,
                                                  result.processed_obs, 0.),
                                                 (result.filtered_syn,
                                                  result.processed_syn,
                                                  result.tshift)):

                    norm = num.sum(num.abs(tr_proc.ydata)) / tr_proc.data_len()
                    tr_filt.ydata /= norm
                    tr_proc.ydata /= norm

                    tr_filt.shift(tshift)
                    tr_proc.shift(tshift)

                ctr = result.cc
                ctr.shift(tref)

                dtrace = ctr

            else:
                for tr in (result.filtered_obs, result.filtered_syn,
                           result.processed_obs, result.processed_syn):

                    tr.ydata *= w

                for spec in (result.spectrum_obs, result.spectrum_syn):

                    if spec is not None:
                        spec.ydata *= w

                if result.tshift is not None and result.tshift != 0.0:
                    # result.filtered_syn.shift(result.tshift)
                    result.processed_syn.shift(result.tshift)

                dtrace = make_norm_trace(result.processed_syn,
                                         result.processed_obs,
                                         problem.norm_exponent)

            target_to_result[target] = result

            dtrace.meta = dict(
                normalisation_family=target.normalisation_family,
                path=target.path)
            dtraces.append(dtrace)

            result.processed_syn.meta = dict(
                normalisation_family=target.normalisation_family,
                path=target.path)

            all_syn_trs.append(result.processed_syn)

            if result.spectrum_syn:
                result.spectrum_syn.meta = dict(
                    normalisation_family=target.normalisation_family,
                    path=target.path)

                all_syn_specs.append(result.spectrum_syn)

        if not all_syn_trs:
            logger.warn('no traces to show')
            return []

        def skey(tr):
            return tr.meta['normalisation_family'], tr.meta['path']

        trace_minmaxs = trace.minmax(all_syn_trs, skey)

        amp_spec_maxs = amp_spec_max(all_syn_specs, skey)

        dminmaxs = trace.minmax([x for x in dtraces if x is not None], skey)

        for tr in dtraces:
            if tr:
                dmin, dmax = dminmaxs[skey(tr)]
                tr.ydata /= max(abs(dmin), abs(dmax))

        cg_to_targets = meta.gather(problem.waveform_targets,
                                    lambda t: (t.path, t.codes[3]),
                                    filter=lambda t: t in target_to_result)

        cgs = sorted(cg_to_targets.keys())

        figs = []
        for cg in cgs:
            targets = cg_to_targets[cg]
            nframes = len(targets)

            nx = int(math.ceil(math.sqrt(nframes)))
            ny = (nframes - 1) // nx + 1

            nxmax = 4
            nymax = 4

            nxx = (nx - 1) // nxmax + 1
            nyy = (ny - 1) // nymax + 1

            # nz = nxx * nyy

            xs = num.arange(nx) // ((max(2, nx) - 1.0) / 2.)
            ys = num.arange(ny) // ((max(2, ny) - 1.0) / 2.)

            xs -= num.mean(xs)
            ys -= num.mean(ys)

            fxs = num.tile(xs, ny)
            fys = num.repeat(ys, nx)

            data = []

            for target in targets:
                azi = source.azibazi_to(target)[0]
                dist = source.distance_to(target)
                x = dist * num.sin(num.deg2rad(azi))
                y = dist * num.cos(num.deg2rad(azi))
                data.append((x, y, dist))

            gxs, gys, dists = num.array(data, dtype=num.float).T

            iorder = num.argsort(dists)

            gxs = gxs[iorder]
            gys = gys[iorder]
            targets_sorted = [targets[ii] for ii in iorder]

            gxs -= num.mean(gxs)
            gys -= num.mean(gys)

            gmax = max(num.max(num.abs(gys)), num.max(num.abs(gxs)))
            if gmax == 0.:
                gmax = 1.

            gxs /= gmax
            gys /= gmax

            dists = num.sqrt((fxs[num.newaxis, :] - gxs[:, num.newaxis])**2 +
                             (fys[num.newaxis, :] - gys[:, num.newaxis])**2)

            distmax = num.max(dists)

            availmask = num.ones(dists.shape[1], dtype=num.bool)
            frame_to_target = {}
            for itarget, target in enumerate(targets_sorted):
                iframe = num.argmin(
                    num.where(availmask, dists[itarget], distmax + 1.))
                availmask[iframe] = False
                iy, ix = num.unravel_index(iframe, (ny, nx))
                frame_to_target[iy, ix] = target

            figures = {}
            for iy in range(ny):
                for ix in range(nx):
                    if (iy, ix) not in frame_to_target:
                        continue

                    ixx = ix // nxmax
                    iyy = iy // nymax
                    if (iyy, ixx) not in figures:
                        title = '_'.join(x for x in cg if x)
                        item = PlotItem(name='fig_%s_%i_%i' %
                                        (title, ixx, iyy))
                        item.attributes['targets'] = []
                        figures[iyy,
                                ixx] = (item,
                                        plt.figure(figsize=self.size_inch))

                        figures[iyy, ixx][1].subplots_adjust(left=0.03,
                                                             right=1.0 - 0.03,
                                                             bottom=0.03,
                                                             top=1.0 - 0.06,
                                                             wspace=0.2,
                                                             hspace=0.2)

                        figs.append(figures[iyy, ixx])

                    item, fig = figures[iyy, ixx]

                    target = frame_to_target[iy, ix]

                    item.attributes['targets'].append(target.string_id())

                    amin, amax = trace_minmaxs[target.normalisation_family,
                                               target.path]
                    absmax = max(abs(amin), abs(amax))

                    ny_this = nymax  # min(ny, nymax)
                    nx_this = nxmax  # min(nx, nxmax)
                    i_this = (iy % ny_this) * nx_this + (ix % nx_this) + 1

                    axes2 = fig.add_subplot(ny_this, nx_this, i_this)

                    space = 0.5
                    space_factor = 1.0 + space
                    axes2.set_axis_off()
                    axes2.set_ylim(-1.05 * space_factor, 1.05)

                    axes = axes2.twinx()
                    axes.set_axis_off()

                    if target.misfit_config.domain == 'cc_max_norm':
                        axes.set_ylim(-10. * space_factor, 10.)
                    else:
                        axes.set_ylim(-absmax * 1.33 * space_factor,
                                      absmax * 1.33)

                    itarget = target_index[target]
                    result = target_to_result[target]

                    dtrace = dtraces[itarget]

                    tap_color_annot = (0.35, 0.35, 0.25)
                    tap_color_edge = (0.85, 0.85, 0.80)
                    tap_color_fill = (0.95, 0.95, 0.90)

                    plot_taper(axes2,
                               result.processed_obs.get_xdata(),
                               result.taper,
                               fc=tap_color_fill,
                               ec=tap_color_edge)

                    obs_color = mpl_color('aluminium5')
                    obs_color_light = light(obs_color, 0.5)

                    syn_color = mpl_color('scarletred2')
                    syn_color_light = light(syn_color, 0.5)

                    misfit_color = mpl_color('scarletred2')
                    weight_color = mpl_color('chocolate2')

                    cc_color = mpl_color('aluminium5')

                    if target.misfit_config.domain == 'cc_max_norm':
                        tref = (result.filtered_obs.tmin +
                                result.filtered_obs.tmax) * 0.5

                        plot_dtrace(axes2,
                                    dtrace,
                                    space,
                                    -1.,
                                    1.,
                                    fc=light(cc_color, 0.5),
                                    ec=cc_color)

                        plot_dtrace_vline(axes2,
                                          tref,
                                          space,
                                          color=tap_color_annot)

                    elif target.misfit_config.domain == 'frequency_domain':

                        asmax = amp_spec_maxs[target.normalisation_family,
                                              target.path]
                        fmin, fmax = \
                            target.misfit_config.get_full_frequency_range()

                        plot_spectrum(axes2,
                                      result.spectrum_syn,
                                      result.spectrum_obs,
                                      fmin,
                                      fmax,
                                      space,
                                      0.,
                                      asmax,
                                      syn_color=syn_color,
                                      obs_color=obs_color,
                                      syn_lw=1.0,
                                      obs_lw=0.75,
                                      color_vline=tap_color_annot,
                                      fontsize=fontsize)

                    else:
                        plot_dtrace(axes2,
                                    dtrace,
                                    space,
                                    0.,
                                    1.,
                                    fc=light(misfit_color, 0.3),
                                    ec=misfit_color)

                    plot_trace(axes,
                               result.filtered_syn,
                               color=syn_color_light,
                               lw=1.0)

                    plot_trace(axes,
                               result.filtered_obs,
                               color=obs_color_light,
                               lw=0.75)

                    plot_trace(axes,
                               result.processed_syn,
                               color=syn_color,
                               lw=1.0)

                    plot_trace(axes,
                               result.processed_obs,
                               color=obs_color,
                               lw=0.75)

                    xdata = result.filtered_obs.get_xdata()
                    axes.set_xlim(xdata[0], xdata[-1])

                    tmarks = [
                        result.processed_obs.tmin, result.processed_obs.tmax
                    ]

                    for tmark in tmarks:
                        axes2.plot([tmark, tmark], [-0.9, 0.1],
                                   color=tap_color_annot)

                    for tmark, text, ha in [
                        (tmarks[0],
                         '$\\,$ ' + meta.str_duration(tmarks[0] - source.time),
                         'right'),
                        (tmarks[1], '$\\Delta$ ' +
                         meta.str_duration(tmarks[1] - tmarks[0]), 'left')
                    ]:

                        axes2.annotate(
                            text,
                            xy=(tmark, -0.9),
                            xycoords='data',
                            xytext=(fontsize * 0.4 * [-1, 1][ha == 'left'],
                                    fontsize * 0.2),
                            textcoords='offset points',
                            ha=ha,
                            va='bottom',
                            color=tap_color_annot,
                            fontsize=fontsize)

                    rel_w = ws[itarget] / w_max
                    rel_c = gcms[itarget] / gcm_max

                    sw = 0.25
                    sh = 0.1
                    ph = 0.01

                    for (ih, rw, facecolor, edgecolor) in [
                        (0, rel_w, light(weight_color, 0.5), weight_color),
                        (1, rel_c, light(misfit_color, 0.5), misfit_color)
                    ]:

                        bar = patches.Rectangle(
                            (1.0 - rw * sw, 1.0 - (ih + 1) * sh + ph),
                            rw * sw,
                            sh - 2 * ph,
                            facecolor=facecolor,
                            edgecolor=edgecolor,
                            zorder=10,
                            transform=axes.transAxes,
                            clip_on=False)

                        axes.add_patch(bar)

                    scale_string = None

                    if target.misfit_config.domain == 'cc_max_norm':
                        scale_string = 'Syn/obs scales differ!'

                    infos = []
                    if scale_string:
                        infos.append(scale_string)

                    infos.append('.'.join(x for x in target.codes if x))
                    dist = source.distance_to(target)
                    azi = source.azibazi_to(target)[0]
                    infos.append(meta.str_dist(dist))
                    infos.append('%.0f\u00B0' % azi)
                    infos.append('%.3g' % ws[itarget])
                    infos.append('%.3g' % gcms[itarget])
                    axes2.annotate('\n'.join(infos),
                                   xy=(0., 1.),
                                   xycoords='axes fraction',
                                   xytext=(2., 2.),
                                   textcoords='offset points',
                                   ha='left',
                                   va='top',
                                   fontsize=fontsize,
                                   fontstyle='normal')

            for (iyy, ixx), (_, fig) in figures.items():
                title = '.'.join(x for x in cg if x)
                if len(figures) > 1:
                    title += ' (%i/%i, %i/%i)' % (iyy + 1, nyy, ixx + 1, nxx)

                fig.suptitle(title, fontsize=fontsize_title)

        return figs
Пример #9
0
    def draw_figures(self, ds, history):

        color_parameter = self.color_parameter
        misfit_cutoff = self.misfit_cutoff
        fontsize = self.font_size
        fontsize_title = self.font_size_title

        problem = history.problem

        for target in problem.targets:
            target.set_dataset(ds)

        target_index = dict(
            (target, i) for (i, target) in enumerate(problem.targets))

        gms = problem.combine_misfits(history.misfits)
        isort = num.argsort(gms)[::-1]
        gms = gms[isort]
        models = history.models[isort, :]

        if misfit_cutoff is not None:
            ibest = gms < misfit_cutoff
            gms = gms[ibest]
            models = models[ibest]

        gms = gms[::10]
        models = models[::10]

        nmodels = models.shape[0]
        if color_parameter == 'dist':
            mx = num.mean(models, axis=0)
            cov = num.cov(models.T)
            mdists = core.mahalanobis_distance(models, mx, cov)
            icolor = meta.ordersort(mdists)

        elif color_parameter == 'misfit':
            iorder = num.arange(nmodels)
            icolor = iorder

        elif color_parameter in problem.parameter_names:
            ind = problem.name_to_index(color_parameter)
            icolor = problem.extract(models, ind)

        target_to_results = defaultdict(list)
        all_syn_trs = []

        dtraces = []
        for imodel in range(nmodels):
            model = models[imodel, :]

            source = problem.get_source(model)
            results = problem.evaluate(model)

            dtraces.append([])

            for target, result in zip(problem.targets, results):
                if isinstance(result, gf.SeismosizerError):
                    dtraces[-1].append(None)
                    continue

                if not isinstance(target, WaveformMisfitTarget):
                    dtraces[-1].append(None)
                    continue

                itarget = target_index[target]
                w = target.get_combined_weight()

                if target.misfit_config.domain == 'cc_max_norm':
                    tref = (
                        result.filtered_obs.tmin + result.filtered_obs.tmax) \
                        * 0.5

                    for tr_filt, tr_proc, tshift in ((result.filtered_obs,
                                                      result.processed_obs,
                                                      0.),
                                                     (result.filtered_syn,
                                                      result.processed_syn,
                                                      result.tshift)):

                        norm = num.sum(num.abs(tr_proc.ydata)) \
                            / tr_proc.data_len()
                        tr_filt.ydata /= norm
                        tr_proc.ydata /= norm

                        tr_filt.shift(tshift)
                        tr_proc.shift(tshift)

                    ctr = result.cc
                    ctr.shift(tref)

                    dtrace = ctr

                else:
                    for tr in (result.filtered_obs, result.filtered_syn,
                               result.processed_obs, result.processed_syn):

                        tr.ydata *= w

                    if result.tshift is not None and result.tshift != 0.0:
                        # result.filtered_syn.shift(result.tshift)
                        result.processed_syn.shift(result.tshift)

                    dtrace = make_norm_trace(result.processed_syn,
                                             result.processed_obs,
                                             problem.norm_exponent)

                target_to_results[target].append(result)

                dtrace.meta = dict(
                    normalisation_family=target.normalisation_family,
                    path=target.path)

                dtraces[-1].append(dtrace)

                result.processed_syn.meta = dict(
                    normalisation_family=target.normalisation_family,
                    path=target.path)

                all_syn_trs.append(result.processed_syn)

        if not all_syn_trs:
            logger.warn('no traces to show')
            return []

        def skey(tr):
            return tr.meta['normalisation_family'], tr.meta['path']

        trace_minmaxs = trace.minmax(all_syn_trs, skey)

        dtraces_all = []
        for dtraces_group in dtraces:
            dtraces_all.extend(dtraces_group)

        dminmaxs = trace.minmax(
            [dtrace_ for dtrace_ in dtraces_all if dtrace_ is not None], skey)

        for tr in dtraces_all:
            if tr:
                dmin, dmax = dminmaxs[skey(tr)]
                tr.ydata /= max(abs(dmin), abs(dmax))

        cg_to_targets = meta.gather(problem.waveform_targets,
                                    lambda t: (t.path, t.codes[3]),
                                    filter=lambda t: t in target_to_results)

        cgs = sorted(cg_to_targets.keys())

        from matplotlib import colors
        cmap = cm.ScalarMappable(norm=colors.Normalize(vmin=num.min(icolor),
                                                       vmax=num.max(icolor)),
                                 cmap=plt.get_cmap('coolwarm'))

        imodel_to_color = []
        for imodel in range(nmodels):
            imodel_to_color.append(cmap.to_rgba(icolor[imodel]))

        figs = []
        for cg in cgs:
            targets = cg_to_targets[cg]
            nframes = len(targets)

            nx = int(math.ceil(math.sqrt(nframes)))
            ny = (nframes - 1) // nx + 1

            nxmax = 4
            nymax = 4

            nxx = (nx - 1) // nxmax + 1
            nyy = (ny - 1) // nymax + 1

            # nz = nxx * nyy

            xs = num.arange(nx) / ((max(2, nx) - 1.0) / 2.)
            ys = num.arange(ny) / ((max(2, ny) - 1.0) / 2.)

            xs -= num.mean(xs)
            ys -= num.mean(ys)

            fxs = num.tile(xs, ny)
            fys = num.repeat(ys, nx)

            data = []

            for target in targets:
                azi = source.azibazi_to(target)[0]
                dist = source.distance_to(target)
                x = dist * num.sin(num.deg2rad(azi))
                y = dist * num.cos(num.deg2rad(azi))
                data.append((x, y, dist))

            gxs, gys, dists = num.array(data, dtype=num.float).T

            iorder = num.argsort(dists)

            gxs = gxs[iorder]
            gys = gys[iorder]
            targets_sorted = [targets[ii] for ii in iorder]

            gxs -= num.mean(gxs)
            gys -= num.mean(gys)

            gmax = max(num.max(num.abs(gys)), num.max(num.abs(gxs)))
            if gmax == 0.:
                gmax = 1.

            gxs /= gmax
            gys /= gmax

            dists = num.sqrt((fxs[num.newaxis, :] - gxs[:, num.newaxis])**2 +
                             (fys[num.newaxis, :] - gys[:, num.newaxis])**2)

            distmax = num.max(dists)

            availmask = num.ones(dists.shape[1], dtype=num.bool)
            frame_to_target = {}
            for itarget, target in enumerate(targets_sorted):
                iframe = num.argmin(
                    num.where(availmask, dists[itarget], distmax + 1.))
                availmask[iframe] = False
                iy, ix = num.unravel_index(iframe, (ny, nx))
                frame_to_target[iy, ix] = target

            figures = {}
            for iy in range(ny):
                for ix in range(nx):
                    if (iy, ix) not in frame_to_target:
                        continue

                    ixx = ix // nxmax
                    iyy = iy // nymax
                    if (iyy, ixx) not in figures:
                        title = '_'.join(x for x in cg if x)
                        item = PlotItem(name='fig_%s_%i_%i' %
                                        (title, ixx, iyy))
                        item.attributes['targets'] = []
                        figures[iyy,
                                ixx] = (item,
                                        plt.figure(figsize=self.size_inch))

                        figures[iyy, ixx][1].subplots_adjust(left=0.03,
                                                             right=1.0 - 0.03,
                                                             bottom=0.03,
                                                             top=1.0 - 0.06,
                                                             wspace=0.2,
                                                             hspace=0.2)

                        figs.append(figures[iyy, ixx])

                    item, fig = figures[iyy, ixx]

                    target = frame_to_target[iy, ix]

                    item.attributes['targets'].append(target.string_id())

                    amin, amax = trace_minmaxs[target.normalisation_family,
                                               target.path]
                    absmax = max(abs(amin), abs(amax))

                    ny_this = nymax  # min(ny, nymax)
                    nx_this = nxmax  # min(nx, nxmax)
                    i_this = (iy % ny_this) * nx_this + (ix % nx_this) + 1

                    axes2 = fig.add_subplot(ny_this, nx_this, i_this)

                    space = 0.5
                    space_factor = 1.0 + space
                    axes2.set_axis_off()
                    axes2.set_ylim(-1.05 * space_factor, 1.05)

                    axes = axes2.twinx()
                    axes.set_axis_off()

                    if target.misfit_config.domain == 'cc_max_norm':
                        axes.set_ylim(-10. * space_factor, 10.)
                    else:
                        axes.set_ylim(-absmax * 1.33 * space_factor,
                                      absmax * 1.33)

                    itarget = target_index[target]
                    for imodel, result in enumerate(target_to_results[target]):

                        syn_color = imodel_to_color[imodel]

                        dtrace = dtraces[imodel][itarget]

                        tap_color_annot = (0.35, 0.35, 0.25)
                        tap_color_edge = (0.85, 0.85, 0.80)
                        tap_color_fill = (0.95, 0.95, 0.90)

                        plot_taper(axes2,
                                   result.processed_obs.get_xdata(),
                                   result.taper,
                                   fc=tap_color_fill,
                                   ec=tap_color_edge,
                                   alpha=0.2)

                        obs_color = mpl_color('aluminium5')
                        obs_color_light = light(obs_color, 0.5)

                        plot_dtrace(axes2,
                                    dtrace,
                                    space,
                                    0.,
                                    1.,
                                    fc='none',
                                    ec=syn_color)

                        # plot_trace(
                        #     axes, result.filtered_syn,
                        #     color=syn_color_light, lw=1.0)

                        if imodel == 0:
                            plot_trace(axes,
                                       result.filtered_obs,
                                       color=obs_color_light,
                                       lw=0.75)

                        plot_trace(axes,
                                   result.processed_syn,
                                   color=syn_color,
                                   lw=1.0,
                                   alpha=0.3)

                        plot_trace(axes,
                                   result.processed_obs,
                                   color=obs_color,
                                   lw=0.75,
                                   alpha=0.3)

                        if imodel != 0:
                            continue
                        xdata = result.filtered_obs.get_xdata()
                        axes.set_xlim(xdata[0], xdata[-1])

                        tmarks = [
                            result.processed_obs.tmin,
                            result.processed_obs.tmax
                        ]

                        for tmark in tmarks:
                            axes2.plot([tmark, tmark], [-0.9, 0.1],
                                       color=tap_color_annot)

                        for tmark, text, ha in [
                            (tmarks[0], '$\\,$ ' +
                             meta.str_duration(tmarks[0] - source.time),
                             'right'),
                            (tmarks[1], '$\\Delta$ ' +
                             meta.str_duration(tmarks[1] - tmarks[0]), 'left')
                        ]:

                            axes2.annotate(
                                text,
                                xy=(tmark, -0.9),
                                xycoords='data',
                                xytext=(fontsize * 0.4 * [-1, 1][ha == 'left'],
                                        fontsize * 0.2),
                                textcoords='offset points',
                                ha=ha,
                                va='bottom',
                                color=tap_color_annot,
                                fontsize=fontsize)

                    scale_string = None

                    if target.misfit_config.domain == 'cc_max_norm':
                        scale_string = 'Syn/obs scales differ!'

                    infos = []
                    if scale_string:
                        infos.append(scale_string)

                    infos.append('.'.join(x for x in target.codes if x))
                    dist = source.distance_to(target)
                    azi = source.azibazi_to(target)[0]
                    infos.append(meta.str_dist(dist))
                    infos.append(u'%.0f\u00B0' % azi)
                    axes2.annotate('\n'.join(infos),
                                   xy=(0., 1.),
                                   xycoords='axes fraction',
                                   xytext=(2., 2.),
                                   textcoords='offset points',
                                   ha='left',
                                   va='top',
                                   fontsize=fontsize,
                                   fontstyle='normal')

            for (iyy, ixx), (_, fig) in figures.items():
                title = '.'.join(x for x in cg if x)
                if len(figures) > 1:
                    title += ' (%i/%i, %i/%i)' % (iyy + 1, nyy, ixx + 1, nxx)

                fig.suptitle(title, fontsize=fontsize_title)

        return figs