Esempio n. 1
0
    def draw_figures(self, problem, dataset, history):

        event = problem.base_source
        targets = problem.gnss_targets

        for target in targets:
            target.set_dataset(dataset)
            comp_weights = target.component_weights()[0]

            ws_n = comp_weights[:, 0::3] / comp_weights.max()
            ws_e = comp_weights[:, 1::3] / comp_weights.max()
            ws_u = comp_weights[:, 2::3] / comp_weights.max()
            ws_e = num.array(ws_e[0]).flatten()
            ws_n = num.array(ws_n[0]).flatten()
            ws_u = num.array(ws_u[0]).flatten()

            if ws_n.size == 0:
                continue

            distances = target.distance_to(event)
            azimuths = od.azibazi_numpy(
                num.array(event.effective_lat)[num.newaxis],
                num.array(event.effective_lon)[num.newaxis],
                target.get_latlon()[:, 0],
                target.get_latlon()[:, 1])[0]
            labels = target.station_names

            item = PlotItem(name='station_distribution-N-%s' % target.path)
            fig, ax, legend = self.plot_station_distribution(
                azimuths,
                distances,
                ws_n,
                labels,
                legend_title='Weight, N components')

            yield (item, fig)

            item = PlotItem(name='station_distribution-E-%s' % target.path)
            fig, ax, legend = self.plot_station_distribution(
                azimuths,
                distances,
                ws_e,
                labels,
                legend_title='Weight, E components')

            yield (item, fig)

            item = PlotItem(name='station_distribution-U-%s' % target.path)
            fig, ax, legend = self.plot_station_distribution(
                azimuths,
                distances,
                ws_u,
                labels,
                legend_title='Weight, U components')

            yield (item, fig)
Esempio n. 2
0
    def draw_figures(self, sources, targets, results_list):
        results_list = list(zip(*results_list))
        for itarget, target, results in zip(
                range(len(targets)), targets, results_list):

            if isinstance(target, WaveformMisfitTarget) and results:
                item = PlotItem(name='t%i' % itarget)
                item.attributes['targets'] = [target.string_id()]
                fig = self.draw_figure(sources, target, results)
                if fig is not None:
                    yield item, fig
Esempio n. 3
0
    def draw_figures(self, history):
        problem = history.problem

        by_cluster = history.imodels_by_cluster(
            self.cluster_attribute)

        for icluster, percentage, imodels in by_cluster:
            misfits = history.misfits[imodels]
            models = history.models[imodels]

            mts = []
            for ix, x in enumerate(models):
                source = problem.get_source(x)
                mts.append(source.pyrocko_moment_tensor())

            best_mt = stats.get_best_source(
                problem, models, misfits).pyrocko_moment_tensor()

            fig = plt.figure(figsize=self.size_inch)
            fig.subplots_adjust(left=0., right=1., bottom=0., top=1.)
            axes = fig.add_subplot(1, 1, 1, aspect=1.0)

            if self.cluster_attribute is not None:
                color = cluster_color(icluster)
            else:
                color = 'black'

            beachball.plot_fuzzy_beachball_mpl_pixmap(
                mts, axes, best_mt,
                beachball_type='full',
                size=8.*math.sqrt(percentage/100.),
                position=(5., 5.),
                color_t=color,
                edgecolor='black',
                best_color=mpl_color('scarletred2'))

            if self.cluster_attribute is not None:
                axes.annotate(
                    cluster_label(icluster, percentage),
                    xy=(5., 0.),
                    xycoords='data',
                    xytext=(0., self.font_size/2.),
                    textcoords='offset points',
                    ha='center',
                    va='bottom',
                    color='black',
                    fontsize=self.font_size)

            axes.set_xlim(0., 10.)
            axes.set_ylim(0., 10.)
            axes.set_axis_off()

            item = PlotItem(
                name=(
                    'cluster_%i' % icluster
                    if icluster >= 0
                    else 'unclustered'))

            yield [item, fig]
Esempio n. 4
0
    def draw_figures(self, history, optimiser):

        fig = plt.figure()

        imodels = num.arange(history.nmodels)
        gms = history.bootstrap_misfits[:, 0]

        gms_softclip = num.where(gms > 1.0, 0.1 * num.log10(gms) + 1.0, gms)
        axes = fig.add_subplot(1, 1, 1)

        ibests = []
        for ibootstrap in range(history.nchains):
            # if ibootstrap ==0:
            #    global, no-bootstrapping misfits, chain
            #    gms = history.bootstrap_misfits[:, ibootstrap]
            #    gms_softclip = num.where(gms > 1.0,
            #                            0.1 * num.log10(gms) + 1.0,
            #                            gms)

            bms = history.bootstrap_misfits[:, ibootstrap]
            isort_bms = num.argsort(bms)[::-1]
            ibests.append(isort_bms[-1])

            bms_softclip = num.where(bms > 1.0, 0.1 * num.log10(bms) + 1.0,
                                     bms)
            axes.plot(imodels, bms_softclip[isort_bms], color='red', alpha=0.2)

        isort = num.argsort(gms)[::-1]
        iorder = num.empty(isort.size)
        iorder[isort] = imodels

        axes.plot(iorder[ibests], gms_softclip[ibests], 'x', color='black')

        m = num.median(gms_softclip[ibests])
        s = num.std(gms_softclip[ibests])
        axes.axhline(m + s, color='black', alpha=0.5)
        axes.axhline(m, color='black')
        axes.axhline(m - s, color='black', alpha=0.5)

        axes.plot(imodels, gms_softclip[isort], color='black')

        axes.set_xlim(imodels[0], imodels[-1])
        axes.set_xlabel(
            'Tested model, sorted descending by global misfit value')

        return [(PlotItem(name='main'), fig)]
Esempio n. 5
0
    def draw_figures(self, history):
        problem = history.problem

        fig = plt.figure(figsize=self.size_inch)
        axes = fig.gca()

        gms = problem.combine_misfits(history.misfits)

        isort = num.argsort(gms)[::-1]

        gms = gms[isort]
        models = history.models[isort, :]

        kwargs = {
            'beachball_type': 'full',
            'size': 8,
            'position': (5, 5),
            'color_t': 'black',
            'edgecolor': 'black'
        }

        mts = []
        for ix, x in enumerate(models):
            if random.random() < 0.1:
                source = problem.get_source(x)
                mts.append(source.pyrocko_moment_tensor())

        best_mt = mts[-1]

        beachball.plot_fuzzy_beachball_mpl_pixmap(mts, axes, best_mt, **kwargs)

        axes.set_xlim(0., 10.)
        axes.set_ylim(0., 10.)
        axes.set_axis_off()

        item = PlotItem(
            name='main',
            title='Fuzzy Moment Tensor',
            description='The opaqueness illustrates the propability'
            ' of all combined moment tensor solution.'
            'The red lines indicate the global best solution.')
        return [[item, fig]]
Esempio n. 6
0
    def draw_figures(self, problem, dataset, history):

        event = problem.base_source
        targets = problem.gnss_targets

        for target in targets:
            target.set_dataset(dataset)
            ws = target.station_weights / target.station_weights.max()

            distances = target.distance_to(event)
            azimuths = od.azibazi_numpy(
                num.array(event.effective_lat)[num.newaxis],
                num.array(event.effective_lon)[num.newaxis],
                target.get_latlon()[:, 0],
                target.get_latlon()[:, 1])[0]
            labels = target.station_names

            item = PlotItem(name='station_distribution-%s' % target.path)
            fig, ax, legend = self.plot_station_distribution(
                azimuths, distances, ws, labels)
            legend.set_title('Weight')

            yield (item, fig)
Esempio n. 7
0
    def draw_figures(self, history):

        fontsize = self.font_size

        fig = plt.figure(figsize=self.size_inch)
        axes = fig.add_subplot(1, 1, 1, aspect=1.0)
        fig.subplots_adjust(left=0., right=1., bottom=0., top=1.)

        problem = history.problem
        models = history.models

        if models.size == 0:
            logger.warn('Empty models vector.')
            return []

        # gms = problem.combine_misfits(history.misfits)
        # isort = num.argsort(gms)
        # iorder = num.empty_like(isort)
        # iorder[isort] = num.arange(iorder.size)[::-1]

        ref_source = problem.base_source

        mean_source = stats.get_mean_source(
            problem, history.models)

        best_source = history.get_best_source()

        nlines_max = int(round(self.size_cm[1] / 5. * 4. - 1.0))

        if self.cluster_attribute:
            cluster_sources = history.mean_sources_by_cluster(
                self.cluster_attribute)
        else:
            cluster_sources = []

        def get_deco(source):
            mt = source.pyrocko_moment_tensor()
            return mt.standard_decomposition()

        lines = []
        lines.append(
            ('Ensemble best', get_deco(best_source), mpl_color('aluminium5')))

        lines.append(
            ('Ensemble mean', get_deco(mean_source), mpl_color('aluminium5')))

        for (icluster, perc, source) in cluster_sources:
            if len(lines) < nlines_max - int(self.show_reference):
                lines.append(
                    (cluster_label(icluster, perc),
                     get_deco(source),
                     cluster_color(icluster)))
            else:
                logger.warn(
                    'Skipping display of cluster %i because figure height is '
                    'too small. Figure height should be at least %g cm.' % (
                        icluster, (3 + len(cluster_sources)
                                   + int(self.show_reference)) * 5/4.))

        if self.show_reference:
            lines.append(
                ('Reference', get_deco(ref_source), mpl_color('aluminium3')))

        moment_full_max = max(deco[-1][0] for (_, deco, _) in lines)

        for xpos, label in [
                (0., 'Full'),
                (2., 'Isotropic'),
                (4., 'Deviatoric'),
                (6., 'CLVD'),
                (8., 'DC')]:

            axes.annotate(
                label,
                xy=(1 + xpos, nlines_max),
                xycoords='data',
                xytext=(0., 0.),
                textcoords='offset points',
                ha='center',
                va='center',
                color='black',
                fontsize=fontsize)

        for i, (label, deco, color_t) in enumerate(lines):
            ypos = nlines_max - i - 1.0

            [(moment_iso, ratio_iso, m_iso),
             (moment_dc, ratio_dc, m_dc),
             (moment_clvd, ratio_clvd, m_clvd),
             (moment_devi, ratio_devi, m_devi),
             (moment_full, ratio_full, m_full)] = deco

            size0 = moment_full / moment_full_max

            axes.annotate(
                label,
                xy=(-2., ypos),
                xycoords='data',
                xytext=(0., 0.),
                textcoords='offset points',
                ha='left',
                va='center',
                color='black',
                fontsize=fontsize)

            for xpos, mt_part, ratio, ops in [
                    (0., m_full, ratio_full, '-'),
                    (2., m_iso, ratio_iso, '='),
                    (4., m_devi, ratio_devi, '='),
                    (6., m_clvd, ratio_clvd, '+'),
                    (8., m_dc, ratio_dc, None)]:

                if ratio > 1e-4:
                    try:
                        beachball.plot_beachball_mpl(
                            mt_part, axes,
                            beachball_type='full',
                            position=(1. + xpos, ypos),
                            size=0.9 * size0 * math.sqrt(ratio),
                            size_units='data',
                            color_t=color_t,
                            linewidth=1.0)

                    except beachball.BeachballError as e:
                        logger.warn(str(e))

                        axes.annotate(
                            'ERROR',
                            xy=(1. + xpos, ypos),
                            ha='center',
                            va='center',
                            color='red',
                            fontsize=fontsize)

                else:
                    axes.annotate(
                        'N/A',
                        xy=(1. + xpos, ypos),
                        ha='center',
                        va='center',
                        color='black',
                        fontsize=fontsize)

                if ops is not None:
                    axes.annotate(
                        ops,
                        xy=(2. + xpos, ypos),
                        ha='center',
                        va='center',
                        color='black',
                        fontsize=fontsize)

        axes.axison = False
        axes.set_xlim(-2.25, 9.75)
        axes.set_ylim(-0.5, nlines_max+0.5)

        item = PlotItem(name='main')
        return [[item, fig]]
Esempio n. 8
0
    def draw_figures(self, history):

        import scipy.stats
        from grond.core import make_stats

        exclude = self.exclude
        include = self.include
        figsize = self.size_inch
        fontsize = self.font_size
        method = self.method
        ref_color = mpl_color('aluminium6')
        stats_color = mpl_color('scarletred2')
        bar_color = mpl_color('scarletred1')
        stats_color3 = mpl_color('scarletred3')

        problem = history.problem

        models = history.models

        bounds = problem.get_combined_bounds()
        exclude = list(exclude)
        for ipar in range(problem.ncombined):
            par = problem.combined[ipar]
            vmin, vmax = bounds[ipar]
            if vmin == vmax:
                exclude.append(par.name)

        xref = problem.get_reference_model()

        smap = {}
        iselected = 0
        for ipar in range(problem.ncombined):
            par = problem.combined[ipar]
            if exclude and par.name in exclude or \
                    include and par.name not in include:
                continue

            smap[iselected] = ipar
            iselected += 1

        nselected = iselected
        del iselected

        pnames = [
            problem.combined[smap[iselected]].name
            for iselected in range(nselected)]

        rstats = make_stats(problem, models,
                            history.get_primary_chain_misfits(),
                            pnames=pnames)

        for iselected in range(nselected):
            ipar = smap[iselected]
            par = problem.combined[ipar]
            vs = problem.extract(models, ipar)
            vmin, vmax = bounds[ipar]

            fig = plt.figure(figsize=figsize)
            labelpos = mpl_margins(
                fig, nw=1, nh=1, w=7., bottom=5., top=1, units=fontsize)

            axes = fig.add_subplot(1, 1, 1)
            labelpos(axes, 2.5, 2.0)
            axes.set_xlabel(par.get_label())
            axes.set_ylabel('PDF')
            axes.set_xlim(*fixlim(*par.scaled((vmin, vmax))))

            if method == 'gaussian_kde':
                try:
                    kde = scipy.stats.gaussian_kde(vs)
                except Exception:
                    logger.warn(
                        'Cannot create plot histogram with gaussian_kde: '
                        'possibly all samples have the same value.')
                    continue

                vps = num.linspace(vmin, vmax, 600)
                pps = kde(vps)

                axes.plot(
                    par.scaled(vps), par.inv_scaled(pps), color=stats_color)

            elif method == 'histogram':
                pps, edges = num.histogram(
                    vs,
                    bins=num.linspace(vmin, vmax, num=40),
                    density=True)
                vps = 0.5 * (edges[:-1] + edges[1:])

                axes.bar(par.scaled(vps), par.inv_scaled(pps),
                         par.scaled(2.*(vps - edges[:-1])),
                         color=bar_color)

            pstats = rstats.parameter_stats_list[iselected]

            axes.axvspan(
                par.scaled(pstats.minimum),
                par.scaled(pstats.maximum),
                color=stats_color, alpha=0.1)
            axes.axvspan(
                par.scaled(pstats.percentile16),
                par.scaled(pstats.percentile84),
                color=stats_color, alpha=0.1)
            axes.axvspan(
                par.scaled(pstats.percentile5),
                par.scaled(pstats.percentile95),
                color=stats_color, alpha=0.1)

            axes.axvline(
                par.scaled(pstats.median),
                color=stats_color3, alpha=0.5)
            axes.axvline(
                par.scaled(pstats.mean),
                color=stats_color3, ls=':', alpha=0.5)

            if self.show_reference:
                axes.axvline(
                    par.scaled(problem.extract(xref, ipar)),
                    color=ref_color)

            item = PlotItem(name=par.name)
            item.attributes['parameters'] = [par.name]
            yield item, fig
Esempio n. 9
0
    def draw_figures(self, environ):
        nwindow = 200
        show_raw_acceptance_rates = False
        optimiser = environ.get_optimiser()
        problem = environ.get_problem()
        history = environ.get_history()
        chains = optimiser.chains(problem, history)
        chains.load()

        acceptance = chains.acceptance_history

        nmodels_rate = history.nmodels - (nwindow - 1)
        if nmodels_rate < 1:
            logger.warning(
                'Cannot create plot acceptance: insufficient number of tested '
                'models.')

            return

        acceptance_rate = num.zeros((history.nchains, nmodels_rate))
        for ichain in range(history.nchains):
            acceptance_rate[ichain, :] = trace.moving_sum(
                acceptance[ichain, :], nwindow, mode='valid') / float(nwindow)

        acceptance_n = num.sum(acceptance, axis=0)

        acceptance_any = num.minimum(acceptance_n, 1)

        acceptance_any_rate = trace.moving_sum(
            acceptance_any, nwindow, mode='valid') / float(nwindow)

        acceptance_p = acceptance_n / float(history.nchains)

        popularity = trace.moving_sum(
            acceptance_p, nwindow, mode='valid') \
            / float(nwindow) / acceptance_any_rate

        mpl_init(fontsize=self.font_size)
        fig = plt.figure(figsize=self.size_inch)
        labelpos = mpl_margins(fig, w=7., h=5., units=self.font_size)

        axes = fig.add_subplot(1, 1, 1)
        labelpos(axes, 2.5, 2.0)

        imodels = num.arange(history.nmodels)

        imodels_rate = imodels[nwindow - 1:]

        axes.plot(acceptance_n / history.nchains * 100.,
                  '.',
                  ms=2.0,
                  color=mpl_color('skyblue2'),
                  label='Popularity of Accepted Models',
                  alpha=0.3)

        if show_raw_acceptance_rates:
            for ichain in range(chains.nchains):
                axes.plot(imodels_rate,
                          acceptance_rate[ichain, :] * 100.,
                          color=mpl_color('scarletred2'),
                          alpha=0.2)

        axes.plot(imodels_rate,
                  popularity * 100.,
                  color=mpl_color('skyblue2'),
                  label='Popularity (moving average)')
        axes.plot(imodels_rate,
                  acceptance_any_rate * 100.,
                  color='black',
                  label='Acceptance Rate (any chain)')

        axes.legend()

        axes.set_xlabel('Iteration')
        axes.set_ylabel('Acceptance Rate, Model Popularity')

        axes.set_ylim(0., 100.)
        axes.set_xlim(0., history.nmodels - 1)
        axes.grid(alpha=.2)
        axes.yaxis.set_major_formatter(FuncFormatter(lambda v, p: '%d%%' % v))

        iiter = 0
        bgcolors = [mpl_color('aluminium1'), mpl_color('aluminium2')]
        for iphase, phase in enumerate(optimiser.sampler_phases):
            axes.axvspan(iiter,
                         iiter + phase.niterations,
                         color=bgcolors[iphase % len(bgcolors)])

            iiter += phase.niterations

        yield (PlotItem(name='acceptance',
                        description=u'''
Acceptance rate (black line) within a moving window of %d iterations.

A model is considered accepted, if it is accepted in at least one chain. The
popularity of accepted models is shown as blue dots. Popularity is defined as
the percentage of chains accepting the model (100%% meaning acceptance in all
chains). A moving average of the popularities is shown as blue line (same
averaging interval as for the acceptance rate). Different background colors
represent different sampler phases.
''' % nwindow), fig)

        mpl_init(fontsize=self.font_size)
        fig = plt.figure(figsize=self.size_inch)
        labelpos = mpl_margins(fig, w=7., h=5., units=self.font_size)

        axes = fig.add_subplot(1, 1, 1)
        labelpos(axes, 2.5, 2.0)

        nwindow2 = max(1, int(history.nmodels / (self.size_inch[1] * 100)))
        nmodels_rate2 = history.nmodels - (nwindow2 - 1)
        acceptance_rate2 = num.zeros((history.nchains, nmodels_rate2))
        for ichain in range(history.nchains):
            acceptance_rate2[ichain, :] = trace.moving_sum(
                acceptance[ichain, :], nwindow2, mode='valid') \
                / float(nwindow2)

        imodels_rate2 = imodels[nwindow2 - 1:]

        axes.pcolormesh(imodels_rate2,
                        num.arange(history.nchains),
                        num.log(0.01 + acceptance_rate2),
                        cmap='GnBu')

        if history.sampler_contexts is not None:
            axes.plot(imodels,
                      history.sampler_contexts[:, 1],
                      '.',
                      ms=2.0,
                      color='black',
                      label='Breeding Chain',
                      alpha=0.3)

        axes.set_xlabel('Iteration')
        axes.set_ylabel('Bootstrap Chain')
        axes.set_xlim(0, history.nmodels - 1)
        axes.set_ylim(0, history.nchains - 1)

        axes.xaxis.grid(alpha=.4)

        yield (PlotItem(name='acceptance_img',
                        description=u'''
Model acceptance per bootstrap chain averaged over %d models (background color,
low to high acceptance as light to dark colors).

Black dots mark the base chains used when sampling new models (directed sampler
phases only).
''' % nwindow2), fig)
Esempio n. 10
0
        def generate_plot(sat_target, result, ifig):

            scene = sat_target.scene

            fig = plt.figure()
            fig.set_size_inches(*self.size_inch)
            gs = gridspec.GridSpec(
                2, 3,
                wspace=.15, hspace=.2,
                left=.1, right=.975, top=.95,
                height_ratios=[12, 1])

            item = PlotItem(
                name='fig_%i' % ifig,
                attributes={'targets': [sat_target.path]},
                title=u'Satellite Surface Displacements - %s'
                      % scene.meta.scene_title,
                description=u'''
Surface displacements derived from satellite data.
(Left) the input data, (center) the modelled
data and (right) the model residual.
''')

            stat_obs = result.statics_obs['displacement.los']
            stat_syn = result.statics_syn['displacement.los']
            res = stat_obs - stat_syn

            if scene.frame.isMeter():
                offset_n, offset_e = map(float, latlon_to_ne_numpy(
                    scene.frame.llLat, scene.frame.llLon,
                    source.effective_lat, source.effective_lon))
            elif scene.frame.isDegree():
                offset_n = source.effective_lat - scene.frame.llLat
                offset_e = source.effective_lon - scene.frame.llLon

            im_extent = (
                scene.frame.E.min() - offset_e,
                scene.frame.E.max() - offset_e,
                scene.frame.N.min() - offset_n,
                scene.frame.N.max() - offset_n)

            if self.displacement_unit == 'rad':
                wavelength = scene.meta.wavelength
                if wavelength is None:
                    raise AttributeError(
                        'The satellite\'s wavelength is not set')

                stat_obs = displ2rad(stat_obs, wavelength)
                stat_syn = displ2rad(stat_syn, wavelength)
                res = displ2rad(res, wavelength)

                self.colormap = 'hsv'
                data_range = (0., num.pi)

            else:
                abs_displ = num.abs([stat_obs.min(), stat_obs.max(),
                                     stat_syn.min(), stat_syn.max(),
                                     res.min(), res.max()]).max()
                data_range = (-abs_displ, abs_displ)

            cmw = cm.ScalarMappable(cmap=self.colormap)
            cmw.set_clim(*data_range)
            cmw.set_array(stat_obs)

            axes = [fig.add_subplot(gs[0, 0]),
                    fig.add_subplot(gs[0, 1]),
                    fig.add_subplot(gs[0, 2])]

            ax = axes[0]
            ax.imshow(
                get_displacement_rgba(stat_obs, scene, cmw),
                extent=im_extent, origin='lower')
            draw_leaves(ax, scene, offset_e, offset_n)
            draw_source(ax, scene)
            add_arrow(ax, scene)
            init_axes(ax, scene, 'Observed')

            ax.text(.025, .025, 'Scene ID: %s' % scene.meta.scene_id,
                    fontsize=8, alpha=.7,
                    va='bottom', transform=ax.transAxes)
            if scene.frame.isMeter():
                ax.set_ylabel('Northing [km]', fontsize=self.font_size)

            ax = axes[1]
            ax.imshow(
                get_displacement_rgba(stat_syn, scene, cmw),
                extent=im_extent, origin='lower')
            draw_leaves(ax, scene, offset_e, offset_n)
            draw_source(ax, scene)
            add_arrow(ax, scene)
            init_axes(ax, scene, 'Model')
            ax.get_yaxis().set_visible(False)

            ax = axes[2]
            ax.imshow(
                get_displacement_rgba(res, scene, cmw),
                extent=im_extent, origin='lower')

            draw_leaves(ax, scene, offset_e, offset_n)
            draw_source(ax, scene)
            add_arrow(ax, scene)
            init_axes(ax, scene, 'Residual', last_axes=True)
            ax.get_yaxis().set_visible(False)

            for ax in axes:
                ax.set_xlim(*im_extent[:2])
                ax.set_ylim(*im_extent[2:])

            if closeup:
                if scene.frame.isMeter():
                    fn, fe = source.outline(cs='xy').T
                elif scene.frame.isDegree():
                    fn, fe = source.outline(cs='latlon').T
                    fn -= source.effective_lat
                    fe -= source.effective_lon

                if fn.size > 1:
                    off_n = (fn[0] + fn[1]) / 2
                    off_e = (fe[0] + fe[1]) / 2
                else:
                    off_n = fn[0]
                    off_e = fe[0]

                fault_size = 2*num.sqrt(max(abs(fn-off_n))**2
                                        + max(abs(fe-off_e))**2)
                fault_size *= self.map_scale
                if fault_size == 0.0:
                    extent = (scene.frame.N[-1] + scene.frame.E[-1]) / 2
                    fault_size = extent * .25

                for ax in axes:
                    ax.set_xlim(-fault_size/2 + off_e, fault_size/2 + off_e)
                    ax.set_ylim(-fault_size/2 + off_n, fault_size/2 + off_n)

            if self.map_limits is not None:
                xmin, xmax, ymin, ymax = self.map_limits
                assert xmin < xmax, 'bad map_limits xmin > xmax'
                assert ymin < ymax, 'bad map_limits ymin > ymax'

                for ax in axes:
                    ax.set_xlim(
                        xmin/ax.scale_x['scale'] - ax.scale_x['offset'],
                        xmax/ax.scale_x['scale'] - ax.scale_x['offset'],)
                    ax.set_ylim(
                        ymin/ax.scale_y['scale'] - ax.scale_y['offset'],
                        ymax/ax.scale_y['scale'] - ax.scale_y['offset'])

            if self.displacement_unit == 'm':
                def cfmt(x, p):
                    return '%.2f' % x
            elif self.displacement_unit == 'cm':
                def cfmt(x, p):
                    return '%.1f' % (x * 1e2)
            elif self.displacement_unit == 'mm':
                def cfmt(x, p):
                    return '%.0f' % (x * 1e3)
            elif self.displacement_unit == 'rad':
                def cfmt(x, p):
                    return '%.2f' % x
            else:
                raise AttributeError(
                    'unknown displacement unit %s' % self.displacement_unit)

            cbar_args = dict(
                orientation='horizontal',
                format=FuncFormatter(cfmt),
                use_gridspec=True)
            cbar_label = 'LOS Displacement [%s]' % self.displacement_unit

            if self.common_color_scale:
                cax = fig.add_subplot(gs[1, 1])
                cax.set_aspect(.05)
                cbar = fig.colorbar(cmw, cax=cax, **cbar_args)
                cbar.set_label(cbar_label)
            else:
                for idata, data in enumerate((stat_syn, stat_obs, res)):
                    cax = fig.add_subplot(gs[1, idata])
                    cax.set_aspect(.05)

                    if not self.displacement_unit == 'rad':
                        abs_displ = num.abs(data).max()
                        cmw.set_clim(-abs_displ, abs_displ)

                    cbar = fig.colorbar(cmw, cax=cax, **cbar_args)
                    cbar.set_label(cbar_label)

            return (item, fig)
Esempio n. 11
0
        def plot_gnss(gnss_target, result, ifig, vertical=False):
            campaign = gnss_target.campaign
            item = PlotItem(
                name='fig_%i' % ifig,
                attributes={'targets': gnss_target.path},
                title=u'Static GNSS Surface Displacements - Campaign %s' %
                campaign.name,
                description=u'Static surface displacement from GNSS campaign '
                u'%s (black vectors) and displacements derived '
                u'from best rupture model (red).' % campaign.name)

            lat, lon = campaign.get_center_latlon()

            if self.radius is None:
                radius = campaign.get_radius()

            if radius == 0.:
                logger.warn('Radius of GNSS campaign %s too small, defaulting'
                            ' to 30 km' % campaign.name)
                radius = 30 * km

            model_camp = gnss.GNSSCampaign(stations=copy.deepcopy(
                campaign.stations),
                                           name='grond model')
            for ista, sta in enumerate(model_camp.stations):
                sta.north.shift = result.statics_syn['displacement.n'][ista]
                sta.north.sigma = 0.

                sta.east.shift = result.statics_syn['displacement.e'][ista]
                sta.east.sigma = 0.

                sta.up.shift = -result.statics_syn['displacement.d'][ista]
                sta.up.sigma = 0.

            m = automap.Map(width=self.size_cm[0],
                            height=self.size_cm[1],
                            lat=lat,
                            lon=lon,
                            radius=radius,
                            show_topo=self.show_topo,
                            show_grid=self.show_grid,
                            show_rivers=self.show_rivers,
                            color_wet=(216, 242, 254),
                            color_dry=(238, 236, 230))

            if vertical:
                m.add_gnss_campaign(campaign,
                                    psxy_style={
                                        'G': 'black',
                                        'W': '0.8p,black',
                                    },
                                    vertical=True)

                m.add_gnss_campaign(model_camp,
                                    psxy_style={
                                        'G': 'red',
                                        'W': '0.8p,red',
                                        't': 30,
                                    },
                                    vertical=True,
                                    labels=False)
            else:
                m.add_gnss_campaign(campaign,
                                    psxy_style={
                                        'G': 'black',
                                        'W': '0.8p,black',
                                    })

                m.add_gnss_campaign(model_camp,
                                    psxy_style={
                                        'G': 'red',
                                        'W': '0.8p,red',
                                        't': 30,
                                    },
                                    labels=False)

            if isinstance(problem, CMTProblem):
                from pyrocko import moment_tensor
                from pyrocko.plot import gmtpy

                event = source.pyrocko_event()
                mt = event.moment_tensor.m_up_south_east()

                xx = num.trace(mt) / 3.
                mc = num.matrix([[xx, 0., 0.], [0., xx, 0.], [0., 0., xx]])
                mc = mt - mc
                mc = mc / event.moment_tensor.scalar_moment() * \
                    moment_tensor.magnitude_to_moment(5.0)
                m6 = tuple(moment_tensor.to6(mc))
                symbol_size = 20.
                m.gmt.psmeca(S='%s%g' % ('d', symbol_size / gmtpy.cm),
                             in_rows=[
                                 (source.lon, source.lat, 10) + m6 + (1, 0, 0)
                             ],
                             M=True,
                             *m.jxyr)

            elif isinstance(problem, RectangularProblem):
                m.gmt.psxy(in_rows=source.outline(cs='lonlat'),
                           L='+p2p,black',
                           W='1p,black',
                           G='black',
                           t=60,
                           *m.jxyr)

            return (item, m)
Esempio n. 12
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
Esempio n. 13
0
        def generate_plot(sat_target, result, ifig):

            scene = sat_target.scene

            fig = plt.figure()
            fig.set_size_inches(*self.size_inch)
            gs = gridspec.GridSpec(2,
                                   3,
                                   wspace=.15,
                                   hspace=.2,
                                   left=.1,
                                   right=.975,
                                   top=.95,
                                   height_ratios=[12, 1])

            item = PlotItem(name='fig_%i' % ifig,
                            attributes={'targets': [sat_target.path]},
                            title=u'Satellite Surface Displacements - %s' %
                            scene.meta.scene_title,
                            description=u'''
Surface displacements derived from satellite data.
(Left) the input data, (center) the modelled
data and (right) the model residual.
'''.format(meta=scene.meta))

            stat_obs = result.statics_obs
            stat_syn = result.statics_syn['displacement.los']
            res = stat_obs - stat_syn

            if scene.frame.isMeter():
                offset_n, offset_e = map(
                    float,
                    latlon_to_ne_numpy(scene.frame.llLat, scene.frame.llLon,
                                       source.effective_lat,
                                       source.effective_lon))
            elif scene.frame.isDegree():
                offset_n = source.effective_lat - scene.frame.llLat
                offset_e = source.effective_lon - scene.frame.llLon

            im_extent = (scene.frame.E.min() - offset_e, scene.frame.E.max() -
                         offset_e, scene.frame.N.min() - offset_n,
                         scene.frame.N.max() - offset_n)

            abs_displ = num.abs([
                stat_obs.min(),
                stat_obs.max(),
                stat_syn.min(),
                stat_syn.max(),
                res.min(),
                res.max()
            ]).max()

            cmw = cm.ScalarMappable(cmap=self.colormap)
            cmw.set_clim(vmin=-abs_displ, vmax=abs_displ)
            cmw.set_array(stat_obs)

            axes = [
                fig.add_subplot(gs[0, 0]),
                fig.add_subplot(gs[0, 1]),
                fig.add_subplot(gs[0, 2])
            ]

            ax = axes[0]
            ax.imshow(mapDisplacementGrid(stat_obs, scene),
                      extent=im_extent,
                      cmap=self.colormap,
                      vmin=-abs_displ,
                      vmax=abs_displ,
                      origin='lower')
            drawLeaves(ax, scene, offset_e, offset_n)
            drawSource(ax, scene)
            addArrow(ax, scene)
            initAxes(ax, scene, 'Observed')

            ax.text(.025,
                    .025,
                    'Scene ID: %s' % scene.meta.scene_id,
                    fontsize=8,
                    alpha=.7,
                    va='bottom',
                    transform=ax.transAxes)
            if scene.frame.isDegree():
                ax.set_ylabel('Lat [°]')
            elif scene.frame.isMeter():
                ax.set_ylabel('Northing [km]')

            ax = axes[1]
            ax.imshow(mapDisplacementGrid(stat_syn, scene),
                      extent=im_extent,
                      cmap=self.colormap,
                      vmin=-abs_displ,
                      vmax=abs_displ,
                      origin='lower')
            drawLeaves(ax, scene, offset_e, offset_n)
            drawSource(ax, scene)
            addArrow(ax, scene)
            initAxes(ax, scene, 'Model')
            ax.get_yaxis().set_visible(False)

            ax = axes[2]
            ax.imshow(mapDisplacementGrid(res, scene),
                      extent=im_extent,
                      cmap=self.colormap,
                      vmin=-abs_displ,
                      vmax=abs_displ,
                      origin='lower')
            drawLeaves(ax, scene, offset_e, offset_n)
            drawSource(ax, scene)
            addArrow(ax, scene)
            initAxes(ax, scene, 'Residual', last_axes=True)
            ax.get_yaxis().set_visible(False)

            for ax in axes:
                ax.set_xlim(llE, urE)
                ax.set_ylim(llN, urN)

            if closeup:
                if scene.frame.isMeter():
                    fn, fe = source.outline(cs='xy').T
                elif scene.frame.isDegree():
                    fn, fe = source.outline(cs='latlon').T
                    fn -= source.effective_lat
                    fe -= source.effective_lon

                if fn.size > 1:
                    off_n = (fn[0] + fn[1]) / 2
                    off_e = (fe[0] + fe[1]) / 2
                else:
                    off_n = fn[0]
                    off_e = fe[0]

                fault_size = 2 * num.sqrt(
                    max(abs(fn - off_n))**2 + max(abs(fe - off_e))**2)
                fault_size *= self.map_scale
                if fault_size == 0.0:
                    extent = (scene.frame.N[-1] + scene.frame.E[-1]) / 2
                    fault_size = extent * .25

                for ax in axes:
                    ax.set_xlim(-fault_size / 2 + off_e,
                                fault_size / 2 + off_e)
                    ax.set_ylim(-fault_size / 2 + off_n,
                                fault_size / 2 + off_n)

            cax = fig.add_subplot(gs[1, :])
            cbar = fig.colorbar(cmw,
                                cax=cax,
                                orientation='horizontal',
                                use_gridspec=True)

            cbar.set_label('LOS Displacement [m]')

            return (item, fig)
Esempio n. 14
0
    def draw_figures(self, history, optimiser):

        color_parameter = self.color_parameter
        exclude = self.exclude
        include = self.include
        nsubplots = self.nsubplots
        figsize = self.size_inch
        ibootstrap = 0 if self.ibootstrap is None else self.ibootstrap
        misfit_cutoff = self.misfit_cutoff
        show_ellipses = self.show_ellipses
        msize = 1.5
        cmap = 'coolwarm'

        problem = history.problem
        if not problem:
            return []

        models = history.models

        exclude = list(exclude)
        bounds = problem.get_combined_bounds()
        for ipar in range(problem.ncombined):
            par = problem.combined[ipar]
            lo, hi = bounds[ipar]
            if lo == hi:
                exclude.append(par.name)

        xref = problem.get_reference_model()

        isort = history.get_sorted_misfits_idx(chain=ibootstrap)[::-1]
        models = history.get_sorted_models(chain=ibootstrap)[::-1]
        nmodels = history.nmodels

        gms = history.get_sorted_misfits(chain=ibootstrap)[::-1]
        if misfit_cutoff is not None:
            ibest = gms < misfit_cutoff
            gms = gms[ibest]
            models = models[ibest]

        kwargs = {}

        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)

        elif color_parameter in history.attribute_names:
            icolor = history.get_attribute(color_parameter)[isort]
            icolor_need = num.unique(icolor)

            colors = []
            for i in range(icolor_need[-1]+1):
                colors.append(mpl_graph_color(i))

            cmap = mcolors.ListedColormap(colors)
            cmap.set_under(mpl_color('aluminium3'))
            kwargs.update(dict(vmin=0, vmax=icolor_need[-1]))
        else:
            raise meta.GrondError(
                'Invalid color_parameter: %s' % color_parameter)

        smap = {}
        iselected = 0
        for ipar in range(problem.ncombined):
            par = problem.combined[ipar]
            if exclude and par.name in exclude or \
                    include and par.name not in include:
                continue

            smap[iselected] = ipar
            iselected += 1

        nselected = iselected

        if nselected < 2:
            logger.warn('Cannot draw joinpar figures with less than two '
                        'parameters selected.')
            return []

        nfig = (nselected - 2) // nsubplots + 1

        figs = []
        for ifig in range(nfig):
            figs_row = []
            for jfig in range(nfig):
                if ifig >= jfig:
                    item = PlotItem(name='fig_%i_%i' % (ifig, jfig))
                    item.attributes['parameters'] = []
                    figs_row.append((item, plt.figure(figsize=figsize)))
                else:
                    figs_row.append(None)

            figs.append(figs_row)

        for iselected in range(nselected):
            ipar = smap[iselected]
            ypar = problem.combined[ipar]
            for jselected in range(iselected):
                jpar = smap[jselected]
                xpar = problem.combined[jpar]

                ixg = (iselected - 1)
                iyg = jselected

                ix = ixg % nsubplots
                iy = iyg % nsubplots

                ifig = ixg // nsubplots
                jfig = iyg // nsubplots

                aind = (nsubplots, nsubplots, (ix * nsubplots) + iy + 1)

                item, fig = figs[ifig][jfig]

                tlist = item.attributes['parameters']
                if xpar.name not in tlist:
                    tlist.append(xpar.name)
                if ypar.name not in tlist:
                    tlist.append(ypar.name)

                axes = fig.add_subplot(*aind)

                axes.axvline(0., color=mpl_color('aluminium3'), lw=0.5)
                axes.axhline(0., color=mpl_color('aluminium3'), lw=0.5)
                for spine in axes.spines.values():
                    spine.set_edgecolor(mpl_color('aluminium5'))
                    spine.set_linewidth(0.5)

                xmin, xmax = fixlim(*xpar.scaled(bounds[jpar]))
                ymin, ymax = fixlim(*ypar.scaled(bounds[ipar]))

                if ix == 0 or jselected + 1 == iselected:
                    for (xpos, xoff, x) in [
                            (0.0, 10., xmin),
                            (1.0, -10., xmax)]:

                        axes.annotate(
                            '%.3g%s' % (x, xpar.get_unit_suffix()),
                            xy=(xpos, 1.05),
                            xycoords='axes fraction',
                            xytext=(xoff, 5.),
                            textcoords='offset points',
                            verticalalignment='bottom',
                            horizontalalignment='left',
                            rotation=45.)

                if iy == nsubplots - 1 or jselected + 1 == iselected:
                    for (ypos, yoff, y) in [
                            (0., 10., ymin),
                            (1.0, -10., ymax)]:

                        axes.annotate(
                            '%.3g%s' % (y, ypar.get_unit_suffix()),
                            xy=(1.0, ypos),
                            xycoords='axes fraction',
                            xytext=(5., yoff),
                            textcoords='offset points',
                            verticalalignment='bottom',
                            horizontalalignment='left',
                            rotation=45.)

                axes.set_xlim(xmin, xmax)
                axes.set_ylim(ymin, ymax)

                if not self.show_ticks:
                    axes.get_xaxis().set_ticks([])
                    axes.get_yaxis().set_ticks([])
                else:
                    axes.tick_params(length=4, which='both')
                    axes.get_yaxis().set_ticklabels([])
                    axes.get_xaxis().set_ticklabels([])

                if iselected == nselected - 1 or ix == nsubplots - 1:
                    axes.annotate(
                        xpar.get_label(with_unit=False),
                        xy=(0.5, -0.05),
                        xycoords='axes fraction',
                        verticalalignment='top',
                        horizontalalignment='right',
                        rotation=45.)

                if iy == 0:
                    axes.annotate(
                        ypar.get_label(with_unit=False),
                        xy=(-0.05, 0.5),
                        xycoords='axes fraction',
                        verticalalignment='top',
                        horizontalalignment='right',
                        rotation=45.)

                fx = problem.extract(models, jpar)
                fy = problem.extract(models, ipar)

                axes.scatter(
                    xpar.scaled(fx),
                    ypar.scaled(fy),
                    c=icolor,
                    s=msize, alpha=0.5, cmap=cmap, edgecolors='none', **kwargs)

                if show_ellipses:
                    cov = num.cov((xpar.scaled(fx), ypar.scaled(fy)))
                    evals, evecs = eigh_sorted(cov)
                    evals = num.sqrt(evals)
                    ell = patches.Ellipse(
                        xy=(
                            num.mean(xpar.scaled(fx)),
                            num.mean(ypar.scaled(fy))),
                        width=evals[0] * 2,
                        height=evals[1] * 2,
                        angle=num.rad2deg(
                            num.arctan2(evecs[1][0], evecs[0][0])))

                    ell.set_facecolor('none')
                    axes.add_artist(ell)

                if self.show_reference:
                    fx = problem.extract(xref, jpar)
                    fy = problem.extract(xref, ipar)

                    ref_color = mpl_color('aluminium6')
                    ref_color_light = 'none'
                    axes.plot(
                        xpar.scaled(fx), ypar.scaled(fy), 's',
                        mew=1.5, ms=5, mfc=ref_color_light, mec=ref_color)

        figs_flat = []
        for figs_row in figs:
            figs_flat.extend(
                item_fig for item_fig in figs_row if item_fig is not None)

        return figs_flat
Esempio n. 15
0
    def draw_figure(self, ds, history, tpath):
        problem = history.problem
        color_parameter = self.color_parameter
        misfit_cutoff = self.misfit_cutoff
        fontsize = self.font_size
        targets = [
            t for t in problem.targets
            if isinstance(t, PhaseRatioTarget) and t.path == tpath
        ]

        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[::self.istride_ensemble]
        models = models[::self.istride_ensemble]

        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)

        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]))

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

            # source = problem.get_source(model)
            results = problem.evaluate(model, targets=targets)

            for target, result in zip(targets, results):
                if isinstance(result, gf.SeismosizerError):
                    continue

                if not isinstance(target, PhaseRatioTarget):
                    continue

                a_obs = result.a_obs
                b_obs = result.b_obs
                a_syn = result.a_syn
                b_syn = result.b_syn

                r_obs = a_obs / (a_obs + b_obs)
                r_syn = a_syn / (a_syn + b_syn)

                data.append(('.'.join(target.codes), imodel, r_obs, r_syn))

        fontsize = self.font_size

        item = PlotItem(name='fig_%s' % tpath)

        item.attributes['targets'] = [t.string_id() for t in targets]

        fig = plt.figure(figsize=self.size_inch)

        labelpos = mpl_margins(fig,
                               nw=1,
                               nh=1,
                               left=7.,
                               right=1.,
                               bottom=10.,
                               top=3,
                               units=fontsize)

        axes = fig.add_subplot(1, 1, 1)
        labelpos(axes, 2.5, 2.0)

        labels = sorted(set(x[0] for x in data))

        ntargets = len(labels)
        string_id_to_itarget = dict((x, i) for (i, x) in enumerate(labels))

        itargets = num.array([string_id_to_itarget[x[0]] for x in data])

        imodels = num.array([x[1] for x in data], dtype=num.int).T
        r_obs, r_syn = num.array([x[2:] for x in data]).T

        r_obs_median = num.zeros(ntargets)
        for itarget in range(ntargets):
            r_obs_median[itarget] = num.median(r_obs[itargets == itarget])

        iorder = meta.ordersort(r_obs_median)

        for imodel in range(nmodels):
            mask = imodels == imodel
            axes.plot(iorder[itargets[mask]],
                      r_obs[mask],
                      '_',
                      ms=20.,
                      zorder=-10,
                      alpha=0.5,
                      color='black')
            axes.plot(iorder[itargets[mask]],
                      r_syn[mask],
                      '_',
                      ms=10.,
                      alpha=0.5,
                      color=imodel_to_color[imodel])

        axes.set_yscale('log')
        axes.set_ylabel('Ratio')

        axes.set_xticks(iorder[num.arange(ntargets)])
        axes.set_xticklabels(labels, rotation='vertical')

        fig.suptitle(tpath, fontsize=self.font_size_title)

        yield item, fig
Esempio n. 16
0
    def draw_figures(self, history):
        from matplotlib import colors

        color = 'black'
        fontsize = self.font_size
        markersize = fontsize * 1.5
        beachballsize_small = markersize * 0.5
        beachball_type = self.beachball_type

        problem = history.problem
        sp = SectionPlot(config=self)
        self._to_be_closed.append(sp)

        fig = sp.fig
        axes_en = sp.axes_xy
        axes_dn = sp.axes_zy
        axes_ed = sp.axes_xz

        bounds = problem.get_combined_bounds()

        gms = problem.combine_misfits(history.misfits)

        isort = num.argsort(gms)[::-1]

        gms = gms[isort]
        models = history.models[isort, :]

        iorder = num.arange(history.nmodels)

        for parname, set_label, set_lim in [[
                'east_shift', sp.set_xlabel, sp.set_xlim
        ], ['north_shift', sp.set_ylabel,
                sp.set_ylim], ['depth', sp.set_zlabel, sp.set_zlim]]:

            ipar = problem.name_to_index(parname)
            par = problem.combined[ipar]
            set_label(par.get_label())
            xmin, xmax = fixlim(*par.scaled(bounds[ipar]))
            set_lim(xmin, xmax)

        for axes, xparname, yparname in [(axes_en, 'east_shift',
                                          'north_shift'),
                                         (axes_dn, 'depth', 'north_shift'),
                                         (axes_ed, 'east_shift', 'depth')]:

            ixpar = problem.name_to_index(xparname)
            iypar = problem.name_to_index(yparname)

            xpar = problem.combined[ixpar]
            ypar = problem.combined[iypar]

            xmin, xmax = fixlim(*xpar.scaled(bounds[ixpar]))
            ymin, ymax = fixlim(*ypar.scaled(bounds[iypar]))

            try:
                axes.set_facecolor(mpl_color('aluminium1'))
            except AttributeError:
                axes.patch.set_facecolor(mpl_color('aluminium1'))

            rect = patches.Rectangle((xmin, ymin),
                                     xmax - xmin,
                                     ymax - ymin,
                                     facecolor=mpl_color('white'),
                                     edgecolor=mpl_color('aluminium2'))

            axes.add_patch(rect)

            # fxs = xpar.scaled(problem.extract(models, ixpar))
            # fys = ypar.scaled(problem.extract(models, iypar))

            # axes.set_xlim(*fixlim(num.min(fxs), num.max(fxs)))
            # axes.set_ylim(*fixlim(num.min(fys), num.max(fys)))

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

            for ix, x in enumerate(models):

                source = problem.get_source(x)
                mt = source.pyrocko_moment_tensor(store=problem.get_gf_store(
                    problem.targets[0]),
                                                  target=problem.targets[0])
                fx = problem.extract(x, ixpar)
                fy = problem.extract(x, iypar)
                sx, sy = xpar.scaled(fx), ypar.scaled(fy)

                color = cmap.to_rgba(iorder[ix])

                alpha = (iorder[ix] - num.min(iorder)) / \
                    float(num.max(iorder) - num.min(iorder))

                try:
                    beachball.plot_beachball_mpl(mt,
                                                 axes,
                                                 beachball_type=beachball_type,
                                                 position=(sx, sy),
                                                 size=beachballsize_small,
                                                 color_t=color,
                                                 alpha=alpha,
                                                 zorder=1,
                                                 linewidth=0.25)

                except beachball.BeachballError as e:
                    logger.warn(str(e))

        item = PlotItem(name='main')
        return [[item, fig]]
Esempio n. 17
0
    def draw_figures(self, history):

        fontsize = self.font_size

        fig = plt.figure(figsize=self.size_inch)
        labelpos = mpl_margins(fig,
                               nw=2,
                               nh=2,
                               w=7.,
                               h=5.,
                               wspace=2.,
                               hspace=5.,
                               units=fontsize)

        problem = history.problem
        if not problem:
            logger.warn('problem not set')
            return []

        models = history.models

        if models.size == 0:
            logger.warn('empty models vector')
            return []

        imodels = num.arange(history.nmodels)

        gms = problem.combine_misfits(history.misfits)**problem.norm_exponent

        isort = num.argsort(gms)[::-1]

        gms = gms[isort]

        gms_softclip = num.where(gms > 1.0, 0.1 * num.log10(gms) + 1.0, gms)

        gcms = problem.combine_misfits(history.misfits, get_contributions=True)

        gcms = gcms[isort, :]

        jsort = num.argsort(gcms[-1, :])[::-1]

        # ncols = 4
        # nrows = ((problem.ntargets + 1) - 1) / ncols + 1

        axes = fig.add_subplot(2, 2, 1)
        labelpos(axes, 2.5, 2.0)

        axes.set_ylabel('Relative contribution (smoothed)')
        axes.set_ylim(0.0, 1.0)

        axes2 = fig.add_subplot(2, 2, 3, sharex=axes)
        labelpos(axes2, 2.5, 2.0)

        axes2.set_xlabel(
            'Tested model, sorted descending by global misfit value')

        axes2.set_ylabel('Square of misfit')

        axes2.set_ylim(0., 1.5)
        axes2.axhspan(1.0, 1.5, color=(0.8, 0.8, 0.8))
        axes2.set_yticks(
            [0., 0.2, 0.4, 0.6, 0.8, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5])
        axes2.set_yticklabels([
            '0.0', '0.2', '0.4', '0.6', '0.8', '1', '10', '100', '1000',
            '10000', '100000'
        ])

        axes2.set_xlim(imodels[0], imodels[-1])

        rel_ms_sum = num.zeros(history.nmodels)
        rel_ms_smooth_sum = num.zeros(history.nmodels)
        ms_smooth_sum = num.zeros(history.nmodels)
        b = num.hanning(min(100, history.nmodels // 3))
        b /= num.sum(b)
        a = [1]
        ii = 0

        target_idx = [
            str(it) * t.nmisfits for it, t in enumerate(problem.targets)
        ]
        target_idx = num.fromiter(map(float, ''.join(target_idx)), dtype=int)

        for idx in jsort:
            target = problem.targets[target_idx[idx]]
            ms = gcms[:, idx]

            ms = num.where(num.isfinite(ms), ms, 0.0)
            if num.all(ms == 0.0):
                continue

            rel_ms = ms / gms

            rel_ms_smooth = signal.filtfilt(b, a, rel_ms)

            ms_smooth = rel_ms_smooth * gms_softclip

            rel_poly_y = num.concatenate(
                [rel_ms_smooth_sum[::-1], rel_ms_smooth_sum + rel_ms_smooth])
            poly_x = num.concatenate([imodels[::-1], imodels])

            add_args = {}
            if ii < 20:
                add_args['label'] = '%s (%.2g)' % (target.string_id(),
                                                   num.mean(rel_ms[-1]))

            axes.fill(poly_x,
                      rel_poly_y,
                      alpha=0.5,
                      color=mpl_graph_color(ii),
                      **add_args)

            poly_y = num.concatenate(
                [ms_smooth_sum[::-1], ms_smooth_sum + ms_smooth])

            axes2.fill(poly_x, poly_y, alpha=0.5, color=mpl_graph_color(ii))

            rel_ms_sum += rel_ms

            # axes.plot(
            #    imodels, rel_ms_sum, color='black', alpha=0.1, zorder=-1)

            ms_smooth_sum += ms_smooth
            rel_ms_smooth_sum += rel_ms_smooth
            ii += 1

        axes.legend(title='Contributions (top twenty)',
                    bbox_to_anchor=(1.05, 0.0, 1.0, 1.0),
                    loc='upper left',
                    ncol=1,
                    borderaxespad=0.,
                    prop={'size': 9})

        axes2.plot(imodels, gms_softclip, color='black')
        axes2.axhline(1.0, color=(0.5, 0.5, 0.5))

        return [[PlotItem(name='main'), fig]]
Esempio n. 18
0
    def draw_figures(self, history):

        fontsize = self.font_size

        fig = plt.figure(figsize=self.size_inch)
        axes = fig.add_subplot(1, 1, 1, aspect=1.0)
        fig.subplots_adjust(left=0., right=1., bottom=0., top=1.)

        problem = history.problem
        models = history.models

        if models.size == 0:
            logger.warn('empty models vector')
            return []

        gms = problem.combine_misfits(history.misfits)
        isort = num.argsort(gms)
        iorder = num.empty_like(isort)
        iorder[isort] = num.arange(iorder.size)[::-1]

        mean_source = core.get_mean_source(problem, history.models)

        best_source = core.get_best_source(problem, history.models,
                                           history.misfits)

        ref_source = problem.base_source

        for xpos, label in [(0., 'Full'), (2., 'Isotropic'),
                            (4., 'Deviatoric'), (6., 'CLVD'), (8., 'DC')]:

            axes.annotate(label,
                          xy=(1 + xpos, 3),
                          xycoords='data',
                          xytext=(0., 0.),
                          textcoords='offset points',
                          ha='center',
                          va='center',
                          color='black',
                          fontsize=fontsize)

        decos = []
        for source in [best_source, mean_source, ref_source]:
            mt = source.pyrocko_moment_tensor()
            deco = mt.standard_decomposition()
            decos.append(deco)

        moment_full_max = max(deco[-1][0] for deco in decos)

        for ypos, label, deco, color_t in [
            (2., 'Ensemble best', decos[0], mpl_color('aluminium5')),
            (1., 'Ensemble mean', decos[1], mpl_color('scarletred1')),
            (0., 'Reference', decos[2], mpl_color('aluminium3'))
        ]:

            [(moment_iso, ratio_iso, m_iso), (moment_dc, ratio_dc, m_dc),
             (moment_clvd, ratio_clvd, m_clvd),
             (moment_devi, ratio_devi, m_devi),
             (moment_full, ratio_full, m_full)] = deco

            size0 = moment_full / moment_full_max

            axes.annotate(label,
                          xy=(-2., ypos),
                          xycoords='data',
                          xytext=(0., 0.),
                          textcoords='offset points',
                          ha='left',
                          va='center',
                          color='black',
                          fontsize=fontsize)

            for xpos, mt_part, ratio, ops in [(0., m_full, ratio_full, '-'),
                                              (2., m_iso, ratio_iso, '='),
                                              (4., m_devi, ratio_devi, '='),
                                              (6., m_clvd, ratio_clvd, '+'),
                                              (8., m_dc, ratio_dc, None)]:

                if ratio > 1e-4:
                    try:
                        beachball.plot_beachball_mpl(
                            mt_part,
                            axes,
                            beachball_type='full',
                            position=(1. + xpos, ypos),
                            size=0.9 * size0 * math.sqrt(ratio),
                            size_units='data',
                            color_t=color_t,
                            linewidth=1.0)

                    except beachball.BeachballError as e:
                        logger.warn(str(e))

                        axes.annotate('ERROR',
                                      xy=(1. + xpos, ypos),
                                      ha='center',
                                      va='center',
                                      color='red',
                                      fontsize=fontsize)

                else:
                    axes.annotate('N/A',
                                  xy=(1. + xpos, ypos),
                                  ha='center',
                                  va='center',
                                  color='black',
                                  fontsize=fontsize)

                if ops is not None:
                    axes.annotate(ops,
                                  xy=(2. + xpos, ypos),
                                  ha='center',
                                  va='center',
                                  color='black',
                                  fontsize=fontsize)

        axes.axison = False
        axes.set_xlim(-2.25, 9.75)
        axes.set_ylim(-0.5, 3.5)

        item = PlotItem(name='main')
        return [[item, fig]]
Esempio n. 19
0
    def draw_figures(self, history, color_p_axis=False):
        from matplotlib import colors

        color = 'black'
        fontsize = self.font_size
        markersize = fontsize * 1.5
        beachballsize_small = markersize * 0.5
        beachball_type = self.beachball_type

        problem = history.problem
        sp = SectionPlot(config=self)
        self._to_be_closed.append(sp)

        fig = sp.fig
        axes_en = sp.axes_xy
        axes_dn = sp.axes_zy
        axes_ed = sp.axes_xz

        bounds = problem.get_combined_bounds()

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

        iorder = num.arange(history.nmodels)

        for parname, set_label, set_lim in [
                ['east_shift', sp.set_xlabel, sp.set_xlim],
                ['north_shift', sp.set_ylabel, sp.set_ylim],
                ['depth', sp.set_zlabel, sp.set_zlim]]:

            ipar = problem.name_to_index(parname)
            par = problem.combined[ipar]
            set_label(par.get_label())
            xmin, xmax = fixlim(*par.scaled(bounds[ipar]))
            set_lim(xmin, xmax)

        if 'volume_change' in problem.parameter_names:
            volumes = models[:, problem.name_to_index('volume_change')]
            volume_max = volumes.max()
            volume_min = volumes.min()

        def scale_size(source):
            if not hasattr(source, 'volume_change'):
                return beachballsize_small

            volume_change = source.volume_change
            fac = (volume_change - volume_min) / (volume_max - volume_min)
            return markersize * .25 + markersize * .5 * fac

        for axes, xparname, yparname in [
                (axes_en, 'east_shift', 'north_shift'),
                (axes_dn, 'depth', 'north_shift'),
                (axes_ed, 'east_shift', 'depth')]:

            ixpar = problem.name_to_index(xparname)
            iypar = problem.name_to_index(yparname)

            xpar = problem.combined[ixpar]
            ypar = problem.combined[iypar]

            xmin, xmax = fixlim(*xpar.scaled(bounds[ixpar]))
            ymin, ymax = fixlim(*ypar.scaled(bounds[iypar]))

            try:
                axes.set_facecolor(mpl_color('aluminium1'))
            except AttributeError:
                axes.patch.set_facecolor(mpl_color('aluminium1'))

            rect = patches.Rectangle(
                (xmin, ymin), xmax-xmin, ymax-ymin,
                facecolor=mpl_color('white'),
                edgecolor=mpl_color('aluminium2'))

            axes.add_patch(rect)

            # fxs = xpar.scaled(problem.extract(models, ixpar))
            # fys = ypar.scaled(problem.extract(models, iypar))

            # axes.set_xlim(*fixlim(num.min(fxs), num.max(fxs)))
            # axes.set_ylim(*fixlim(num.min(fys), num.max(fys)))

            cmap = cm.ScalarMappable(
                norm=colors.PowerNorm(
                    gamma=self.normalisation_gamma,
                    vmin=iorder.min(),
                    vmax=iorder.max()),

                cmap=plt.get_cmap('coolwarm'))

            for ix, x in enumerate(models):

                source = problem.get_source(x)
                mt = source.pyrocko_moment_tensor(
                    store=problem.get_gf_store(problem.targets[0]),
                    target=problem.targets[0])
                fx = problem.extract(x, ixpar)
                fy = problem.extract(x, iypar)
                sx, sy = xpar.scaled(fx), ypar.scaled(fy)

                # TODO: Add rotation in cross-sections
                color = cmap.to_rgba(iorder[ix])

                alpha = (iorder[ix] - iorder.min()) / \
                    float(iorder.max() - iorder.min())
                alpha = alpha**self.normalisation_gamma

                try:
                    beachball.plot_beachball_mpl(
                        mt, axes,
                        beachball_type=beachball_type,
                        position=(sx, sy),
                        size=scale_size(source),
                        color_t=color,
                        color_p=color if color_p_axis else 'white',
                        alpha=alpha,
                        zorder=1,
                        linewidth=0.25)

                except beachball.BeachballError as e:
                    logger.warn(str(e))

        item = PlotItem(name='main')
        return [[item, fig]]
Esempio n. 20
0
 def draw_figures(self):
     item = PlotItem(name='gf_shakemap')
     return [[item]]
Esempio n. 21
0
    def draw_figures(self, problem, dataset, history):

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

        misfits = history.misfits[history.get_sorted_misfits_idx(), ...]
        gcms = problem.combine_misfits(misfits[:1, :, :],
                                       get_contributions=True)[0, :]
        models = history.get_sorted_primary_models()[::-1]

        origin = problem.base_source

        targets = [
            t for t in problem.targets if isinstance(t, PhasePickTarget)
        ]

        ntargets = len(targets)
        nmodels = history.nmodels
        tts = num.zeros((nmodels, ntargets, 2))

        sdata = []
        for imodel in range(nmodels):
            model = models[imodel, :]
            source = problem.get_source(model)
            sdata.append(
                (origin.distance_to(source), origin.azibazi_to(source)[0]))

            results = problem.evaluate(model, targets=targets)
            for itarget, result in enumerate(results):
                result = results[itarget]
                tts[imodel, itarget, :] = result.tobs, result.tsyn

        ok = num.all(num.isfinite(tts), axis=2)
        ok = num.all(ok, axis=0)

        targets_ok = [
            target for (itarget, target) in enumerate(targets) if ok[itarget]
        ]
        tts = tts[:, ok, :]
        residuals = tts[:, :, 0] - tts[:, :, 1]
        mean_residuals = num.mean(residuals, axis=0)

        rlo, rhi = num.percentile(mean_residuals, [10., 90.])
        residual_amax = max(abs(rlo), abs(rhi))

        target_to_residual = dict(
            (target, residual)
            for (target, residual) in zip(targets_ok, mean_residuals))

        cg_to_targets = meta.gather(targets, lambda t: (t.path, ))

        cgs = sorted(cg_to_targets.keys())

        for cg in cgs:
            cg_str = '.'.join(cg)

            targets = cg_to_targets[cg]
            if len(targets) == 0:
                continue

            assert all(target_index[target][0] == target_index[target][1] - 1
                       for target in targets)

            itargets = num.array(
                [target_index[target][0] for target in targets])

            labels = ['.'.join(x for x in t.codes[:3] if x) for t in targets]

            azimuths = num.array([origin.azibazi_to(t)[0] for t in targets])
            distances = num.array([t.distance_to(origin) for t in targets])
            residuals = num.array(
                [target_to_residual.get(t, num.nan) for t in targets])

            item = PlotItem(
                name='picks_contributions_%s' % cg_str,
                title=u'Pick residuals and contributions (%s)' % cg_str,
                description=u'\n\nMarkers are scaled according to their '
                u'misfit contribution for the globally best '
                u'source model.')

            fig, axes, legend = self.plot_station_distribution(
                azimuths,
                distances,
                gcms[itargets],
                labels,
                colors=residuals,
                cnorm=(-residual_amax, residual_amax),
                cmap='RdYlBu',
                clabel='$T_{obs} - T_{syn}$ [s]',
                scatter_kwargs=dict(alpha=1.0),
                legend_title='Contribution')

            sources = [problem.get_source(x) for x in models[::10]]

            azimuths = num.array([origin.azibazi_to(s)[0] for s in sources])
            distances = num.array([s.distance_to(origin) for s in sources])

            axes.plot(azimuths * d2r,
                      distances,
                      'o',
                      ms=2.0,
                      color='black',
                      alpha=0.3)

            yield (item, fig)
Esempio n. 22
0
    def draw_figures(self, history):
        from matplotlib import colors

        color = 'black'
        fontsize = self.font_size
        markersize = fontsize * 1.5
        beachballsize_small = markersize * 0.5
        beachball_type = self.beachball_type

        problem = history.problem

        fig = plt.figure(figsize=self.size_inch)
        axes_en = fig.add_subplot(2, 2, 1)
        axes_dn = fig.add_subplot(2, 2, 2)
        axes_ed = fig.add_subplot(2, 2, 3)

        bounds = problem.get_combined_bounds()

        gms = problem.combine_misfits(history.misfits)

        isort = num.argsort(gms)[::-1]

        gms = gms[isort]
        models = history.models[isort, :]

        iorder = num.arange(history.nmodels)

        for axes, xparname, yparname in [(axes_en, 'east_shift',
                                          'north_shift'),
                                         (axes_dn, 'depth', 'north_shift'),
                                         (axes_ed, 'east_shift', 'depth')]:

            ixpar = problem.name_to_index(xparname)
            iypar = problem.name_to_index(yparname)

            xpar = problem.combined[ixpar]
            ypar = problem.combined[iypar]

            axes.set_xlabel(xpar.get_label())
            axes.set_ylabel(ypar.get_label())

            xmin, xmax = fixlim(*xpar.scaled(bounds[ixpar]))
            ymin, ymax = fixlim(*ypar.scaled(bounds[iypar]))

            axes.set_aspect(1.0)
            axes.set_xlim(xmin, xmax)
            axes.set_ylim(ymin, ymax)

            # fxs = xpar.scaled(problem.extract(models, ixpar))
            # fys = ypar.scaled(problem.extract(models, iypar))

            # axes.set_xlim(*fixlim(num.min(fxs), num.max(fxs)))
            # axes.set_ylim(*fixlim(num.min(fys), num.max(fys)))

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

            for ix, x in enumerate(models):
                source = problem.get_source(x)
                mt = source.pyrocko_moment_tensor()
                fx = problem.extract(x, ixpar)
                fy = problem.extract(x, iypar)
                sx, sy = xpar.scaled(fx), ypar.scaled(fy)

                color = cmap.to_rgba(iorder[ix])

                alpha = (iorder[ix] - num.min(iorder)) / \
                    float(num.max(iorder) - num.min(iorder))

                try:
                    beachball.plot_beachball_mpl(mt,
                                                 axes,
                                                 beachball_type=beachball_type,
                                                 position=(sx, sy),
                                                 size=beachballsize_small,
                                                 color_t=color,
                                                 alpha=alpha,
                                                 zorder=1,
                                                 linewidth=0.25)

                except beachball.BeachballError as e:
                    logger.warn(str(e))

        item = PlotItem(name='main', title='Moment Tensor Location')
        return [[item, fig]]
Esempio n. 23
0
    def draw_figures(self, history):

        color = 'black'
        fontsize = self.font_size
        markersize = fontsize * 1.5
        markersize_small = markersize * 0.2
        beachballsize = markersize
        beachballsize_small = beachballsize * 0.5
        beachball_type = self.beachball_type

        problem = history.problem
        best_source = history.get_best_source()
        mean_source = history.get_mean_source()

        fig = plt.figure(figsize=self.size_inch)
        axes = fig.add_subplot(1, 1, 1)

        data = []
        for ix, x in enumerate(history.models):
            source = problem.get_source(x)
            mt = source.pyrocko_moment_tensor()
            u, v = hudson.project(mt)

            if random.random() < 0.1:
                try:
                    beachball.plot_beachball_mpl(
                        mt, axes,
                        beachball_type=beachball_type,
                        position=(u, v),
                        size=beachballsize_small,
                        color_t=color,
                        alpha=0.5,
                        zorder=1,
                        linewidth=0.25)
                except beachball.BeachballError as e:
                    logger.warn(str(e))

            else:
                data.append((u, v))

        if data:
            u, v = num.array(data).T
            axes.plot(
                u, v, 'o',
                color=color,
                ms=markersize_small,
                mec='none',
                mew=0,
                alpha=0.25,
                zorder=0)

        hudson.draw_axes(axes)

        mt = mean_source.pyrocko_moment_tensor()
        u, v = hudson.project(mt)

        try:
            beachball.plot_beachball_mpl(
                mt, axes,
                beachball_type=beachball_type,
                position=(u, v),
                size=beachballsize,
                color_t=color,
                zorder=2,
                linewidth=0.5)
        except beachball.BeachballError as e:
            logger.warn(str(e))

        mt = best_source.pyrocko_moment_tensor()
        u, v = hudson.project(mt)

        axes.plot(
            u, v, 's',
            markersize=markersize,
            mew=1,
            mec='black',
            mfc='none',
            zorder=-2)

        if self.show_reference:
            mt = problem.base_source.pyrocko_moment_tensor()
            u, v = hudson.project(mt)

            try:
                beachball.plot_beachball_mpl(
                    mt, axes,
                    beachball_type=beachball_type,
                    position=(u, v),
                    size=beachballsize,
                    color_t='red',
                    zorder=2,
                    linewidth=0.5)
            except beachball.BeachballError as e:
                logger.warn(str(e))

        item = PlotItem(
            name='main')
        return [[item, fig]]
Esempio n. 24
0
    def draw_figures(self, ds, history, optimiser):
        show_mean_residuals = False

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

        targets = [
            t for t in problem.targets if isinstance(t, PhasePickTarget)
        ]

        # targets.sort(key=lambda t: t.distance_to(problem.base_source))
        # tpaths = sorted(set(t.path for t in targets))

        ntargets = len(targets)
        nmodels = history.nmodels
        tts = num.zeros((nmodels, ntargets, 2))
        distances = num.zeros((nmodels, ntargets))
        azimuths = num.zeros((nmodels, ntargets))

        for imodel in range(nmodels):
            model = models[imodel, :]
            source = problem.get_source(model)
            results = problem.evaluate(model, targets=targets)
            for itarget, result in enumerate(results):
                result = results[itarget]
                tts[imodel, itarget, :] = result.tobs, result.tsyn
                distances[imodel,
                          itarget] = source.distance_to(targets[itarget])

                azimuths[imodel,
                         itarget] = source.azibazi_to(targets[itarget])[0]

        ok = num.all(num.isfinite(tts), axis=2)
        ok = num.all(ok, axis=0)

        targets = [
            target for (itarget, target) in enumerate(targets) if ok[itarget]
        ]
        tts = tts[:, ok, :]
        distances = distances[:, ok]
        azimuths = azimuths[:, ok]
        residuals = tts[:, :, 0] - tts[:, :, 1]
        residual_amax = num.max(num.abs(residuals))
        mean_residuals = num.mean(residuals, axis=0)
        mean_distances = num.mean(distances, axis=0)

        isort = num.array([
            x[2]
            for x in sorted(zip(targets, mean_distances, range(len(targets))),
                            key=lambda x: (x[0].path, x[1]))
        ],
                          dtype=num.int)

        distances = distances[:, isort]
        distance_min = num.min(distances)
        distance_max = num.max(distances)
        azimuths = azimuths[:, isort]
        targets = [targets[i] for i in isort]
        ntargets = len(targets)
        residuals = residuals[:, isort]
        mean_residuals = mean_residuals[isort]

        icolor = num.arange(nmodels)

        norm = mcolors.Normalize(vmin=num.min(icolor), vmax=num.max(icolor))
        cmap = plt.get_cmap('coolwarm')

        napprox = max(1, int(round(
            (self.size_points[1] / self.font_size - 7))))

        npages = (ntargets - 1) // napprox + 1
        ntargets_page = (ntargets - 1) // npages + 1

        for ipage in range(npages):

            ilo, ihi = ipage * ntargets_page, (ipage + 1) * ntargets_page
            ihi = min(len(targets), ihi)

            targets_page = targets[ilo:ihi]
            item = PlotItem(name='fig_%02i' % ipage)

            item.attributes['targets'] = [t.string_id() for t in targets_page]

            fig = plt.figure(figsize=self.size_inch)

            labelpos = mpl_margins(fig,
                                   nw=2,
                                   nh=1,
                                   left=12.,
                                   right=1.,
                                   bottom=5.,
                                   top=1.,
                                   wspace=1.,
                                   units=self.font_size)

            axes1 = fig.add_subplot(1, 3, 1)
            axes2 = fig.add_subplot(1, 3, 2)
            axes3 = fig.add_subplot(1, 3, 3)

            for axes in (axes1, axes2, axes3):
                axes.set_ylim(-0.5, len(targets_page) - 0.5)
                axes.invert_yaxis()
                labelpos(axes, 2.5, 2.0)

            axes1.axvline(0.0, color='black')

            labels = []
            lastpath = None
            for ipos, t in enumerate(targets_page):
                scodes = '.'.join(t.codes)
                if lastpath is None or lastpath != t.path:
                    labels.append(t.path + '.' + scodes)
                    if lastpath is not None:
                        for axes in (axes1, axes2, axes3):
                            axes.axhline(ipos - 0.5, color='black')
                else:
                    labels.append(scodes)

                lastpath = t.path

            for ipos, itarget in enumerate(range(ilo, ihi)):
                axes1.plot(residuals[-1, itarget],
                           ipos,
                           '|',
                           ms=self.font_size,
                           color='black')

                if show_mean_residuals:
                    axes1.plot(mean_residuals[itarget],
                               ipos,
                               's',
                               ms=self.font_size,
                               color='none',
                               mec='black')

                axes1.scatter(residuals[::10, itarget],
                              util.num_full(icolor[::10].size,
                                            ipos,
                                            dtype=num.float),
                              c=icolor[::10],
                              cmap=cmap,
                              norm=norm,
                              alpha=0.5)

                axes2.scatter(distances[::10, itarget] / km,
                              util.num_full(icolor[::10].size,
                                            ipos,
                                            dtype=num.float),
                              c=icolor[::10],
                              cmap=cmap,
                              norm=norm,
                              alpha=0.5)

                axes3.scatter(azimuths[::10, itarget],
                              util.num_full(icolor[::10].size,
                                            ipos,
                                            dtype=num.float),
                              c=icolor[::10],
                              cmap=cmap,
                              norm=norm,
                              alpha=0.5)

            axes1.set_yticks(num.arange(len(labels)))
            axes1.set_yticklabels(labels)
            axes1.set_xlabel('$T_{obs} - T_{syn}$ [s]')
            axes1.set_xlim(-residual_amax, residual_amax)

            axes2.set_xlabel('Distance [km]')
            axes2.set_xlim(distance_min / km, distance_max / km)

            axes3.set_xlabel('Azimuth [deg]')
            axes3.set_xlim(-180., 180.)

            axes2.get_yaxis().set_ticks([])
            axes2.get_yaxis().set_ticks([])

            axes3.get_yaxis().set_ticks([])
            axes3.get_yaxis().set_ticks([])

            yield item, fig
Esempio n. 25
0
    def draw_figures(self, problem, dataset, history):

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

        ws = problem.get_target_weights()

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

        event = problem.base_source

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

        cgs = sorted(cg_to_targets.keys())

        for cg in cgs:
            cg_str = '.'.join(cg)

            targets = cg_to_targets[cg]
            if len(targets) == 0:
                continue

            assert all(target_index[target][0] == target_index[target][1] - 1
                       for target in targets)

            itargets = num.array(
                [target_index[target][0] for target in targets])

            labels = ['.'.join(x for x in t.codes[:3] if x) for t in targets]

            azimuths = num.array([event.azibazi_to(t)[0] for t in targets])
            distances = num.array([t.distance_to(event) for t in targets])

            item = PlotItem(
                name='seismic_stations_weights_%s' % cg_str,
                title=u'Station weights (%s)' % cg_str,
                description=u'\n\nMarkers are scaled according to the '
                            u'weighting factor of the corresponding target\'s '
                            u'contribution in the misfit function.')
            fig, ax, legend = self.plot_station_distribution(
                azimuths, distances, ws[itargets], labels)
            legend.set_title(
                'Weight',
                prop=dict(size=self.font_size))

            yield (item, fig)

            if history:
                item = PlotItem(
                    name='seismic_stations_contributions_%s' % cg_str,
                    title=u'Station misfit contributions (%s)' % cg_str,
                    description=u'\n\nMarkers are scaled according to their '
                                u'misfit contribution for the globally best '
                                u'source model.')
                fig, ax, legend = self.plot_station_distribution(
                    azimuths, distances, gcms[itargets], labels)
                legend.set_title(
                    'Contribution',
                    prop=dict(size=self.font_size))

                yield (item, fig)
Esempio n. 26
0
    def draw_figures(self, dataset, history, optimiser):

        fontsize = self.font_size

        fig = plt.figure(figsize=self.size_inch)
        labelpos = mpl_margins(fig,
                               nw=2,
                               nh=2,
                               w=7.,
                               h=5.,
                               wspace=2.,
                               hspace=5.,
                               units=fontsize)

        problem = history.problem
        if not problem:
            logger.warn('Problem not set.')
            return []

        models = history.models

        if models.size == 0:
            logger.warn('Empty models vector.')
            return []

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

        imodels = num.arange(history.nmodels)

        gms = history.get_sorted_primary_misfits()[::-1]
        isort = history.get_sorted_misfits_idx(chain=0)[::-1]

        gms **= problem.norm_exponent
        gms_softclip = num.where(gms > 1.0, 0.1 * num.log10(gms) + 1.0, gms)

        gcms = problem.combine_misfits(
            history.misfits,
            extra_correlated_weights=optimiser.get_correlated_weights(problem),
            get_contributions=True)

        gcms = gcms[isort, :]
        nmisfits = gcms.shape[1]  # noqa

        ncontributions = sum([
            1 if t.plot_misfits_cumulative else t.nmisfits
            for t in problem.targets
        ])
        cum_gcms = num.zeros((history.nmodels, ncontributions))

        # Squash matrix and sum large targets.nmisifts, eg SatelliteTarget
        plot_target_labels = []
        idx = 0
        idx_cum = 0
        for itarget, target in enumerate(problem.targets):
            target_gcms = gcms[:, idx:idx + target.nmisfits]
            if target.plot_misfits_cumulative:
                cum_gcms[:, idx_cum] = target_gcms.sum(axis=1)
                plot_target_labels.append(target.string_id())
                idx_cum += 1
            else:
                cum_gcms[:, idx_cum:idx_cum + target.nmisfits] = target_gcms
                plot_target_labels.extend(target.misfits_string_ids())
                idx_cum += target.nmisfits
            idx += target.nmisfits

        jsort = num.argsort(cum_gcms[-1, :])[::-1]

        # ncols = 4
        # nrows = ((problem.ntargets + 1) - 1) / ncols + 1

        axes = fig.add_subplot(2, 2, 1)
        labelpos(axes, 2.5, 2.0)

        axes.set_ylabel('Relative contribution (smoothed)')
        axes.set_ylim(0.0, 1.0)

        axes2 = fig.add_subplot(2, 2, 3, sharex=axes)
        labelpos(axes2, 2.5, 2.0)

        axes2.set_xlabel(
            'Tested model, sorted descending by global misfit value')

        axes2.set_ylabel('Square of misfit')

        axes2.set_ylim(0., 1.5)
        axes2.axhspan(1.0, 1.5, color=(0.8, 0.8, 0.8))
        axes2.set_yticks(
            [0., 0.2, 0.4, 0.6, 0.8, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5])
        axes2.set_yticklabels([
            '0.0', '0.2', '0.4', '0.6', '0.8', '1', '10', '100', '1000',
            '10000', '100000'
        ])

        axes2.set_xlim(imodels[0], imodels[-1])

        rel_ms_sum = num.zeros(history.nmodels)
        rel_ms_smooth_sum = num.zeros(history.nmodels)
        ms_smooth_sum = num.zeros(history.nmodels)
        b = num.hanning(min(100, history.nmodels // 5))
        b /= num.sum(b)
        a = [1]
        ii = 0

        for idx in jsort:
            target_label = plot_target_labels[idx]
            ms = cum_gcms[:, idx]

            ms = num.where(num.isfinite(ms), ms, 0.0)
            if num.all(ms == 0.0):
                continue

            rel_ms = ms / gms

            if b.shape[0] > 5:
                rel_ms_smooth = signal.filtfilt(b, a, rel_ms)
            else:
                rel_ms_smooth = rel_ms

            ms_smooth = rel_ms_smooth * gms_softclip

            rel_poly_y = num.concatenate(
                [rel_ms_smooth_sum[::-1], rel_ms_smooth_sum + rel_ms_smooth])
            poly_x = num.concatenate([imodels[::-1], imodels])

            add_args = {}
            if ii < 20:
                add_args['label'] = '%s (%.2g)' % (target_label,
                                                   num.mean(rel_ms[-1]))

            axes.fill(poly_x,
                      rel_poly_y,
                      alpha=0.5,
                      color=mpl_graph_color(ii),
                      **add_args)

            poly_y = num.concatenate(
                [ms_smooth_sum[::-1], ms_smooth_sum + ms_smooth])

            axes2.fill(poly_x, poly_y, alpha=0.5, color=mpl_graph_color(ii))

            rel_ms_sum += rel_ms

            # axes.plot(
            #    imodels, rel_ms_sum, color='black', alpha=0.1, zorder=-1)

            ms_smooth_sum += ms_smooth
            rel_ms_smooth_sum += rel_ms_smooth
            ii += 1

        axes.legend(title='Contributions (top twenty)',
                    bbox_to_anchor=(1.05, 0.0, 1.0, 1.0),
                    loc='upper left',
                    ncol=1,
                    borderaxespad=0.,
                    prop={'size': 9})

        axes2.plot(imodels, gms_softclip, color='black')
        axes2.axhline(1.0, color=(0.5, 0.5, 0.5))

        return [[PlotItem(name='main'), fig]]
Esempio n. 27
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
Esempio n. 28
0
    def draw_figures(self, history, optimiser):
        misfit_cutoff = self.misfit_cutoff
        sort_by = self.sort_by

        problem = history.problem
        models = history.models

        npar = problem.nparameters
        ndep = problem.ndependants
        fontsize = self.font_size
        nfx, nfy = self.subplot_layout

        imodels = num.arange(history.nmodels)
        bounds = problem.get_combined_bounds()

        xref = problem.get_reference_model()

        gms = history.get_primary_chain_misfits()
        gms_softclip = num.where(gms > 1.0, 0.2 * num.log10(gms) + 1.0, gms)

        isort = num.argsort(gms)[::-1]

        if sort_by == 'iteration':
            imodels = imodels[isort]
        elif sort_by == 'misfit':
            imodels = num.arange(imodels.size)
        else:
            assert False

        gms = gms[isort]
        gms_softclip = gms_softclip[isort]
        models = models[isort, :]

        iorder = num.empty_like(isort)
        iorder = num.arange(iorder.size)

        if misfit_cutoff is None:
            ibest = num.ones(gms.size, dtype=num.bool)
        else:
            ibest = gms < misfit_cutoff

        def config_axes(axes, nfx, nfy, impl, iplot, nplots):
            if (impl - 1) % nfx != nfx - 1:
                axes.get_yaxis().tick_left()

            if (impl - 1) >= (nfx * (nfy - 1)) or iplot >= nplots - nfx:
                axes.set_xlabel('Iteration')
                if not (impl - 1) // nfx == 0:
                    axes.get_xaxis().tick_bottom()
            elif (impl - 1) // nfx == 0:
                axes.get_xaxis().tick_top()
                axes.set_xticklabels([])
            else:
                axes.get_xaxis().set_visible(False)

        # nfz = (npar + ndep + 1 - 1) / (nfx*nfy) + 1
        cmap = cm.YlOrRd
        cmap = cm.jet
        msize = self.marker_size
        axes = None
        fig = None
        item_fig = None
        nfigs = 0
        alpha = 0.5
        for ipar in range(npar):
            impl = ipar % (nfx * nfy) + 1

            if impl == 1:
                if item_fig:
                    yield item_fig
                    nfigs += 1

                fig = plt.figure(figsize=self.size_inch)
                labelpos = mpl_margins(fig,
                                       nw=nfx,
                                       nh=nfy,
                                       left=7.,
                                       right=2.,
                                       top=1.,
                                       bottom=5.,
                                       wspace=7.,
                                       hspace=2.,
                                       units=fontsize)

                item = PlotItem(name='fig_%i' % (nfigs + 1))
                item.attributes['parameters'] = []
                item_fig = (item, fig)

            par = problem.parameters[ipar]

            item_fig[0].attributes['parameters'].append(par.name)

            axes = fig.add_subplot(nfy, nfx, impl)
            labelpos(axes, 2.5, 2.0)

            axes.set_ylabel(par.get_label())
            axes.get_yaxis().set_major_locator(plt.MaxNLocator(4))

            config_axes(axes, nfx, nfy, impl, ipar, npar + ndep + 1)

            axes.set_ylim(*fixlim(*par.scaled(bounds[ipar])))
            axes.set_xlim(0, history.nmodels)

            axes.scatter(imodels[ibest],
                         par.scaled(models[ibest, ipar]),
                         s=msize,
                         c=iorder[ibest],
                         edgecolors='none',
                         cmap=cmap,
                         alpha=alpha,
                         rasterized=True)

            if self.show_reference:
                axes.axhline(par.scaled(xref[ipar]), color='black', alpha=0.3)

        for idep in range(ndep):
            # ifz, ify, ifx = num.unravel_index(ipar, (nfz, nfy, nfx))
            impl = (npar + idep) % (nfx * nfy) + 1

            if impl == 1:
                if item_fig:
                    yield item_fig
                    nfigs += 1

                fig = plt.figure(figsize=self.size_inch)
                labelpos = mpl_margins(fig,
                                       nw=nfx,
                                       nh=nfy,
                                       left=7.,
                                       right=2.,
                                       top=1.,
                                       bottom=5.,
                                       wspace=7.,
                                       hspace=2.,
                                       units=fontsize)

                item = PlotItem(name='fig_%i' % (nfigs + 1))
                item.attributes['parameters'] = []

                item_fig = (item, fig)

            par = problem.dependants[idep]
            item_fig[0].attributes['parameters'].append(par.name)

            axes = fig.add_subplot(nfy, nfx, impl)
            labelpos(axes, 2.5, 2.0)

            axes.set_ylabel(par.get_label())
            axes.get_yaxis().set_major_locator(plt.MaxNLocator(4))

            config_axes(axes, nfx, nfy, impl, npar + idep, npar + ndep + 1)

            axes.set_ylim(*fixlim(*par.scaled(bounds[npar + idep])))
            axes.set_xlim(0, history.nmodels)

            ys = problem.make_dependant(models[ibest, :], par.name)
            axes.scatter(imodels[ibest],
                         par.scaled(ys),
                         s=msize,
                         c=iorder[ibest],
                         edgecolors='none',
                         cmap=cmap,
                         alpha=alpha,
                         rasterized=True)

            if self.show_reference:
                y = problem.make_dependant(xref, par.name)
                axes.axhline(par.scaled(y), color='black', alpha=0.3)

        impl = (npar + ndep) % (nfx * nfy) + 1
        if impl == 1:
            if item_fig:
                yield item_fig
                nfigs += 1

            fig = plt.figure(figsize=self.size_inch)
            labelpos = mpl_margins(fig,
                                   nw=nfx,
                                   nh=nfy,
                                   left=7.,
                                   right=2.,
                                   top=1.,
                                   bottom=5.,
                                   wspace=7.,
                                   hspace=2.,
                                   units=fontsize)

            item = PlotItem(name='fig_%i' % (nfigs + 1))
            item.attributes['parameters'] = []

            item_fig = (item, fig)

        axes = fig.add_subplot(nfy, nfx, impl)
        labelpos(axes, 2.5, 2.0)

        config_axes(axes, nfx, nfy, impl, npar + ndep, npar + ndep + 1)

        axes.set_ylim(0., 1.5)
        axes.set_yticks([0., 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4])
        axes.set_yticklabels(
            ['0.0', '0.2', '0.4', '0.6', '0.8', '1', '10', '100'])

        axes.scatter(imodels[ibest],
                     gms_softclip[ibest],
                     c=iorder[ibest],
                     s=msize,
                     edgecolors='none',
                     cmap=cmap,
                     alpha=alpha)

        axes.axhspan(1.0, 1.5, color=(0.8, 0.8, 0.8), alpha=0.2)
        axes.axhline(1.0, color=(0.5, 0.5, 0.5), zorder=2)

        axes.set_xlim(0, history.nmodels)
        axes.set_xlabel('Iteration')

        axes.set_ylabel('Misfit')

        yield item_fig
        nfigs += 1
Esempio n. 29
0
        def plot_gnss(gnss_target, result, ifig, vertical=False):
            campaign = gnss_target.campaign
            item = PlotItem(
                name='fig_%i' % ifig,
                attributes={'targets': gnss_target.path},
                title=u'Static GNSS Surface Displacements - Campaign %s' %
                campaign.name,
                description=u'''
Static surface displacement from GNSS campaign %s (black vectors) and
displacements derived from best model (red).
''' % campaign.name)

            event = source.pyrocko_event()
            locations = campaign.stations + [event]

            lat, lon = od.geographic_midpoint_locations(locations)

            if self.radius is None:
                coords = num.array([loc.effective_latlon for loc in locations])
                radius = od.distance_accurate50m_numpy(lat[num.newaxis],
                                                       lon[num.newaxis],
                                                       coords[:, 0].max(),
                                                       coords[:, 1]).max()
                radius *= 1.1

            if radius < 30. * km:
                logger.warn('Radius of GNSS campaign %s too small, defaulting'
                            ' to 30 km' % campaign.name)
                radius = 30 * km

            model_camp = gnss.GNSSCampaign(stations=copy.deepcopy(
                campaign.stations),
                                           name='grond model')
            for ista, sta in enumerate(model_camp.stations):
                sta.north.shift = result.statics_syn['displacement.n'][ista]
                sta.north.sigma = 0.

                sta.east.shift = result.statics_syn['displacement.e'][ista]
                sta.east.sigma = 0.

                if sta.up:
                    sta.up.shift = -result.statics_syn['displacement.d'][ista]
                    sta.up.sigma = 0.

            m = automap.Map(width=self.size_cm[0],
                            height=self.size_cm[1],
                            lat=lat,
                            lon=lon,
                            radius=radius,
                            show_topo=self.show_topo,
                            show_grid=self.show_grid,
                            show_rivers=self.show_rivers,
                            color_wet=(216, 242, 254),
                            color_dry=(238, 236, 230))

            all_stations = campaign.stations + model_camp.stations
            offset_scale = num.zeros(len(all_stations))

            for ista, sta in enumerate(all_stations):
                for comp in sta.components.values():
                    offset_scale[ista] += comp.shift
            offset_scale = num.sqrt(offset_scale**2).max()

            m.add_gnss_campaign(campaign,
                                psxy_style={
                                    'G': 'black',
                                    'W': '0.8p,black',
                                },
                                offset_scale=offset_scale,
                                vertical=vertical)

            m.add_gnss_campaign(model_camp,
                                psxy_style={
                                    'G': 'red',
                                    'W': '0.8p,red',
                                    't': 30,
                                },
                                offset_scale=offset_scale,
                                vertical=vertical,
                                labels=False)

            if isinstance(problem, CMTProblem) \
                    or isinstance(problem, VLVDProblem):
                from pyrocko import moment_tensor
                from pyrocko.plot import gmtpy

                mt = event.moment_tensor.m_up_south_east()
                ev_lat, ev_lon = event.effective_latlon

                xx = num.trace(mt) / 3.
                mc = num.matrix([[xx, 0., 0.], [0., xx, 0.], [0., 0., xx]])
                mc = mt - mc
                mc = mc / event.moment_tensor.scalar_moment() * \
                    moment_tensor.magnitude_to_moment(5.0)
                m6 = tuple(moment_tensor.to6(mc))
                symbol_size = 20.
                m.gmt.psmeca(S='%s%g' % ('d', symbol_size / gmtpy.cm),
                             in_rows=[(ev_lon, ev_lat, 10) + m6 + (1, 0, 0)],
                             M=True,
                             *m.jxyr)

            elif isinstance(problem, RectangularProblem):
                m.gmt.psxy(in_rows=source.outline(cs='lonlat'),
                           L='+p2p,black',
                           W='1p,black',
                           G='black',
                           t=60,
                           *m.jxyr)

            elif isinstance(problem, VolumePointProblem):
                ev_lat, ev_lon = event.effective_latlon
                dV = abs(source.volume_change)
                sphere_radius = num.cbrt(dV / (4. / 3. * num.pi))

                volcanic_circle = [ev_lon, ev_lat, '%fe' % sphere_radius]
                m.gmt.psxy(S='E-',
                           in_rows=[volcanic_circle],
                           W='1p,black',
                           G='orange3',
                           *m.jxyr)

            return (item, m)
Esempio n. 30
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