コード例 #1
0
class SourceGenerator(LocationGenerator):

    nevents = Int.T(default=2)
    avoid_water = Bool.T(
        default=False, help='Avoid sources offshore under the ocean / lakes.')

    radius = Float.T(default=10 * km)

    time_min = Timestamp.T(default=util.str_to_time('2017-01-01 00:00:00'))
    time_max = Timestamp.T(default=util.str_to_time('2017-01-03 00:00:00'))

    magnitude_min = Float.T(default=4.0)
    magnitude_max = Float.T(default=7.0)

    def get_sources(self):
        sources = []
        for ievent in range(self.nevents):
            src = self.get_source(ievent)
            src.name = 'scenario_ev%03d' % (ievent + 1)
            sources.append(src)

        return sources

    def dump_data(self, path):
        fn_sources = op.join(path, 'sources.yml')
        with open(fn_sources, 'w') as f:
            for src in self.get_sources():
                f.write(src.dump())

        fn_events = op.join(path, 'events.txt')
        with open(fn_events, 'w') as f:
            for isrc, src in enumerate(self.get_sources()):
                f.write(src.pyrocko_event().dump())

        return [fn_events, fn_sources]

    def add_map_artists(self, automap):
        pass
コード例 #2
0
ファイル: qssp.py プロジェクト: hsudha/pyrocko
class QSSPConfig(Object):
    qssp_version = String.T(default='2010beta')
    time_region = Tuple.T(2,
                          gf.Timing.T(),
                          default=(gf.Timing('-10'), gf.Timing('+890')))

    frequency_max = Float.T(optional=True)
    slowness_max = Float.T(default=0.4)
    antialiasing_factor = Float.T(default=0.1)

    lowpass_order = Int.T(default=0, optional=True)
    lowpass_corner = Float.T(default=1.0, optional=True)

    bandpass_order = Int.T(default=0, optional=True)
    bandpass_corner_low = Float.T(default=1.0, optional=True)
    bandpass_corner_high = Float.T(default=1.0, optional=True)

    output_slowness_min = Float.T(default=0.0, optional=True)
    output_slowness_max = Float.T(optional=True)

    spheroidal_modes = Bool.T(default=True)
    toroidal_modes = Bool.T(default=True)

    # only available in 2010beta:
    cutoff_harmonic_degree_sd = Int.T(optional=True, default=0)

    cutoff_harmonic_degree_min = Int.T(default=0)
    cutoff_harmonic_degree_max = Int.T(default=25000)

    crit_frequency_sge = Float.T(default=0.0)
    crit_harmonic_degree_sge = Int.T(default=0)

    include_physical_dispersion = Bool.T(default=False)

    source_patch_radius = Float.T(default=0.0)

    cut = Tuple.T(2, gf.Timing.T(), optional=True)

    fade = Tuple.T(4, gf.Timing.T(), optional=True)
    relevel_with_fade_in = Bool.T(default=False)
    nonzero_fade_in = Bool.T(default=False)
    nonzero_fade_out = Bool.T(default=False)

    def items(self):
        return dict(self.T.inamevals(self))
コード例 #3
0
ファイル: config.py プロジェクト: braunfuss/beat
class SamplerConfig(Object):
    """
    Config for the sampler specific parameters.
    """

    name = String.T(default='SMC',
                    help='Sampler to use for sampling the solution space.'
                    ' Metropolis/ SMC')
    progressbar = Bool.T(default=True,
                         help='Display progressbar(s) during sampling.')
    buffer_size = Int.T(default=5000,
                        help='number of samples after which the result '
                        'buffer is written to disk')
    parameters = SamplerParameters.T(default=SMCConfig.D(),
                                     optional=True,
                                     help='Sampler dependend Parameters')

    def set_parameters(self, **kwargs):

        if self.name is None:
            logger.info('Sampler not defined, using default sampler: SMC')
            self.name = 'SMC'

        if self.name == 'SMC':
            self.parameters = SMCConfig(**kwargs)

        elif self.name != 'SMC':
            kwargs.pop('update_covariances', None)

            if self.name == 'Metropolis':
                self.parameters = MetropolisConfig(**kwargs)

            elif self.name == 'PT':
                self.parameters = ParallelTemperingConfig(**kwargs)

            else:
                raise TypeError('Sampler "%s" is not implemented.' % self.name)
コード例 #4
0
class MetaDataDownloadConfig(Object):
    # Data and Metadata download
    download_data = Bool.T()
    download_metadata = Bool.T()
    local_metadata = List.T(default=[])
    local_data = List.T(default=[])
    local_waveforms_only = Bool.T(default=False)
    sds_structure = Bool.T(default=False)
    use_downmeta = Bool.T(default=True)
    channels_download = String.T()
    all_channels = Bool.T(default=False)
    # components = List.T()
    token = Dict.T(default={})
    sites = List.T()
    # start and end time with respect to origin time
    # start time before origin time!
    dt_start = Float.T()
    dt_end = Float.T()
コード例 #5
0
class TargetBalancingAnalyserConfig(AnalyserConfig):
    """Configuration parameters of the target balancing."""
    niterations = Int.T(
        default=1000,
        help='Number of random forward models for mean phase amplitude '
        'estimation')

    use_reference_magnitude = Bool.T(
        default=False,
        help='Fix magnitude of random sources to the magnitude of the '
        'reference event.')

    cutoff = Float.T(
        optional=True,
        help='Remove targets where ratio m/p > cutoff, where m is the misfit '
        'between synthetics and observations and p is the misfit between '
        'synthetics and zero-traces. Magnitude should be fixed to use '
        'this.')

    def get_analyser(self):
        return TargetBalancingAnalyser(
            niter=self.niterations,
            use_reference_magnitude=self.use_reference_magnitude,
            cutoff=self.cutoff)
コード例 #6
0
class EngineConfig(HasPaths):
    gf_stores_from_pyrocko_config = Bool.T(
        default=True,
        help='Load the GF stores from ~/.pyrocko/config')
    gf_store_superdirs = List.T(
        Path.T(),
        help='List of path hosting collection of Green\'s function stores.')
    gf_store_dirs = List.T(
        Path.T(),
        help='List of Green\'s function stores')

    def __init__(self, *args, **kwargs):
        HasPaths.__init__(self, *args, **kwargs)
        self._engine = None

    def get_engine(self):
        if self._engine is None:
            fp = self.expand_path
            self._engine = gf.LocalEngine(
                use_config=self.gf_stores_from_pyrocko_config,
                store_superdirs=fp(self.gf_store_superdirs),
                store_dirs=fp(self.gf_store_dirs))

        return self._engine
コード例 #7
0
class PalantiriDataConfig(Object):
    '''Configuration of data IO and data preprocessing'''
    quantity = String.T(default="displacement",
                        help='velocity and displacement')

    tttopt = String.T(default="-ph P", help='quantity')

    cam = Int.T(default=2,
                help='Length in seconds. Not needed \
        when using TFRecordData')

    pyrocko_download = Bool.T(
        default=True,
        optional=True,
        help='if download of was not done with palantiridown command, set to 0'
    )

    export_unfiltered = Bool.T(default=False,
                               optional=True,
                               help='Save unfiltered waveforms.')

    export_filtered = Bool.T(default=False,
                             optional=True,
                             help='Save filtered waveforms.')

    export_resampled = Bool.T(default=False,
                              optional=True,
                              help='Save resmpled mseed.')

    colesseo_input = Bool.T(default=False,
                            optional=True,
                            help='if colosseo\
                                     synthetics should be used, set to 1')

    colosseo_scenario_yml = String.T(optional=True,
                                     help='give the colosseo\
                                    scenario.yml file')

    load_wdf = Bool.T(default=True,
                      optional=True,
                      help='Save and load xcorr files as pickle ')
コード例 #8
0
class PhaseRatioTarget(gf.Location, MisfitTarget):

    '''
    Target to compare ratios or log ratios of two seismic phases.

      misfit = | a_obs / (a_obs + b_obs)  - a_syn / (a_syn + b_syn) |

    '''

    codes = Tuple.T(
        3, String.T(),
        help='network, station, location codes.')

    store_id = gf.StringID.T(
        help='ID of Green\'s function store to use for the computation.')

    backazimuth = Float.T(optional=True)

    interpolation = gf.InterpolationMethod.T()

    measure_a = fm.FeatureMeasure.T()
    measure_b = fm.FeatureMeasure.T()

    fit_log_ratio = Bool.T(
        default=True,
        help='if true, compare synthetic and observed log ratios')

    fit_log_ratio_waterlevel = Float.T(
        default=0.01,
        help='Waterlevel added to both ratios when comparing on logarithmic '
             'scale, to avoid log(0)')

    can_bootstrap_weights = True

    def __init__(self, **kwargs):
        gf.Location.__init__(self, **kwargs)
        MisfitTarget.__init__(self, **kwargs)

    @classmethod
    def get_plot_classes(cls):
        from . import plot
        plots = super(PhaseRatioTarget, cls).get_plot_classes()
        plots.extend(plot.get_plot_classes())
        return plots

    def string_id(self):
        return '.'.join(x for x in (self.path,) + self.codes)

    def get_plain_targets(self, engine, source):
        return self.prepare_modelling(engine, source, None)

    def prepare_modelling(self, engine, source, targets):
        modelling_targets = []
        for measure in [self.measure_a, self.measure_b]:
            modelling_targets.extend(measure.get_modelling_targets(
                self.codes, self.lat, self.lon, self.depth, self.store_id,
                self.backazimuth))

        return modelling_targets

    def finalize_modelling(
            self, engine, source, modelling_targets, modelling_results):

        ds = self.get_dataset()

        try:
            imt = 0
            amps = []
            for measure in [self.measure_a, self.measure_b]:
                nmt_this = measure.get_nmodelling_targets()
                amp_obs, _ = measure.evaluate(
                    engine, source,
                    modelling_targets[imt:imt+nmt_this],
                    dataset=ds)

                amp_syn, _ = measure.evaluate(
                    engine, source,
                    modelling_targets[imt:imt+nmt_this],
                    trs=[r.trace.pyrocko_trace()
                         for r
                         in modelling_results[imt:imt+nmt_this]])

                amps.append((amp_obs, amp_syn))

                imt += nmt_this

            (a_obs, a_syn), (b_obs, b_syn) = amps

            eps = self.fit_log_ratio_waterlevel
            if self.fit_log_ratio:
                res_a = num.log(a_obs / (a_obs + b_obs) + eps) \
                    - num.log(a_syn / (a_syn + b_syn) + eps)
            else:
                res_a = a_obs / (a_obs + b_obs) - a_syn / (a_syn + b_syn)

            misfit = num.abs(res_a)
            norm = 1.0

            result = PhaseRatioResult(
                misfits=num.array([[misfit, norm]], dtype=num.float),
                a_obs=a_obs,
                b_obs=b_obs,
                a_syn=a_syn,
                b_syn=b_syn)

            return result

        except dataset.NotFound as e:
            logger.debug(str(e))
            return gf.SeismosizerError('No waveform data: %s' % str(e))
コード例 #9
0
class HudsonPlot(PlotConfig):

    '''
    Illustration of the solution distribution of decomposed moment tensor.
    '''

    name = 'hudson'
    size_cm = Tuple.T(2, Float.T(), default=(17.5, 17.5*(3./4.)))
    beachball_type = StringChoice.T(
        choices=['full', 'deviatoric', 'dc'],
        default='dc')
    show_reference = Bool.T(default=True)

    def make(self, environ):
        cm = environ.get_plot_collection_manager()
        history = environ.get_history(subset='harvest')
        mpl_init(fontsize=self.font_size)
        cm.create_group_mpl(
            self,
            self.draw_figures(history),
            title=u'Hudson Plot',
            section='solution',
            feather_icon='box',
            description=u'''
Hudson's source type plot with the ensemble of bootstrap solutions.

For about 10% of the solutions (randomly chosen), the focal mechanism is
depicted, others are represented as dots. The square marks the global best
fitting solution.
''')

    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]]
コード例 #10
0
class MTDecompositionPlot(PlotConfig):
    '''
    Moment tensor decomposition plot.
    '''

    name = 'mt_decomposition'
    size_cm = Tuple.T(2, Float.T(), default=(15., 5.))
    cluster_attribute = meta.StringID.T(
        optional=True,
        help='name of attribute to use as cluster IDs')
    show_reference = Bool.T(default=True)

    def make(self, environ):
        cm = environ.get_plot_collection_manager()
        history = environ.get_history(subset='harvest')
        mpl_init(fontsize=self.font_size)
        cm.create_group_mpl(
            self,
            self.draw_figures(history),
            title=u'MT Decomposition',
            section='solution',
            feather_icon='sun',
            description=u'''
Moment tensor decomposition of the best-fitting solution into isotropic,
deviatoric and best double couple components.

Shown are the ensemble best, the ensemble mean%s and, if available, a reference
mechanism. The symbol size indicates the relative strength of the components.
The inversion result is consistent and stable if ensemble mean and ensemble
best have similar symbol size and patterns.
''' % (', cluster results' if self.cluster_attribute else ''))

    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]]
コード例 #11
0
class JointparPlot(PlotConfig):
    '''
    Source problem parameter's tradeoff plots.
    '''

    name = 'jointpar'
    size_cm = Tuple.T(2, Float.T(), default=(20., 20.))
    misfit_cutoff = Float.T(optional=True)
    ibootstrap = Int.T(optional=True)
    color_parameter = String.T(default='misfit')
    exclude = List.T(String.T())
    include = List.T(String.T())
    show_ellipses = Bool.T(default=False)
    nsubplots = Int.T(default=6)
    show_ticks = Bool.T(default=False)
    show_reference = Bool.T(default=True)

    def make(self, environ):
        cm = environ.get_plot_collection_manager()
        history = environ.get_history(subset='harvest')
        optimiser = environ.get_optimiser()
        sref = 'Dark gray boxes mark reference solution.' \
            if self.show_reference else ''

        mpl_init(fontsize=self.font_size)
        cm.create_group_mpl(
            self,
            self.draw_figures(history, optimiser),
            title=u'Jointpar Plot',
            section='solution',
            feather_icon='crosshair',
            description=u'''
Source problem parameter's scatter plots, to evaluate the resolution of source
parameters and possible trade-offs between pairs of model parameters.

A subset of model solutions (from harvest) is shown in two dimensions for all
possible parameter pairs as points. The point color indicates the misfit for
the model solution with cold colors (blue) for high misfit models and warm
colors (red) for low misfit models. The plot ranges are defined by the given
parameter bounds and shows the model space of the optimsation. %s''' % sref)

    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
コード例 #12
0
class Parameter(Object):
    name__ = String.T()
    unit = Unicode.T(optional=True)
    scale_factor = Float.T(default=1., optional=True)
    scale_unit = Unicode.T(optional=True)
    label = Unicode.T(optional=True)
    optional = Bool.T(default=True, optional=True)

    def __init__(self, *args, **kwargs):
        if len(args) >= 1:
            kwargs['name'] = args[0]
        if len(args) >= 2:
            kwargs['unit'] = newstr(args[1])

        self.groups = [None]
        self._name = None

        Object.__init__(self, **kwargs)

    def get_label(self, with_unit=True):
        lbl = [self.label or self.name]
        if with_unit:
            unit = self.get_unit_label()
            if unit:
                lbl.append('[%s]' % unit)

        return ' '.join(lbl)

    def set_groups(self, groups):
        if not isinstance(groups, list):
            raise AttributeError('Groups must be a list of strings.')
        self.groups = groups

    def _get_name(self):
        if None not in self.groups:
            return '%s.%s' % ('.'.join(self.groups), self._name)
        return self._name

    def _set_name(self, value):
        self._name = value

    name = property(_get_name, _set_name)

    @property
    def name_nogroups(self):
        return self._name

    def get_value_label(self, value, format='%(value)g%(unit)s'):
        value = self.scaled(value)
        unit = self.get_unit_suffix()
        return format % dict(value=value, unit=unit)

    def get_unit_label(self):
        if self.scale_unit is not None:
            return self.scale_unit
        elif self.unit:
            return self.unit
        else:
            return None

    def get_unit_suffix(self):
        unit = self.get_unit_label()
        if not unit:
            return ''
        else:
            return ' %s' % unit

    def scaled(self, x):
        if isinstance(x, tuple):
            return tuple(v / self.scale_factor for v in x)
        if isinstance(x, list):
            return list(v / self.scale_factor for v in x)
        else:
            return x / self.scale_factor

    def inv_scaled(self, x):
        if isinstance(x, tuple):
            return tuple(v * self.scale_factor for v in x)
        if isinstance(x, list):
            return list(v * self.scale_factor for v in x)
        else:
            return x * self.scale_factor
コード例 #13
0
class WaveformMisfitTarget(gf.Target, MisfitTarget):
    flip_norm = Bool.T(default=False)
    misfit_config = WaveformMisfitConfig.T()

    can_bootstrap_weights = True

    def __init__(self, **kwargs):
        gf.Target.__init__(self, **kwargs)
        MisfitTarget.__init__(self, **kwargs)
        self._piggyback_subtargets = []

    def string_id(self):
        return '.'.join(x for x in (self.path, ) + self.codes)

    @classmethod
    def get_plot_classes(cls):
        from . import plot
        plots = super(WaveformMisfitTarget, cls).get_plot_classes()
        plots.extend(plot.get_plot_classes())
        return plots

    def get_combined_weight(self):
        if self._combined_weight is None:
            w = self.manual_weight
            for analyser in self.analyser_results.values():
                w *= analyser.weight
            self._combined_weight = num.array([w], dtype=num.float)

        return self._combined_weight

    def get_taper_params(self, engine, source):
        store = engine.get_store(self.store_id)
        config = self.misfit_config
        tmin_fit = source.time + store.t(config.tmin, source, self)
        tmax_fit = source.time + store.t(config.tmax, source, self)
        if config.fmin > 0.0:
            tfade = 1.0 / config.fmin
        else:
            tfade = 1.0 / config.fmax

        if config.tfade is None:
            tfade_taper = tfade
        else:
            tfade_taper = config.tfade

        return tmin_fit, tmax_fit, tfade, tfade_taper

    def get_backazimuth_for_waveform(self):
        return backazimuth_for_waveform(self.azimuth, self.codes)

    def get_freqlimits(self):
        config = self.misfit_config

        return (config.fmin / config.ffactor, config.fmin, config.fmax,
                config.fmax * config.ffactor)

    def get_pick_shift(self, engine, source):
        config = self.misfit_config
        tobs = None
        tsyn = None
        ds = self.get_dataset()

        if config.pick_synthetic_traveltime and config.pick_phasename:
            store = engine.get_store(self.store_id)
            tsyn = source.time + store.t(config.pick_synthetic_traveltime,
                                         source, self)

            marker = ds.get_pick(source.name, self.codes[:3],
                                 config.pick_phasename)

            if marker:
                tobs = marker.tmin

        return tobs, tsyn

    def get_cutout_timespan(self, tmin, tmax, tfade):

        if self.misfit_config.fmin > 0:
            tinc_obs = 1.0 / self.misfit_config.fmin
        else:
            tinc_obs = 10.0 / self.misfit_config.fmax

        tmin_obs = (math.floor((tmin - tfade) / tinc_obs) - 1.0) * tinc_obs
        tmax_obs = (math.ceil((tmax + tfade) / tinc_obs) + 1.0) * tinc_obs

        return tmin_obs, tmax_obs

    def post_process(self, engine, source, tr_syn):

        tr_syn = tr_syn.pyrocko_trace()
        nslc = self.codes

        config = self.misfit_config

        tmin_fit, tmax_fit, tfade, tfade_taper = \
            self.get_taper_params(engine, source)

        ds = self.get_dataset()

        tobs, tsyn = self.get_pick_shift(engine, source)
        if None not in (tobs, tsyn):
            tobs_shift = tobs - tsyn
        else:
            tobs_shift = 0.0

        tr_syn.extend(tmin_fit - tfade * 2.0,
                      tmax_fit + tfade * 2.0,
                      fillmethod='repeat')

        freqlimits = self.get_freqlimits()

        tr_syn = tr_syn.transfer(freqlimits=freqlimits, tfade=tfade)

        tr_syn.chop(tmin_fit - 2 * tfade, tmax_fit + 2 * tfade)

        tmin_obs, tmax_obs = self.get_cutout_timespan(tmin_fit + tobs_shift,
                                                      tmax_fit + tobs_shift,
                                                      tfade)

        try:
            tr_obs = ds.get_waveform(
                nslc,
                tinc_cache=1.0 / (config.fmin or 0.1 * config.fmax),
                tmin=tmin_fit + tobs_shift - tfade,
                tmax=tmax_fit + tobs_shift + tfade,
                tfade=tfade,
                freqlimits=freqlimits,
                deltat=tr_syn.deltat,
                cache=True,
                backazimuth=self.get_backazimuth_for_waveform())

            if tobs_shift != 0.0:
                tr_obs = tr_obs.copy()
                tr_obs.shift(-tobs_shift)

            mr = misfit(tr_obs,
                        tr_syn,
                        taper=trace.CosTaper(tmin_fit - tfade_taper, tmin_fit,
                                             tmax_fit, tmax_fit + tfade_taper),
                        domain=config.domain,
                        exponent=config.norm_exponent,
                        flip=self.flip_norm,
                        result_mode=self._result_mode,
                        tautoshift_max=config.tautoshift_max,
                        autoshift_penalty_max=config.autoshift_penalty_max,
                        subtargets=self._piggyback_subtargets)

            self._piggyback_subtargets = []

            mr.tobs_shift = float(tobs_shift)
            mr.tsyn_pick = float_or_none(tsyn)

            return mr

        except NotFound as e:
            logger.debug(str(e))
            raise gf.SeismosizerError('no waveform data, %s' % str(e))

    def prepare_modelling(self, engine, source, targets):
        return [self]

    def finalize_modelling(self, engine, source, modelling_targets,
                           modelling_results):

        return modelling_results[0]

    def get_plain_targets(self, engine, source):
        d = dict((k, getattr(self, k)) for k in gf.Target.T.propnames)
        return [gf.Target(**d)]

    def add_piggyback_subtarget(self, subtarget):
        self._piggyback_subtargets.append(subtarget)
コード例 #14
0
ファイル: data.py プロジェクト: chaoshunh/pinky
class DataGeneratorBase(Object):
    '''This is the base class for all generators.

    This class to dump and load data to/from all subclasses into
    TFRecordDatasets.
    '''
    fn_tfrecord = String.T(optional=True)
    noise = Noise.T(optional=True, help='Add noise to feature')

    station_dropout_rate = Float.T(default=0.,
        help='Rate by which to mask all channels of station')

    station_dropout_distribution = Bool.T(default=True,
        help='If *true*, station dropout will be drawn from a uniform '
        'distribution limited by this station_dropout.')

    nmax = Int.T(optional=True)
    labeled = Bool.T(default=True)
    blacklist = List.T(optional=True, help='List of indices to ignore.')

    random_seed = Int.T(default=0)

    def __init__(self, *args, **kwargs):
        self.config = kwargs.pop('config', None)
        super().__init__(**kwargs)
        self.blacklist = set() if not self.blacklist else set(self.blacklist)
        self.n_classes = self.config.n_classes
        self.evolution = 0

    def normalize_label(self, label):
        if self.labeled:
            return self.config.normalize_label(label)
        return label

    def set_config(self, pinky_config):
        self.config = pinky_config
        self.setup()

    def setup(self):
        ...

    def reset(self):
        self.evolution = 0

    @property
    def tensor_shape(self):
        return self.config.tensor_shape

    @property
    def n_samples(self):
        return self.config._n_samples

    @n_samples.setter
    def n_samples(self, v):
        self.config._n_samples = v

    @property
    @lru_cache(maxsize=1)
    def nsl_to_indices(self):
        ''' Returns a dictionary which maps nsl codes to indexing arrays.'''
        indices = OrderedDict()
        for nslc, index in self.nslc_to_index.items():
            key = nslc[:3]
            _v = indices.get(key, [])
            _v.append(index)
            indices[key] = _v

        for k in indices.keys():
            indices[k] = num.array(indices[k])

        return indices

    @property
    @lru_cache(maxsize=1)
    def nsl_indices(self):
        ''' Returns a 2D array of indices of channels belonging to one station.'''
        return [v for v in self.nsl_to_indices.values()]

    @property
    def nslc_to_index(self):
        ''' Returns a dictionary which maps nslc codes to trace indices.'''
        d = OrderedDict()
        idx = 0
        for nslc in self.config.channels:
            if not util.match_nslc(self.config.blacklist, nslc):
                d[nslc] = idx
                idx += 1
        return d

    def reject_blacklisted(self, tr):
        '''returns `False` if nslc codes of `tr` match any of the blacklisting
        patters. Otherwise returns `True`'''
        return not util.match_nslc(self.config.blacklist, tr.nslc_id)

    def filter_iter(self, iterator):
        '''Apply *blacklist*ing by example indices

        :param iterator: producing iterator
        '''
        for i, item in enumerate(iterator):
            if i not in self.blacklist:
                yield i, item

    @property
    def generate_output_types(self):
        '''Return data types of features and labels'''
        return tf.float32, tf.float32

    def unpack_examples(self, record_iterator):
        '''Parse examples stored in TFRecordData to `tf.train.Example`'''
        for string_record in record_iterator:
            example = tf.train.Example()
            example.ParseFromString(string_record)
            chunk = example.features.feature['data'].bytes_list.value[0]
            label = example.features.feature['label'].bytes_list.value[0]

            chunk = num.fromstring(chunk, dtype=num.float32)
            chunk = chunk.reshape((self.config.n_channels, -1))

            label = num.fromstring(label, dtype=num.float32)
            yield chunk, label

    @property
    def tstart_data(self):
        return None

    def iter_chunked(self, tinc):
        # if data has been written to tf records:
        return self.iter_examples_and_labels()

    def iter_examples_and_labels(self):
        '''Subclass this method!

        Yields: feature, label

        Chunks that are all NAN will be skipped.
        '''
        record_iterator = tf.python_io.tf_record_iterator(
            path=self.fn_tfrecord)

        for chunk, label in self.unpack_examples(record_iterator):
            if all_NAN(chunk):
                logger.debug('all NAN. skipping...')
                continue

            yield chunk, label

    def generate_chunked(self, tinc=1):
        '''Takes the output of `iter_examples_and_labels` and applies post
        processing (see: `process_chunk`).
        '''
        for i, (chunk, label) in self.filter_iter(self.iter_chunked(tinc)):
            yield self.process_chunk(chunk), self.normalize_label(label)

    def generate(self, return_gaps=False):
        '''Takes the output of `iter_examples_and_labels` and applies post
        processing (see: `process_chunk`).
        '''
        self.evolution += 1
        num.random.seed(self.random_seed + self.evolution)
        for i, (chunk, label) in self.filter_iter(
                self.iter_examples_and_labels()):
            yield self.process_chunk(chunk, return_gaps=return_gaps), self.normalize_label(label)

    def extract_labels(self):
        '''Overwrite this method!'''
        if not self.labeled:
            return UNLABELED

    def iter_labels(self):
        '''Iterate through labels.'''
        for i, (_, label) in self.filter_iter(
                self.iter_examples_and_labels()):
            yield label

    @property
    def text_labels(self):
        '''Returns a list of strings to identify the labels.

        Overwrite this method for more meaningfull identifiers.'''
        return ['%i' % (i) for i, d in
                self.filter_iter(self.iter_examples_and_labels())]

    def gaps(self):
        '''Returns a list containing the gaps of each example'''
        gaps = []
        for (_, gap), _ in self.generate(return_gaps=True):
            gaps.append(gap)

        return gaps

    def snrs(self, split_factor):
        snrs = []
        for chunk, _ in self.generate():
            snrs.append(snr(chunk, split_factor))
        return snrs

    @property
    def output_shapes(self):
        return (self.config.output_shapes)

    def get_dataset(self):
        return tf.data.Dataset.from_generator(
            self.generate,
            self.generate_output_types,
            output_shapes=self.output_shapes)

    def get_chunked_dataset(self, tinc=1.):
        gen = partial(self.generate_chunked, tinc=tinc)
        return tf.data.Dataset.from_generator(
            gen,
            self.generate_output_types,
            output_shapes=self.output_shapes)

    def get_raw_data_chunk(self, shape):
        '''Return an array of size (Nchannels x Nsamples_max) filled with
        NANs.'''
        empty_array = num.empty(shape, dtype=num.float32)
        empty_array.fill(num.nan)
        return empty_array

    def pack_examples(self):
        '''Serialize Examples to strings.'''
        for ydata, label in self.iter_examples_and_labels():
            yield tf.train.Example(
                features=tf.train.Features(
                    feature={
                        'data': _BytesFeature(ydata.tobytes()),
                        'label': _BytesFeature(num.array(
                            label, dtype=num.float32).tobytes()),
                    }))

    def mask(self, chunk, rate):
        '''For data augmentation: Mask traces in chunks with NaNs.
        NaNs will be filled by the imputation method provided by the config
        file.

        :param rate: probability with which traces are NaN-ed
        '''
        # print(rate)
        indices = self.nsl_indices
        a = num.random.random(len(indices))
        i = num.where(a < rate)[0]
        for ii in i:
            chunk[indices[ii], :] = num.nan

    def random_trim(self, chunk, margin):
        '''For data augmentation: Randomly trim examples in time domain with
        *margin* seconds.'''
        sample_margin = int(margin / self.config.effective_deltat)
        nstart = num.random.randint(low=0, high=sample_margin)

        _, n_samples = self.config.tensor_shape
        nstop = nstart + n_samples
        chunk[:, :nstart] = 0.
        chunk[:, nstop:] = 0.

    def process_chunk(self, chunk, return_gaps=False):
        '''Performs preprocessing of data chunks.'''

        if self.config.t_translation_max:
            self.random_trim(chunk, self.config.t_translation_max)

        # add noise
        if self.noise:
            self.noise(chunk)

        # apply normalization
        self.config.normalization(chunk)

        # apply station dropout
        if self.station_dropout_rate:
            if self.station_dropout_distribution:
                self.mask(chunk, num.random.uniform(
                    high=self.station_dropout_rate))
            else:
                self.mask(chunk, self.station_dropout_rate)

        # fill gaps
        if self.config.imputation:
            gaps = num.isnan(chunk)
            chunk[gaps] = self.config.imputation(chunk)

        if not return_gaps:
            return chunk
        else:
            return chunk, gaps

    def write(self, directory):
        '''Write example data to TFRecordDataset using `self.writer`.'''
        logger.debug('writing TFRecordDataset: %s' % directory)
        writer = tf.python_io.TFRecordWriter(directory)

        for ex in self.pack_examples():
            writer.write(ex.SerializeToString())

    def cleanup(self):
        '''Remove remaining folders'''
        delete_if_exists(self.fn_tfrecord)
コード例 #15
0
ファイル: data.py プロジェクト: chaoshunh/pinky
class SeismosizerData(DataGenerator):
    fn_sources = String.T(
            help='filename containing pyrocko.gf.seismosizer.Source instances')
    fn_targets = String.T(
            help='filename containing pyrocko.gf.seismosizer.Target instances',
            optional=True)
    fn_stations = String.T(
            help='filename containing pyrocko.model.Station instances. Will be\
                converted to Target instances',
            optional=True)

    store_id = String.T(optional=True)
    center_sources = Bool.T(
            default=False,
            help='Transform the center of sources to the center of stations')

    engine = LocalEngine.T()
    onset_phase = String.T(default='first(p|P)')

    def setup(self):
        self.sources = guts.load(filename=self.fn_sources)
        self.targets = []

        if self.fn_targets:
            self.targets.extend(guts.load(filename=self.fn_targets))

        if self.fn_stations:
            stats = load_stations(self.fn_stations)
            self.targets.extend(self.cast_stations_to_targets(stats))

        if self.store_id:
            for t in self.targets:
                t.store_id = self.store_id

        if self.center_sources:
            self.move_sources_to_station_center()

        self.config.channels = [t.codes for t in self.targets]
        store_ids = [t.store_id for t in self.targets]
        store_id = set(store_ids)
        assert len(store_id) == 1, 'More than one store used. Not \
                implemented yet'

        self.store = self.engine.get_store(store_id.pop())

        self.sources = filter_oob(self.sources, self.targets, self.store.config)

        dt = self.config.deltat_want or self.store.config.deltat
        self.n_samples = int((self.config.sample_length + self.config.tpad) / dt)

    def move_sources_to_station_center(self):
        '''Transform the center of sources to the center of stations.'''
        lat, lon = orthodrome.geographic_midpoint_locations(self.targets)
        for s in self.sources:
            s.lat = lat
            s.lon = lon

    def cast_stations_to_targets(self, stations):
        targets = []
        channels = 'ENZ'
        for s in stations:
            targets.extend(
                [Target(codes=(s.network, s.station, s.location, c),
                    lat=s.lat, lon=s.lon, elevation=s.elevation,) for c in
                    channels])

        return targets

    def extract_labels(self, source):
        if not self.labeled:
            return UNLABELED
        return (source.north_shift, source.east_shift, source.depth)

    def iter_examples_and_labels(self):
        ensure_list(self.sources)
        ensure_list(self.targets)

        response = self.engine.process(
            sources=self.sources,
            targets=self.targets)

        for isource, source in enumerate(response.request.sources):
            traces = [x.trace.pyrocko_trace() for x in \
                    response.results_list[isource]]

            for tr in traces:
                self.preprocess(tr)
            arrivals = [self.store.t(self.onset_phase,
                (source.depth, source.distance_to(t))) for t in self.targets]
            tref = min([a for a in arrivals if a is not None])
            chunk = self.get_raw_data_chunk(self.tensor_shape)

            self.fit_data_into_chunk(traces, chunk=chunk, tref=tref+source.time)

            label = self.extract_labels(source)

            yield chunk, label
コード例 #16
0
class GACOSConfig(PluginConfig):
    grd_filenames = List.T(default=[], help="List of *two* GACOS gridfiles.")
    applied = Bool.T(default=False, help="Is the correction applied.")
コード例 #17
0
class AutoScaler(Object):

    '''
    Tunable 1D autoscaling based on data range.

    Instances of this class may be used to determine nice minima, maxima and
    increments for ax annotations, as well as suitable common exponents for
    notation.

    The autoscaling process is guided by the following public attributes:
    '''

    approx_ticks = Float.T(
        default=7.0,
        help='Approximate number of increment steps (tickmarks) to generate.')

    mode = AutoScaleMode.T(
        default='auto',
        help='''Mode of operation for auto-scaling.''')

    exp = Int.T(
        optional=True,
        help='If defined, override automatically determined exponent for '
             'notation by the given value.')

    snap = Bool.T(
        default=False,
        help='If set to True, snap output range to multiples of increment. '
             'This parameter has no effect, if mode is set to ``\'off\'``.')

    inc = Float.T(
        optional=True,
        help='If defined, override automatically determined tick increment by '
             'the given value.')

    space = Float.T(
        default=0.0,
        help='Add some padding to the range. The value given, is the fraction '
             'by which the output range is increased on each side. If mode is '
             '``\'0-max\'`` or ``\'min-0\'``, the end at zero is kept fixed '
             'at zero. This parameter has no effect if mode is set to '
             '``\'off\'``.')

    exp_factor = Int.T(
        default=3,
        help='Exponent of notation is chosen to be a multiple of this value.')

    no_exp_interval = Tuple.T(
        2, Int.T(),
        default=(-3, 5),
        help='Range of exponent, for which no exponential notation is a'
             'allowed.')

    def __init__(
            self,
            approx_ticks=7.0,
            mode='auto',
            exp=None,
            snap=False,
            inc=None,
            space=0.0,
            exp_factor=3,
            no_exp_interval=(-3, 5)):

        '''
        Create new AutoScaler instance.

        The parameters are described in the AutoScaler documentation.
        '''

        Object.__init__(
            self,
            approx_ticks=approx_ticks,
            mode=mode,
            exp=exp,
            snap=snap,
            inc=inc,
            space=space,
            exp_factor=exp_factor,
            no_exp_interval=no_exp_interval)

    def make_scale(self, data_range, override_mode=None):

        '''
        Get nice minimum, maximum and increment for given data range.

        Returns ``(minimum, maximum, increment)`` or ``(maximum, minimum,
        -increment)``, depending on whether data_range is ``(data_min,
        data_max)`` or ``(data_max, data_min)``. If ``override_mode`` is
        defined, the mode attribute is temporarily overridden by the given
        value.
        '''

        data_min = min(data_range)
        data_max = max(data_range)

        is_reverse = (data_range[0] > data_range[1])

        a = self.mode
        if self.mode == 'auto':
            a = self.guess_autoscale_mode(data_min, data_max)

        if override_mode is not None:
            a = override_mode

        mi, ma = 0, 0
        if a == 'off':
            mi, ma = data_min, data_max
        elif a == '0-max':
            mi = 0.0
            if data_max > 0.0:
                ma = data_max
            else:
                ma = 1.0
        elif a == 'min-0':
            ma = 0.0
            if data_min < 0.0:
                mi = data_min
            else:
                mi = -1.0
        elif a == 'min-max':
            mi, ma = data_min, data_max
        elif a == 'symmetric':
            m = max(abs(data_min), abs(data_max))
            mi = -m
            ma = m

        nmi = mi
        if (mi != 0. or a == 'min-max') and a != 'off':
            nmi = mi - self.space*(ma-mi)

        nma = ma
        if (ma != 0. or a == 'min-max') and a != 'off':
            nma = ma + self.space*(ma-mi)

        mi, ma = nmi, nma

        if mi == ma and a != 'off':
            mi -= 1.0
            ma += 1.0

        # make nice tick increment
        if self.inc is not None:
            inc = self.inc
        else:
            if self.approx_ticks > 0.:
                inc = nice_value((ma-mi) / self.approx_ticks)
            else:
                inc = nice_value((ma-mi)*10.)

        if inc == 0.0:
            inc = 1.0

        # snap min and max to ticks if this is wanted
        if self.snap and a != 'off':
            ma = inc * math.ceil(ma/inc)
            mi = inc * math.floor(mi/inc)

        if is_reverse:
            return ma, mi, -inc
        else:
            return mi, ma, inc

    def make_exp(self, x):
        '''Get nice exponent for notation of ``x``.

        For ax annotations, give tick increment as ``x``.'''

        if self.exp is not None:
            return self.exp

        x = abs(x)
        if x == 0.0:
            return 0

        if 10**self.no_exp_interval[0] <= x <= 10**self.no_exp_interval[1]:
            return 0

        return math.floor(math.log10(x)/self.exp_factor)*self.exp_factor

    def guess_autoscale_mode(self, data_min, data_max):
        '''Guess mode of operation, based on data range.

        Used to map ``'auto'`` mode to ``'0-max'``, ``'min-0'``, ``'min-max'``
        or ``'symmetric'``.'''

        a = 'min-max'
        if data_min >= 0.0:
            if data_min < data_max/2.:
                a = '0-max'
            else:
                a = 'min-max'
        if data_max <= 0.0:
            if data_max > data_min/2.:
                a = 'min-0'
            else:
                a = 'min-max'
        if data_min < 0.0 and data_max > 0.0:
            if abs((abs(data_max)-abs(data_min)) /
                   (abs(data_max)+abs(data_min))) < 0.5:
                a = 'symmetric'
            else:
                a = 'min-max'
        return a
コード例 #18
0
class DerampConfig(PluginConfig):

    demean = Bool.T(optional=True, default=True)
コード例 #19
0
class SatelliteTargetDisplacement(PlotConfig):
    ''' Maps showing surface displacements from satellite and modelled data '''

    name = 'satellite'
    dpi = Int.T(
        default=250)
    size_cm = Tuple.T(
        2, Float.T(),
        default=(22., 12.))
    colormap = String.T(
        default='RdBu',
        help='Colormap for the surface displacements')
    relative_coordinates = Bool.T(
        default=False,
        help='Show relative coordinates, initial location centered at 0N, 0E')
    fit = StringChoice.T(
        default='best', choices=['best', 'mean'],
        help='Show the \'best\' or \'mean\' fits and source model from the'
             ' ensamble.')

    show_topo = Bool.T(
        default=True,
        help='Drape displacements over the topography.')
    displacement_unit = StringChoice.T(
        default='m',
        choices=['m', 'mm', 'cm', 'rad'],
        help="Show results in 'm', 'cm', 'mm' or 'rad' for radians.")
    show_leaf_centres = Bool.T(
        default=True,
        help='show the center points of Quadtree leaves')
    source_outline_color = String.T(
        default='grey',
        help='Choose color of source outline from named matplotlib Colors')
    common_color_scale = Bool.T(
        default=True,
        help='Results shown with common color scale for all satellite '
             'data sets (based on the data)')
    map_limits = Tuple.T(
        4, Float.T(),
        optional=True,
        help='Overwrite map limits in native coordinates. '
             'Use (xmin, xmax, ymin, ymax)')
    nticks_x = Int.T(
        optional=True,
        help='Number of ticks on the x-axis.')

    def make(self, environ):
        cm = environ.get_plot_collection_manager()
        history = environ.get_history(subset='harvest')
        optimiser = environ.get_optimiser()
        ds = environ.get_dataset()

        environ.setup_modelling()

        cm.create_group_mpl(
            self,
            self.draw_static_fits(ds, history, optimiser),
            title=u'InSAR Displacements',
            section='fits',
            feather_icon='navigation',
            description=u'''
Maps showing subsampled surface displacements as observed, modelled and the
residual (observed minus modelled).

The displacement values predicted by the orbit-ambiguity ramps are added to the
modelled displacements (middle panels). The color shows the LOS displacement
values associated with, and the extent of, every quadtree box. The light grey
dots show the focal point of pixels combined in the quadtree box. This point
corresponds to the position of the modelled data point.

The large dark grey dot shows the reference source position. The grey filled
box shows the surface projection of the modelled source, with the thick-lined
edge marking the upper fault edge. Complete data extent is shown.
''')

    def draw_static_fits(self, ds, history, optimiser, closeup=False):
        from pyrocko.orthodrome import latlon_to_ne_numpy
        problem = history.problem

        sat_targets = problem.satellite_targets
        for target in sat_targets:
            target.set_dataset(ds)

        if self.fit == 'best':
            source = history.get_best_source()
            model = history.get_best_model()
        elif self.fit == 'mean':
            source = history.get_mean_source()
            model = history.get_mean_model()

        results = problem.evaluate(model, targets=sat_targets)

        def init_axes(ax, scene, title, last_axes=False):
            ax.set_title(title, fontsize=self.font_size)
            ax.tick_params(length=2)

            if scene.frame.isMeter():
                import utm
                ax.set_xlabel('Easting [km]', fontsize=self.font_size)
                scale_x = dict(scale=1./km)
                scale_y = dict(scale=1./km)
                utm_E, utm_N, utm_zone, utm_zone_letter =\
                    utm.from_latlon(source.effective_lat,
                                    source.effective_lon)
                scale_x['offset'] = utm_E
                scale_y['offset'] = utm_N

                if last_axes:
                    ax.text(0.975, 0.025,
                            'UTM Zone %d%s' % (utm_zone, utm_zone_letter),
                            va='bottom', ha='right',
                            fontsize=8, alpha=.7,
                            transform=ax.transAxes)
                ax.set_aspect('equal')

            elif scene.frame.isDegree():
                scale_x = dict(scale=1., suffix='°')
                scale_y = dict(scale=1., suffix='°')
                scale_x['offset'] = source.effective_lon
                scale_y['offset'] = source.effective_lat

                ax.set_aspect(1./num.cos(source.effective_lat*d2r))

            if self.relative_coordinates:
                scale_x['offset'] = 0.
                scale_y['offset'] = 0.

            nticks_x = 4 if abs(scene.frame.llLon) >= 100 else 5

            ax.xaxis.set_major_locator(MaxNLocator(self.nticks_x or nticks_x))
            ax.yaxis.set_major_locator(MaxNLocator(5))

            ax.scale_x = scale_x
            ax.scale_y = scale_y

            scale_axes(ax.get_xaxis(), **scale_x)
            scale_axes(ax.get_yaxis(), **scale_y)

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

            # source is centered
            ax.scatter(0., 0., color='black', s=3, alpha=.5, marker='o')
            ax.fill(fe, fn,
                    edgecolor=(0., 0., 0.),
                    facecolor=self.source_outline_color,
                    alpha=0.7)
            ax.plot(fe[0:2], fn[0:2], 'k', linewidth=1.3)

        def get_displacement_rgba(displacements, scene, mappable):
            arr = num.full_like(scene.displacement, fill_value=num.nan)
            qt = scene.quadtree

            for syn_v, leaf in zip(displacements, qt.leaves):
                arr[leaf._slice_rows, leaf._slice_cols] = syn_v

            arr[scene.displacement_mask] = num.nan

            if not self.common_color_scale \
                    and not self.displacement_unit == 'rad':
                abs_displ = num.abs(displacements).max()
                mappable.set_clim(-abs_displ, abs_displ)

            if self.show_topo:
                try:
                    elevation = scene.get_elevation()
                    return drape_displacements(arr, elevation, mappable)
                except Exception as e:
                    logger.warning('could not plot hillshaded topo')
                    logger.exception(e)

            return mappable.to_rgba(arr)

        def draw_leaves(ax, scene, offset_e=0., offset_n=0.):
            rects = scene.quadtree.getMPLRectangles()
            for r in rects:
                r.set_edgecolor((.4, .4, .4))
                r.set_linewidth(.5)
                r.set_facecolor('none')
                r.set_x(r.get_x() - offset_e)
                r.set_y(r.get_y() - offset_n)
            map(ax.add_artist, rects)

            if self.show_leaf_centres:
                ax.scatter(scene.quadtree.leaf_coordinates[:, 0] - offset_e,
                           scene.quadtree.leaf_coordinates[:, 1] - offset_n,
                           s=.25, c='black', alpha=.1)

        def add_arrow(ax, scene):
            phi = num.nanmean(scene.phi)
            los_dx = num.cos(phi + num.pi) * .0625
            los_dy = num.sin(phi + num.pi) * .0625

            az_dx = num.cos(phi - num.pi/2) * .125
            az_dy = num.sin(phi - num.pi/2) * .125

            anchor_x = .9 if los_dx < 0 else .1
            anchor_y = .85 if los_dx < 0 else .975

            az_arrow = patches.FancyArrow(
                x=anchor_x-az_dx, y=anchor_y-az_dy,
                dx=az_dx, dy=az_dy,
                head_width=.025,
                alpha=.5, fc='k',
                head_starts_at_zero=False,
                length_includes_head=True,
                transform=ax.transAxes)

            los_arrow = patches.FancyArrow(
                x=anchor_x-az_dx/2, y=anchor_y-az_dy/2,
                dx=los_dx, dy=los_dy,
                head_width=.02,
                alpha=.5, fc='k',
                head_starts_at_zero=False,
                length_includes_head=True,
                transform=ax.transAxes)

            ax.add_artist(az_arrow)
            ax.add_artist(los_arrow)

        urE, urN, llE, llN = (0., 0., 0., 0.)
        for target in sat_targets:

            if target.scene.frame.isMeter():
                off_n, off_e = map(float, latlon_to_ne_numpy(
                    target.scene.frame.llLat, target.scene.frame.llLon,
                    source.effective_lat, source.effective_lon))
            if target.scene.frame.isDegree():
                off_n = source.effective_lat - target.scene.frame.llLat
                off_e = source.effective_lon - target.scene.frame.llLon

            turE, turN, tllE, tllN = zip(
                *[(leaf.gridE.max()-off_e,
                   leaf.gridN.max()-off_n,
                   leaf.gridE.min()-off_e,
                   leaf.gridN.min()-off_n)
                  for leaf in target.scene.quadtree.leaves])

            turE, turN = map(max, (turE, turN))
            tllE, tllN = map(min, (tllE, tllN))
            urE, urN = map(max, ((turE, urE), (urN, turN)))
            llE, llN = map(min, ((tllE, llE), (llN, tllN)))

        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)

        for ifig, (sat_target, result) in enumerate(zip(sat_targets, results)):
            yield generate_plot(sat_target, result, ifig)
コード例 #20
0
class PlotSettings(Object):
    trace_filename = String.T(help='filename of beam or trace to use for '
                              'plotting, incl. path.',
                              optional=True)
    station_filename = String.T(help='filename containing station meta '
                                'information related to *trace_filename*.',
                                optional=True)
    event_filename = String.T(help='filename containing event information '
                              'including the expected moment tensor.',
                              default='event.pf')
    store_id = String.T(help='Store ID to use for generating the synthetic '
                        'traces.',
                        optional=True)
    store_superdirs = List.T(String.T(), optional=True)
    depth = Float.T(help='Depth [km] where to put the trace.', default=10.)
    depths = String.T(help='Synthetic source depths [km]. start:stop:delta. '
                      'default: 0:15:1',
                      optional=True,
                      default='0:15:1')
    filters = List.T(
        FrequencyResponse.T(help='List of filters used to filter '
                            'the traces'))
    zoom = List.T(Float.T(),
                  help='Window to visualize with reference to the P '
                  'phase onset [s].',
                  default=[-7, 15])
    correction = Float.T(help='time shift, to move beam trace.', default=0.)
    normalize = Bool.T(help='normalize by maximum amplitude', default=True)
    save_as = String.T(default='depth_%(array-id)s.png',
                       help='filename of output figure')
    force_nearest_neighbor = Bool.T(help='Handles OutOfBounds exceptions. '
                                    'applies only laterally!',
                                    default=False)
    auto_caption = Bool.T(
        help='Add a caption giving basic information to the figure.',
        default=False)
    title = String.T(default='%(array-id)s - %(event_name)s',
                     help='Add default title.')
    quantity = String.T(default='velocity',
                        help='velocity-> differentiate synthetic.'
                        'displacement-> integrate recorded')
    gain = Float.T(default=1., help='Gain factor')
    gain_record = Float.T(default=1., help='Gain factor')
    color = String.T(help='Trace color', default='blue')

    def update_from_args(self, args):
        kwargs = {}
        try:
            hp, lp = args.filter.split(':')
            filters = [
                ButterworthResponse(corner=float(lp), order=4, type='low'),
                ButterworthResponse(corner=float(hp), order=4, type='high')
            ]
            kwargs.update({'filters': filters})
        except:
            pass

        kwargs.update(self.process_arglist(args))
        for arg, v in kwargs.items():
            setattr(self, arg, v)

    @classmethod
    def from_argument_parser(cls, args):
        try:
            hp, lp = args.filter.split(':')
        except AttributeError:
            hp, lp = (0.7, 4.5)
        filters = [
            ButterworthResponse(corner=float(lp), order=4, type='low'),
            ButterworthResponse(corner=float(hp), order=4, type='high')
        ]
        kwargs = cls.process_arglist(args)
        return cls(filters=filters, **kwargs)

    def do_filter(self, tr):
        for f in self.filters:
            tr = tr.transfer(transfer_function=f,
                             tfade=10,
                             cut_off_fading=False)
        return tr

    @staticmethod
    def process_arglist(args):
        kwargs = {}
        for arg in arglist:
            try:
                val = getattr(args, arg)
                if arg == 'zoom' and val:
                    val = val.split(':')
                    val = map(float, val)
                if val:
                    kwargs.update({arg: val})
            except AttributeError:
                logger.debug('%s not defined' % arg)
                continue

        return kwargs
コード例 #21
0
class SatelliteTargetDisplacement(PlotConfig):
    ''' Maps showing surface displacements from satellite and modelled data '''

    name = 'satellite'
    dpi = Int.T(default=250)
    size_cm = Tuple.T(2, Float.T(), default=(22., 12.))
    colormap = String.T(default='RdBu',
                        help='Colormap for the surface displacements')
    relative_coordinates = Bool.T(
        default=False,
        help='Show relative coordinates, initial location centered at 0N, 0E')

    def make(self, environ):
        cm = environ.get_plot_collection_manager()
        history = environ.get_history(subset='harvest')
        optimiser = environ.get_optimiser()
        ds = environ.get_dataset()

        environ.setup_modelling()

        cm.create_group_mpl(self,
                            self.draw_static_fits(ds, history, optimiser),
                            title=u'InSAR Displacements',
                            section='fits',
                            feather_icon='navigation',
                            description=u'''
Maps showing subsampled surface displacements as observed, modelled and the
residual (observed minus modelled).

The displacement values predicted by the orbit-ambiguity ramps are added to the
modelled displacements (middle panels). The color shows the LOS displacement
values associated with, and the extent of, every quadtree box. The light grey
dots show the focal point of pixels combined in the quadtree box. This point
corresponds to the position of the modelled data point.

The large dark grey dot shows the reference source position. The grey filled
box shows the surface projection of the modelled source, with the thick-lined
edge marking the upper fault edge. Complete data extent is shown.
''')

    def draw_static_fits(self, ds, history, optimiser, closeup=False):
        from pyrocko.orthodrome import latlon_to_ne_numpy
        problem = history.problem

        sat_targets = problem.satellite_targets
        for target in sat_targets:
            target.set_dataset(ds)

        source = history.get_best_source()
        best_model = history.get_best_model()
        results = problem.evaluate(best_model, targets=sat_targets)

        def initAxes(ax, scene, title, last_axes=False):
            ax.set_title(title)
            ax.tick_params(length=2)

            if scene.frame.isMeter():
                ax.set_xlabel('Easting [km]')
                scale_x = {'scale': 1. / km}
                scale_y = {'scale': 1. / km}
                if not self.relative_coordinates:
                    import utm
                    utm_E, utm_N, utm_zone, utm_zone_letter =\
                        utm.from_latlon(source.effective_lat,
                                        source.effective_lon)
                    scale_x['offset'] = utm_E
                    scale_y['offset'] = utm_N

                    if last_axes:
                        ax.text(0.975,
                                0.025,
                                'UTM Zone %d%s' % (utm_zone, utm_zone_letter),
                                va='bottom',
                                ha='right',
                                fontsize=8,
                                alpha=.7,
                                transform=ax.transAxes)
                ax.set_aspect('equal')

            elif scene.frame.isDegree():
                ax.set_xlabel('Lon [°]')
                scale_x = {'scale': 1.}
                scale_y = {'scale': 1.}
                if not self.relative_coordinates:
                    scale_x['offset'] = source.effective_lon
                    scale_y['offset'] = source.effective_lat
                ax.set_aspect(1. / num.cos(source.effective_lat * d2r))

            scale_axes(ax.get_xaxis(), **scale_x)
            scale_axes(ax.get_yaxis(), **scale_y)

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

            # source is centered
            ax.scatter(0., 0., color='black', s=3, alpha=.5, marker='o')
            ax.fill(fe,
                    fn,
                    edgecolor=(0., 0., 0.),
                    facecolor=(.5, .5, .5),
                    alpha=0.7)
            ax.plot(fe[0:2], fn[0:2], 'k', linewidth=1.3)

        def mapDisplacementGrid(displacements, scene):
            arr = num.full_like(scene.displacement, fill_value=num.nan)
            qt = scene.quadtree

            for syn_v, l in zip(displacements, qt.leaves):
                arr[l._slice_rows, l._slice_cols] = syn_v

            arr[scene.displacement_mask] = num.nan
            return arr

        def drawLeaves(ax, scene, offset_e=0., offset_n=0.):
            rects = scene.quadtree.getMPLRectangles()
            for r in rects:
                r.set_edgecolor((.4, .4, .4))
                r.set_linewidth(.5)
                r.set_facecolor('none')
                r.set_x(r.get_x() - offset_e)
                r.set_y(r.get_y() - offset_n)
            map(ax.add_artist, rects)

            ax.scatter(scene.quadtree.leaf_coordinates[:, 0] - offset_e,
                       scene.quadtree.leaf_coordinates[:, 1] - offset_n,
                       s=.25,
                       c='black',
                       alpha=.1)

        def addArrow(ax, scene):
            phi = num.nanmean(scene.phi)
            los_dx = num.cos(phi + num.pi) * .0625
            los_dy = num.sin(phi + num.pi) * .0625

            az_dx = num.cos(phi - num.pi / 2) * .125
            az_dy = num.sin(phi - num.pi / 2) * .125

            anchor_x = .9 if los_dx < 0 else .1
            anchor_y = .85 if los_dx < 0 else .975

            az_arrow = patches.FancyArrow(x=anchor_x - az_dx,
                                          y=anchor_y - az_dy,
                                          dx=az_dx,
                                          dy=az_dy,
                                          head_width=.025,
                                          alpha=.5,
                                          fc='k',
                                          head_starts_at_zero=False,
                                          length_includes_head=True,
                                          transform=ax.transAxes)

            los_arrow = patches.FancyArrow(x=anchor_x - az_dx / 2,
                                           y=anchor_y - az_dy / 2,
                                           dx=los_dx,
                                           dy=los_dy,
                                           head_width=.02,
                                           alpha=.5,
                                           fc='k',
                                           head_starts_at_zero=False,
                                           length_includes_head=True,
                                           transform=ax.transAxes)

            ax.add_artist(az_arrow)
            ax.add_artist(los_arrow)

        urE, urN, llE, llN = (0., 0., 0., 0.)
        for target in sat_targets:

            if target.scene.frame.isMeter():
                off_n, off_e = map(
                    float,
                    latlon_to_ne_numpy(target.scene.frame.llLat,
                                       target.scene.frame.llLon,
                                       source.effective_lat,
                                       source.effective_lon))
            if target.scene.frame.isDegree():
                off_n = source.effective_lat - target.scene.frame.llLat
                off_e = source.effective_lon - target.scene.frame.llLon

            turE, turN, tllE, tllN = zip(
                *[(l.gridE.max() - off_e, l.gridN.max() - off_n,
                   l.gridE.min() - off_e, l.gridN.min() - off_n)
                  for l in target.scene.quadtree.leaves])

            turE, turN = map(max, (turE, turN))
            tllE, tllN = map(min, (tllE, tllN))
            urE, urN = map(max, ((turE, urE), (urN, turN)))
            llE, llN = map(min, ((tllE, llE), (llN, tllN)))

        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)

        for ifig, (sat_target, result) in enumerate(zip(sat_targets, results)):
            yield generate_plot(sat_target, result, ifig)
コード例 #22
0
class PhaseRatioTargetGroup(TargetGroup):

    '''
    Generate targets to compare ratios or log ratios of two seismic phases.

      misfit = | a_obs / (a_obs + b_obs)  - a_syn / (a_syn + b_syn) |

    or

      misfit = | log(a_obs / (a_obs + b_obs) + waterlevel)  -
                 log(a_syn / (a_syn + b_syn) + waterlevel) |
    '''

    distance_min = Float.T(optional=True)
    distance_max = Float.T(optional=True)
    distance_3d_min = Float.T(optional=True)
    distance_3d_max = Float.T(optional=True)
    depth_min = Float.T(optional=True)
    depth_max = Float.T(optional=True)
    measure_a = fm.FeatureMeasure.T()
    measure_b = fm.FeatureMeasure.T()
    interpolation = gf.InterpolationMethod.T()
    store_id = gf.StringID.T(optional=True)
    store_id_selector = StoreIDSelector.T(
            optional=True,
            help='select GF store based on event-station geometry.')

    fit_log_ratio = Bool.T(
        default=True,
        help='If true, compare synthetic and observed log ratios')

    fit_log_ratio_waterlevel = Float.T(
        default=0.01,
        help='Waterlevel added to both ratios when comparing on logarithmic '
             'scale, to avoid log(0)')

    def get_targets(self, ds, event, default_path='none'):
        logger.debug('Selecting phase ratio targets...')
        origin = event
        targets = []

        for st in ds.get_stations():
            blacklisted = False
            for measure in [self.measure_a, self.measure_b]:
                for cha in measure.channels:
                    if ds.is_blacklisted((st.nsl() + (cha,))):
                        blacklisted = True

            if self.store_id_selector:
                store_id = self.store_id_selector.get_store_id(
                    event, st, cha)
            else:
                store_id = self.store_id

            target = PhaseRatioTarget(
                codes=st.nsl(),
                lat=st.lat,
                lon=st.lon,
                north_shift=st.north_shift,
                east_shift=st.east_shift,
                depth=st.depth,
                interpolation=self.interpolation,
                store_id=store_id,
                measure_a=self.measure_a,
                measure_b=self.measure_b,
                manual_weight=self.weight,
                normalisation_family=self.normalisation_family,
                path=self.path or default_path,
                backazimuth=0.0,
                fit_log_ratio=self.fit_log_ratio,
                fit_log_ratio_waterlevel=self.fit_log_ratio_waterlevel)

            if blacklisted:
                log_exclude(target, 'blacklisted')
                continue

            if self.distance_min is not None and \
               target.distance_to(origin) < self.distance_min:
                log_exclude(target, 'distance < distance_min')
                continue

            if self.distance_max is not None and \
               target.distance_to(origin) > self.distance_max:
                log_exclude(target, 'distance > distance_max')
                continue

            if self.distance_3d_min is not None and \
               target.distance_3d_to(origin) < self.distance_3d_min:
                log_exclude(target, 'distance_3d < distance_3d_min')
                continue

            if self.distance_3d_max is not None and \
               target.distance_3d_to(origin) > self.distance_3d_max:
                log_exclude(target, 'distance_3d > distance_3d_max')
                continue

            if self.depth_min is not None and \
               target.depth < self.depth_min:
                log_exclude(target, 'depth < depth_min')
                continue

            if self.depth_max is not None and \
               target.depth > self.depth_max:
                log_exclude(target, 'depth > depth_max')
                continue

            bazi, _ = target.azibazi_to(origin)
            target.backazimuth = bazi
            target.set_dataset(ds)
            targets.append(target)

        return targets
コード例 #23
0
ファイル: data.py プロジェクト: chaoshunh/pinky
class PileData(DataGenerator):
    '''Data generator for locally saved data.'''
    fn_stations = String.T()
    data_paths = List.T(String.T())
    data_format = String.T(default='detect')
    fn_markers = String.T()
    fn_events = String.T(optional=True)
    sort_markers = Bool.T(default=False,
            help= 'Sorting markers speeds up data io. Shuffled markers \
            improve generalization')
    align_phase = String.T(default='P')

    tstart = String.T(optional=True)
    tstop = String.T(optional=True)

    def setup(self):
        self.data_pile = pile.make_pile(
            self.data_paths, fileformat=self.data_format)

        if self.data_pile.is_empty():
            sys.exit('Data pile is empty!')

        self.deltat_want = self.config.deltat_want or \
                min(self.data_pile.deltats.keys())

        self.n_samples = int(
                (self.config.sample_length + self.config.tpad) / self.deltat_want)

        logger.debug('loading marker file %s' % self.fn_markers)

        # loads just plain markers:
        markers = marker.load_markers(self.fn_markers)

        if self.fn_events:
            markers.extend(
                    [marker.EventMarker(e) for e in
                load_events(self.fn_events)])

        if self.sort_markers:
            logger.info('sorting markers!')
            markers.sort(key=lambda x: x.tmin)
        marker.associate_phases_to_events(markers)

        markers_by_nsl = {}
        for m in markers:
            if not m.match_nsl(self.config.reference_target.codes[:3]):
                continue

            if m.get_phasename().upper() != self.align_phase:
                continue

            markers_by_nsl.setdefault(m.one_nslc()[:3], []).append(m)

        assert(len(markers_by_nsl) == 1)

        # filter markers that do not have an event assigned:
        self.markers = list(markers_by_nsl.values())[0]

        if not self.labeled:
            dummy_event = Event(lat=0., lon=0., depth=0.)
            for m in self.markers:
                if not m.get_event():
                    m.set_event(dummy_event)

        self.markers = [m for m in self.markers if m.get_event() is not None]

        if not len(self.markers):
            raise Exception('No markers left in dataset')

        self.config.channels = list(self.data_pile.nslc_ids.keys())
        self.config.channels.sort()

    def check_inputs(self):
        if len(self.data_pile.deltats()) > 1:
            logger.warn(
                'Different sampling rates in dataset. Preprocessing slow')

    def extract_labels(self, marker):
        if not self.labeled:
            return UNLABELED

        source = marker.get_event()
        n, e = orthodrome.latlon_to_ne(
            self.config.reference_target.lat, self.config.reference_target.lon,
            source.lat, source.lon)
        return (n, e, source.depth)

    @property
    def tstart_data(self):
        '''Returns start point of data returned by generator.'''
        return util.stt(self.tstart) if self.tstart else self.data_pile.tmin

    def iter_chunked(self, tinc):
        tr_len = self.n_samples * self.deltat_want
        nslc_to_index = self.nslc_to_index

        tpad = self.config.effective_tpad

        tstart = util.stt(self.tstart) if self.tstart else None
        tstop = util.stt(self.tstop) if self.tstop else None

        logger.debug('START')
        for trs in self.data_pile.chopper(
                tinc=tinc, tmin=tstart, tmax=tstop, tpad=tpad,
                keep_current_files_open=True, want_incomplete=False,
                trace_selector=self.reject_blacklisted):

            chunk = self.get_raw_data_chunk(self.tensor_shape)

            if not trs:
                yield chunk, UNLABELED
                continue

            for tr in trs:
                self.preprocess(tr)

            indices = [nslc_to_index[tr.nslc_id] for tr in trs]
            self.fit_data_into_chunk(trs, chunk=chunk, indices=indices,
                    tref=trs[0].tmin)

            if all_NAN(chunk):
                logger.debug('all NAN. skipping...')
                continue

            yield chunk, UNLABELED

    def iter_labels(self):
        for m in self.markers:
            yield self.extract_labels(m)

    def iter_examples_and_labels(self):
        tr_len = self.n_samples * self.deltat_want
        nslc_to_index = self.nslc_to_index

        tpad = self.config.effective_tpad

        for i_m, m in enumerate(self.markers):
            logger.debug('processig marker %s / %s' % (i_m, len(self.markers)))

            for trs in self.data_pile.chopper(
                    tmin=m.tmin-tpad, tmax=m.tmax+tr_len+tpad,
                    keep_current_files_open=True,
                    want_incomplete=False,
                    trace_selector=self.reject_blacklisted):

                for tr in trs:
                    self.preprocess(tr)

                indices = [nslc_to_index[tr.nslc_id] for tr in trs]
                chunk = self.get_raw_data_chunk(self.tensor_shape)
                self.fit_data_into_chunk(trs, chunk=chunk, indices=indices, tref=m.tmin)

                if all_NAN(chunk):
                    logger.debug('all NAN. skipping...')
                    continue

                label = self.extract_labels(m)
                yield chunk, label
コード例 #24
0
ファイル: automap.py プロジェクト: lileipku00/pyrocko
class Map(Object):
    lat = Float.T(optional=True)
    lon = Float.T(optional=True)
    radius = Float.T(optional=True)
    width = Float.T(default=20.)
    height = Float.T(default=14.)
    margins = List.T(Float.T())
    illuminate = Bool.T(default=True)
    skip_feature_factor = Float.T(default=0.02)
    show_grid = Bool.T(default=False)
    show_topo = Bool.T(default=True)
    show_topo_scale = Bool.T(default=False)
    show_center_mark = Bool.T(default=False)
    show_rivers = Bool.T(default=True)
    illuminate_factor_land = Float.T(default=0.5)
    illuminate_factor_ocean = Float.T(default=0.25)
    color_wet = Tuple.T(3, Int.T(), default=(216, 242, 254))
    color_dry = Tuple.T(3, Int.T(), default=(172, 208, 165))
    topo_resolution_min = Float.T(
        default=40., help='minimum resolution of topography [dpi]')
    topo_resolution_max = Float.T(
        default=200., help='maximum resolution of topography [dpi]')
    replace_topo_color_only = FloatTile.T(
        optional=True,
        help='replace topo color while keeping topographic shading')
    topo_cpt_wet = String.T(default='light_sea')
    topo_cpt_dry = String.T(default='light_land')
    axes_layout = String.T(optional=True)
    custom_cities = List.T(City.T())
    gmt_config = Dict.T(String.T(), String.T())
    comment = String.T(optional=True)

    def __init__(self, **kwargs):
        Object.__init__(self, **kwargs)
        self._gmt = None
        self._scaler = None
        self._widget = None
        self._corners = None
        self._wesn = None
        self._minarea = None
        self._coastline_resolution = None
        self._rivers = None
        self._dems = None
        self._have_topo_land = None
        self._have_topo_ocean = None
        self._jxyr = None
        self._prep_topo_have = None
        self._labels = []

    def save(self,
             outpath,
             resolution=75.,
             oversample=2.,
             size=None,
             width=None,
             height=None):
        '''Save the image.

        Save the image to *outpath*. The format is determined by the filename
        extension. Formats are handled as follows: ``'.eps'`` and ``'.ps'``
        produce EPS and PS, respectively, directly with GMT. If the file name
        ends with ``'.pdf'``, GMT output is fed through ``gmtpy-epstopdf`` to
        create a PDF file. For any other filename extension, output is first
        converted to PDF with ``gmtpy-epstopdf``, then with ``pdftocairo`` to
        PNG with a resolution oversampled by the factor *oversample* and
        finally the PNG is downsampled and converted to the target format with
        ``convert``. The resolution of rasterized target image can be
        controlled either by *resolution* in DPI or by specifying *width* or
        *height* or *size*, where the latter fits the image into a square with
        given side length.'''

        gmt = self.gmt
        self.draw_labels()
        self.draw_axes()
        if self.show_topo and self.show_topo_scale:
            self._draw_topo_scale()

        gmt = self._gmt
        if outpath.endswith('.eps'):
            tmppath = gmt.tempfilename() + '.eps'
        elif outpath.endswith('.ps'):
            tmppath = gmt.tempfilename() + '.ps'
        else:
            tmppath = gmt.tempfilename() + '.pdf'

        gmt.save(tmppath)

        if any(outpath.endswith(x) for x in ('.eps', '.ps', '.pdf')):
            shutil.copy(tmppath, outpath)
        else:
            convert_graph(tmppath,
                          outpath,
                          resolution=resolution,
                          oversample=oversample,
                          size=size,
                          width=width,
                          height=height)

    @property
    def scaler(self):
        if self._scaler is None:
            self._setup_geometry()

        return self._scaler

    @property
    def wesn(self):
        if self._wesn is None:
            self._setup_geometry()

        return self._wesn

    @property
    def widget(self):
        if self._widget is None:
            self._setup()

        return self._widget

    @property
    def layout(self):
        if self._layout is None:
            self._setup()

        return self._layout

    @property
    def jxyr(self):
        if self._jxyr is None:
            self._setup()

        return self._jxyr

    @property
    def pxyr(self):
        if self._pxyr is None:
            self._setup()

        return self._pxyr

    @property
    def gmt(self):
        if self._gmt is None:
            self._setup()

        if self._have_topo_ocean is None:
            self._draw_background()

        return self._gmt

    def _setup(self):
        if not self._widget:
            self._setup_geometry()

        self._setup_lod()
        self._setup_gmt()

    def _setup_geometry(self):
        wpage, hpage = self.width, self.height
        ml, mr, mt, mb = self._expand_margins()
        wpage -= ml + mr
        hpage -= mt + mb

        wreg = self.radius * 2.0
        hreg = self.radius * 2.0
        if wpage >= hpage:
            wreg *= wpage / hpage
        else:
            hreg *= hpage / wpage

        self._corners = corners(self.lon, self.lat, wreg, hreg)
        west, east, south, north = extent(self.lon, self.lat, wreg, hreg, 10)

        x, y, z = ((west, east), (south, north), (-6000., 4500.))

        xax = gmtpy.Ax(mode='min-max', approx_ticks=4.)
        yax = gmtpy.Ax(mode='min-max', approx_ticks=4.)
        zax = gmtpy.Ax(mode='min-max',
                       inc=1000.,
                       label='Height',
                       scaled_unit='km',
                       scaled_unit_factor=0.001)

        scaler = gmtpy.ScaleGuru(data_tuples=[(x, y, z)], axes=(xax, yax, zax))

        par = scaler.get_params()

        west = par['xmin']
        east = par['xmax']
        south = par['ymin']
        north = par['ymax']

        self._wesn = west, east, south, north
        self._scaler = scaler

    def _setup_lod(self):
        w, e, s, n = self._wesn
        if self.radius > 1500. * km:
            coastline_resolution = 'i'
            rivers = False
        else:
            coastline_resolution = 'f'
            rivers = True

        self._minarea = (self.skip_feature_factor * self.radius / km)**2

        self._coastline_resolution = coastline_resolution
        self._rivers = rivers

        self._prep_topo_have = {}
        self._dems = {}

        cm2inch = gmtpy.cm / gmtpy.inch

        dmin = 2.0 * self.radius * m2d / (self.topo_resolution_max *
                                          (self.height * cm2inch))
        dmax = 2.0 * self.radius * m2d / (self.topo_resolution_min *
                                          (self.height * cm2inch))

        for k in ['ocean', 'land']:
            self._dems[k] = topo.select_dem_names(k, dmin, dmax, self._wesn)
            if self._dems[k]:
                logger.debug('using topography dataset %s for %s' %
                             (','.join(self._dems[k]), k))

    def _expand_margins(self):
        if len(self.margins) == 0 or len(self.margins) > 4:
            ml = mr = mt = mb = 2.0
        elif len(self.margins) == 1:
            ml = mr = mt = mb = self.margins[0]
        elif len(self.margins) == 2:
            ml = mr = self.margins[0]
            mt = mb = self.margins[1]
        elif len(self.margins) == 4:
            ml, mr, mt, mb = self.margins

        return ml, mr, mt, mb

    def _setup_gmt(self):
        w, h = self.width, self.height
        scaler = self._scaler

        gmtconf = dict(TICK_PEN='1.25p',
                       TICK_LENGTH='0.2c',
                       ANNOT_FONT_PRIMARY='1',
                       ANNOT_FONT_SIZE_PRIMARY='12p',
                       LABEL_FONT='1',
                       LABEL_FONT_SIZE='12p',
                       CHAR_ENCODING='ISOLatin1+',
                       BASEMAP_TYPE='fancy',
                       PLOT_DEGREE_FORMAT='D',
                       PAPER_MEDIA='Custom_%ix%i' %
                       (w * gmtpy.cm, h * gmtpy.cm),
                       GRID_PEN_PRIMARY='thinnest/0/50/0',
                       DOTS_PR_INCH='1200',
                       OBLIQUE_ANNOTATION='6')

        gmtconf.update(
            (k.upper(), v) for (k, v) in self.gmt_config.iteritems())

        gmt = gmtpy.GMT(config=gmtconf)

        layout = gmt.default_layout()

        layout.set_fixed_margins(*[x * cm for x in self._expand_margins()])

        widget = layout.get_widget()
        # widget['J'] = ('-JT%g/%g' % (self.lon, self.lat)) + '/%(width)gp'
        # widget['J'] = ('-JA%g/%g' % (self.lon, self.lat)) + '/%(width)gp'
        widget['P'] = widget['J']
        widget['J'] = ('-JA%g/%g' % (self.lon, self.lat)) + '/%(width_m)gm'
        # widget['J'] = ('-JE%g/%g' % (self.lon, self.lat)) + '/%(width)gp'
        # scaler['R'] = '-R%(xmin)g/%(xmax)g/%(ymin)g/%(ymax)g'
        scaler['R'] = '-R%g/%g/%g/%gr' % self._corners

        aspect = gmtpy.aspect_for_projection(*(widget.J() + scaler.R()))
        widget.set_aspect(aspect)

        self._gmt = gmt
        self._layout = layout
        self._widget = widget
        self._jxyr = self._widget.JXY() + self._scaler.R()
        self._pxyr = self._widget.PXY() + [
            '-R%g/%g/%g/%g' % (0, widget.width(), 0, widget.height())
        ]
        self._have_drawn_axes = False
        self._have_drawn_labels = False

    def _draw_background(self):
        self._have_topo_land = False
        self._have_topo_ocean = False
        if self.show_topo:
            self._have_topo = self._draw_topo()

        self._draw_basefeatures()

    def _get_topo_tile(self, k):
        t = None
        demname = None
        for dem in self._dems[k]:
            t = topo.get(dem, self._wesn)
            demname = dem
            if t is not None:
                break

        if not t:
            raise NoTopo()

        return t, demname

    def _prep_topo(self, k):
        gmt = self._gmt
        t, demname = self._get_topo_tile(k)

        if demname not in self._prep_topo_have:

            grdfile = gmt.tempfilename()
            gmtpy.savegrd(t.x(),
                          t.y(),
                          t.data,
                          filename=grdfile,
                          naming='lonlat')

            if self.illuminate:
                if k == 'ocean':
                    factor = self.illuminate_factor_ocean
                else:
                    factor = self.illuminate_factor_land

                ilumfn = gmt.tempfilename()
                gmt.grdgradient(grdfile,
                                N='e%g' % factor,
                                A=-45,
                                G=ilumfn,
                                out_discard=True)

                ilumargs = ['-I%s' % ilumfn]
            else:
                ilumargs = []

            if self.replace_topo_color_only:
                t2 = self.replace_topo_color_only
                grdfile2 = gmt.tempfilename()

                gmtpy.savegrd(t2.x(),
                              t2.y(),
                              t2.data,
                              filename=grdfile2,
                              naming='lonlat')

                gmt.grdsample(grdfile2,
                              G=grdfile,
                              Q='l',
                              I='%g/%g' % (t.dx, t.dy),
                              R=grdfile,
                              out_discard=True)

                gmt.grdmath(grdfile,
                            '0.0',
                            'AND',
                            '=',
                            grdfile2,
                            out_discard=True)

                grdfile = grdfile2

            self._prep_topo_have[demname] = grdfile, ilumargs

        return self._prep_topo_have[demname]

    def _draw_topo(self):
        widget = self._widget
        scaler = self._scaler
        gmt = self._gmt
        cres = self._coastline_resolution
        minarea = self._minarea

        JXY = widget.JXY()
        R = scaler.R()

        try:
            grdfile, ilumargs = self._prep_topo('ocean')
            gmt.pscoast(D=cres, S='c', A=minarea, *(JXY + R))
            gmt.grdimage(grdfile,
                         C=topo.cpt(self.topo_cpt_wet),
                         *(ilumargs + JXY + R))
            gmt.pscoast(Q=True, *(JXY + R))
            self._have_topo_ocean = True
        except NoTopo:
            self._have_topo_ocean = False

        try:
            grdfile, ilumargs = self._prep_topo('land')
            gmt.pscoast(D=cres, G='c', A=minarea, *(JXY + R))
            gmt.grdimage(grdfile,
                         C=topo.cpt(self.topo_cpt_dry),
                         *(ilumargs + JXY + R))
            gmt.pscoast(Q=True, *(JXY + R))
            self._have_topo_land = True
        except NoTopo:
            self._have_topo_land = False

    def _draw_topo_scale(self, label='Elevation [km]'):
        dry = read_cpt(topo.cpt(self.topo_cpt_dry))
        wet = read_cpt(topo.cpt(self.topo_cpt_wet))
        combi = cpt_merge_wet_dry(wet, dry)
        for level in combi.levels:
            level.vmin /= km
            level.vmax /= km

        topo_cpt = self.gmt.tempfilename()
        write_cpt(combi, topo_cpt)

        (w, h), (xo, yo) = self.widget.get_size()
        self.gmt.psscale(
            D='%gp/%gp/%gp/%gph' %
            (xo + 0.5 * w, yo - 2.0 * gmtpy.cm, w, 0.5 * gmtpy.cm),
            C=topo_cpt,
            B='1:%s:' % label)

    def _draw_basefeatures(self):
        gmt = self._gmt
        cres = self._coastline_resolution
        rivers = self._rivers
        minarea = self._minarea

        color_wet = self.color_wet
        color_dry = self.color_dry

        if self.show_rivers and rivers:
            rivers = ['-Ir/0.25p,%s' % gmtpy.color(self.color_wet)]
        else:
            rivers = []

        fill = {}
        if not self._have_topo_land:
            fill['G'] = color_dry

        if not self._have_topo_ocean:
            fill['S'] = color_wet

        gmt.pscoast(D=cres,
                    W='thinnest,%s' %
                    gmtpy.color(darken(gmtpy.color_tup(color_dry))),
                    A=minarea,
                    *(rivers + self._jxyr),
                    **fill)

    def _draw_axes(self):
        gmt = self._gmt
        scaler = self._scaler
        widget = self._widget

        if self.axes_layout is None:
            if self.lat > 0.0:
                axes_layout = 'WSen'
            else:
                axes_layout = 'WseN'
        else:
            axes_layout = self.axes_layout

        scale_km = gmtpy.nice_value(self.radius / 5.) / 1000.

        if self.show_center_mark:
            gmt.psxy(in_rows=[[self.lon, self.lat]],
                     S='c20p',
                     W='2p,black',
                     *self._jxyr)

        if self.show_grid:
            btmpl = ('%(xinc)gg%(xinc)g:%(xlabel)s:/'
                     '%(yinc)gg%(yinc)g:%(ylabel)s:')
        else:
            btmpl = '%(xinc)g:%(xlabel)s:/%(yinc)g:%(ylabel)s:'

        gmt.psbasemap(B=(btmpl % scaler.get_params()) + axes_layout,
                      L=('x%gp/%gp/%g/%g/%gk' %
                         (6. / 7 * widget.width(), widget.height() / 7.,
                          self.lon, self.lat, scale_km)),
                      *self._jxyr)

        if self.comment:
            fontsize = self.gmt.to_points(
                self.gmt.gmt_config['LABEL_FONT_SIZE'])

            _, east, south, _ = self._wesn
            gmt.pstext(in_rows=[[1, 0, fontsize, 0, 0, 'BR', self.comment]],
                       N=True,
                       R=(0, 1, 0, 1),
                       D='%gp/%gp' % (-fontsize * 0.2, fontsize * 0.3),
                       *widget.PXY())

    def draw_axes(self):
        if not self._have_drawn_axes:
            self._draw_axes()
            self._have_drawn_axes = True

    def _have_coastlines(self):
        gmt = self._gmt
        cres = self._coastline_resolution
        minarea = self._minarea

        checkfile = gmt.tempfilename()

        gmt.pscoast(M=True,
                    D=cres,
                    W='thinnest/black',
                    A=minarea,
                    out_filename=checkfile,
                    *self._jxyr)

        with open(checkfile, 'r') as f:
            for line in f:
                ls = line.strip()
                if ls.startswith('#') or ls.startswith('>') or ls == '':
                    continue
                plon, plat = [float(x) for x in ls.split()]
                if point_in_region((plon, plat), self._wesn):
                    return True

        return False

    def project(self, lats, lons):
        onepoint = False
        if isinstance(lats, float) and isinstance(lons, float):
            lats = [lats]
            lons = [lons]
            onepoint = True

        j, _, _, r = self.jxyr
        (xo, yo) = self.widget.get_size()[1]
        f = StringIO()
        self.gmt.mapproject(j, r, in_columns=(lons, lats), out_stream=f, D='p')
        f.seek(0)
        data = num.loadtxt(f, ndmin=2)
        xs, ys = data.T
        if onepoint:
            xs = xs[0]
            ys = ys[0]
        return xs, ys

    def _draw_labels(self):
        if self._labels:
            fontsize = self.gmt.to_points(
                self.gmt.gmt_config['LABEL_FONT_SIZE'])

            n = len(self._labels)

            lons, lats, texts, sx, sy, styles = zip(*self._labels)

            sx = num.array(sx, dtype=num.float)
            sy = num.array(sy, dtype=num.float)

            j, _, _, r = self.jxyr
            f = StringIO()
            self.gmt.mapproject(j,
                                r,
                                in_columns=(lons, lats),
                                out_stream=f,
                                D='p')
            f.seek(0)
            data = num.loadtxt(f, ndmin=2)
            xs, ys = data.T
            dxs = num.zeros(n)
            dys = num.zeros(n)

            g = gmtpy.GMT()
            g.psbasemap('-G0', finish=True, *(j, r))
            l, b, r, t = g.bbox()
            h = (t - b)
            w = (r - l)

            for i in xrange(n):
                g = gmtpy.GMT()
                g.pstext(in_rows=[[0, 0, fontsize, 0, 1, 'BL', texts[i]]],
                         finish=True,
                         R=(0, 1, 0, 1),
                         J='x10p',
                         N=True,
                         **styles[i])

                fn = g.tempfilename()
                g.save(fn)

                (_, stderr) = Popen([
                    'gs', '-q', '-dNOPAUSE', '-dBATCH', '-r720',
                    '-sDEVICE=bbox', fn
                ],
                                    stderr=PIPE).communicate()

                dx, dy = None, None
                for line in stderr.splitlines():
                    if line.startswith('%%HiResBoundingBox:'):
                        l, b, r, t = [float(x) for x in line.split()[-4:]]
                        dx, dy = r - l, t - b

                dxs[i] = dx
                dys[i] = dy

            la = num.logical_and
            anchors_ok = (
                la(xs + sx + dxs < w, ys + sy + dys < h),
                la(xs - sx - dxs > 0., ys - sy - dys > 0.),
                la(xs + sx + dxs < w, ys - sy - dys > 0.),
                la(xs - sx - dxs > 0., ys + sy + dys < h),
            )

            arects = [(xs, ys, xs + sx + dxs, ys + sy + dys),
                      (xs - sx - dxs, ys - sy - dys, xs, ys),
                      (xs, ys - sy - dys, xs + sx + dxs, ys),
                      (xs - sx - dxs, ys, xs, ys + sy + dys)]

            def no_points_in_rect(xs, ys, xmin, ymin, xmax, ymax):
                xx = not num.any(
                    la(la(xmin < xs, xs < xmax), la(ymin < ys, ys < ymax)))
                return xx

            for i in xrange(n):
                for ianch in xrange(4):
                    anchors_ok[ianch][i] &= no_points_in_rect(
                        xs, ys, *[xxx[i] for xxx in arects[ianch]])

            anchor_choices = []
            anchor_take = []
            for i in xrange(n):
                choices = [
                    ianch for ianch in xrange(4) if anchors_ok[ianch][i]
                ]
                anchor_choices.append(choices)
                if choices:
                    anchor_take.append(choices[0])
                else:
                    anchor_take.append(None)

            def roverlaps(a, b):
                return (a[0] < b[2] and b[0] < a[2] and a[1] < b[3]
                        and b[1] < a[3])

            def cost(anchor_take):
                noverlaps = 0
                for i in xrange(n):
                    for j in xrange(n):
                        if i != j:
                            i_take = anchor_take[i]
                            j_take = anchor_take[j]
                            if i_take is None or j_take is None:
                                continue
                            r_i = [xxx[i] for xxx in arects[i_take]]
                            r_j = [xxx[j] for xxx in arects[j_take]]
                            if roverlaps(r_i, r_j):
                                noverlaps += 1

                return noverlaps

            cur_cost = cost(anchor_take)
            imax = 30
            while cur_cost != 0 and imax > 0:
                for i in xrange(n):
                    for t in anchor_choices[i]:
                        anchor_take_new = list(anchor_take)
                        anchor_take_new[i] = t
                        new_cost = cost(anchor_take_new)
                        if new_cost < cur_cost:
                            anchor_take = anchor_take_new
                            cur_cost = new_cost

                imax -= 1

            while cur_cost != 0:
                for i in xrange(n):
                    anchor_take_new = list(anchor_take)
                    anchor_take_new[i] = None
                    new_cost = cost(anchor_take_new)
                    if new_cost < cur_cost:
                        anchor_take = anchor_take_new
                        cur_cost = new_cost
                        break

            anchor_strs = ['BL', 'TR', 'TL', 'BR']

            for i in xrange(n):
                ianchor = anchor_take[i]
                if ianchor is not None:
                    anchor = anchor_strs[ianchor]
                    yoff = [-sy[i], sy[i]][anchor[0] == 'B']
                    xoff = [-sx[i], sx[i]][anchor[1] == 'L']
                    row = (lons[i], lats[i], fontsize, 0, 1, anchor, texts[i])
                    self.gmt.pstext(in_rows=[row],
                                    D='%gp/%gp' % (xoff, yoff),
                                    *self.jxyr,
                                    **styles[i])

    def draw_labels(self):
        self.gmt
        if not self._have_drawn_labels:
            self._draw_labels()
            self._have_drawn_labels = True

    def add_label(self, lat, lon, text, offset_x=5., offset_y=5., style={}):
        self._labels.append((lon, lat, text, offset_x, offset_y, style))

    def cities_in_region(self):
        from pyrocko import geonames
        cities = geonames.get_cities_region(region=self.wesn, minpop=0)
        cities.extend(self.custom_cities)
        cities.sort(key=lambda x: x.population)
        return cities

    def draw_cities(
        self,
        exact=None,
        include=[],
        exclude=['City of London'],  # duplicate entry in geonames
        nmax_soft=10,
        psxy_style=dict(S='s5p', G='black')):

        cities = self.cities_in_region()

        if exact is not None:
            cities = [c for c in cities if c.name in exact]
            minpop = None
        else:
            cities = [c for c in cities if c.name not in exclude]
            minpop = 10**3
            for minpop_new in [1e3, 3e3, 1e4, 3e4, 1e5, 3e5, 1e6, 3e6, 1e7]:
                cities_new = [c for c in cities if c.population > minpop_new]

                if len(cities_new) == 0 or (len(cities_new) < 3
                                            and len(cities) < nmax_soft * 2):
                    break

                cities = cities_new
                minpop = minpop_new
                if len(cities) <= nmax_soft:
                    break

        if cities:
            lats = [c.lat for c in cities]
            lons = [c.lon for c in cities]

            self.gmt.psxy(in_columns=(lons, lats), *self.jxyr, **psxy_style)

            for c in cities:
                try:
                    text = c.name.encode('iso-8859-1')
                except UnicodeEncodeError:
                    text = c.asciiname

                self.add_label(c.lat, c.lon, text)

        self._cities_minpop = minpop
コード例 #25
0
ファイル: base.py プロジェクト: braunfuss/silvertine
class ReportInfo(Object):
    title = Unicode.T(optional=True)
    description = Unicode.T(optional=True)
    have_archive = Bool.T(optional=True)
コード例 #26
0
ファイル: model.py プロジェクト: braunfuss/silvertine
class Model(Object):
    '''Defines your neural network and the basic training strategy.'''

    name = String.T(default='unnamed',
        help='Used to identify the model and runs in summy and checkpoint \
            directory')

    config = SilvertineConfig.T(help='')
    learning_rate = Float.T(default=1e-3)
    dropout_rate = Float.T(default=0.01)
    batch_size = Int.T(default=10)
    n_epochs = Int.T(default=1)
    max_steps = Int.T(default=5000)
    outdir = String.T(default=tempfile.mkdtemp(prefix='Silvertine-'))
    summary_outdir = String.T(default='summary')
    summary_nth_step = Int.T(default=1)

    shuffle_size = Int.T(
        optional=True, help='if set, shuffle examples at given buffer size.')

    tf.logging.set_verbosity(tf.logging.INFO)
    force_dropout = Bool.T(optional=True)
    layers = List.T(Layer.T(), help='A list of `Layer` instances.')

    def __init__(self, tf_config=None, **kwargs):
        ''' '''
        super().__init__(**kwargs)

        if not tf_config:
            tf_config = tf.ConfigProto()
            tf_config.gpu_options.allow_growth = True

        self.sess = tf.Session(config=tf_config)
        self.debug = logger.getEffectiveLevel() == logging.DEBUG
        self.est = None
        self.prefix = None
        self.tinc_detect = 1.

    def set_tfconfig(self, tf_config):
        self.sess.close()
        self.sess = tf.Session(config=tf_config)

    def enable_debugger(self):
        '''wrap session to enable breaking into debugger.'''
        from tensorflow.python import debug as tf_debug

        # Attach debugger
        self.sess = tf_debug.LocalCLIDebugWrapperSession(self.sess)

        # Attach Tensorboard debugger
        # self.sess = tf_debug.TensorBoardDebugWrapperSession(
        #         self.sess, "localhost:8080")

    def extend_path(self, p):
        '''Append subdirectory to path `p` named by the model.'''
        if self.prefix:
            return os.path.join(self.prefix, p, self.name)
        return os.path.join(p, self.name)

    def get_summary_outdir(self):
        '''Return the directory where to store the summary.'''
        d = self.extend_path(self.summary_outdir)
        ensure_dir(d)
        return d

    def get_outdir(self):
        '''Return the directory where to store the model.'''
        return self.extend_path(self.outdir)

    def get_plot_path(self):
        '''Return the directory where to store figures.'''
        d = os.path.join(self.get_summary_outdir(), 'plots')
        ensure_dir(d)
        return d

    def clear(self):
        '''Delete summary and model directories.'''
        delete_if_exists(self.get_summary_outdir())
        self.clear_model()

    def denormalize_location(self, items):
        '''Convert normalized carthesian location to true location.'''
        return self.config.denormalize_label(items)

    def clear_model(self):
        '''model directories.'''
        delete_if_exists(self.get_outdir())

    def generate_eval_dataset(self):
        '''Generator of evaluation dataset.'''
        return self.config.evaluation_data_generator.get_dataset().batch(
                self.batch_size)

    def generate_eval_dataset_3(self):
        '''Generator of evaluation dataset.'''
        return self.config.evaluation_data_generator.get_dataset().batch(
                self.batch_size).repeat(3)

    def generate_predict_dataset(self):
        '''Generator of prediction dataset.'''
        d = self.config.prediction_data_generator
        if not d:
            raise Exception('\nNo prediction data generator defined in config!')
        return d.get_dataset().batch(self.batch_size)

    def generate_dataset(self):
        '''Generator of training dataset.'''
        dataset = self.config.data_generator.get_dataset()
        if self.shuffle_size is not None:
            dataset = dataset.shuffle(buffer_size=self.shuffle_size)
        return dataset.repeat(count=self.n_epochs).batch(self.batch_size)

    def generate_detect_dataset(self):
        '''Generator of prediction dataset.'''
        d = self.config.prediction_data_generator
        if not d:
            raise Exception('\nNo prediction data generator defined in config!')
        return d.get_chunked_dataset(tinc=self.tinc_detect).prefetch(100)

    def model(self, features, labels, mode):
        '''Setup the model, summaries and run training or evaluation.'''
        training = bool(mode == tf.estimator.ModeKeys.TRAIN)

        if self.debug:
            view = features[:3]
            view = tf.expand_dims(view, -1)
            tf.summary.image('input', view)

        with tf.name_scope('input'):
            input = tf.reshape(
                features, [-1, *self.config.data_generator.tensor_shape,  1])

        input = tf.layers.batch_normalization(input, training=training)
        level = tf.zeros([1], name='level')

        for layer in self.layers:
            logger.debug('chain in layer: %s' % layer)
            input, level = layer.chain(input=input, level=level,
                    training=training or self.force_dropout,
                    dropout_rate=self.dropout_rate)

        # Final layer
        predictions = tf.layers.dense(input, self.config.n_classes,
                name='output', activation=None)

        if mode == tf.estimator.ModeKeys.PREDICT:
            return tf.estimator.EstimatorSpec(mode,
                    predictions = {
                        'predictions': self.denormalize_location(predictions),
                        'level': level})

        # do not denormalize labels and predictions for loss
        loss = tf.losses.mean_squared_error(labels, predictions)

        # transform to carthesian coordiantes
        labels = self.denormalize_location(labels)
        predictions = self.denormalize_location(predictions)

        predictions = tf.transpose(predictions)
        labels = tf.transpose(labels)
        errors = predictions - labels
        abs_errors = tf.abs(errors)
        variable_summaries(errors[0], 'error_abs_x')
        variable_summaries(errors[1], 'error_abs_y')
        variable_summaries(errors[2], 'error_abs_z')

        loss_carthesian = tf.sqrt(tf.reduce_sum(errors ** 2, axis=0,
            keepdims=False))

        variable_summaries(loss_carthesian, 'training_loss')
        loss_ = tf.reduce_mean(loss_carthesian)
        tf.summary.scalar('mean_loss_cart', loss_)
        tf.summary.scalar('loss_normalized', loss)

        if mode == tf.estimator.ModeKeys.TRAIN:
            optimizer = tf.train.AdamOptimizer(self.learning_rate)
            update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
            with tf.control_dependencies(update_ops):
                train_op = optimizer.minimize(
                    loss=loss, global_step=tf.train.get_global_step())

            logging_hook = tf.train.LoggingTensorHook(
                    {"loss": loss, "step": tf.train.get_global_step()},
                    every_n_iter=10)

            return tf.estimator.EstimatorSpec(
                    mode=mode,
                    loss=loss,
                    train_op=train_op,
                    evaluation_hooks=[self.get_summary_hook('eval'),],
                    training_hooks=[
                            self.get_summary_hook('train'), logging_hook])

        elif mode == tf.estimator.ModeKeys.EVAL:
            metrics = {
                    'rmse_eval': tf.metrics.root_mean_squared_error(
                labels=labels, predictions=predictions, name='rmse_eval'),
                    'mse_eval': tf.metrics.mean_squared_error(
                labels=labels, predictions=predictions, name='mse_eval'),
                    'mae_eval': tf.metrics.mean_absolute_error(
                labels=labels, predictions=predictions, name='mae_eval')}

            with tf.name_scope('eval'):
                for k, v in metrics.items():
                    tf.summary.scalar(k, v[1])
            return tf.estimator.EstimatorSpec(
                    mode=mode, loss=loss, eval_metric_ops=metrics,
                    evaluation_hooks=[self.get_summary_hook('eval'),])

    def get_summary_hook(self, subdir=''):
        '''Return a summary hook storing summaries at *subdir*.'''
        return tf.train.SummarySaverHook(
            self.summary_nth_step,
            output_dir=pjoin(self.get_summary_outdir(), subdir),
            scaffold=tf.train.Scaffold(summary_op=tf.summary.merge_all()))

    def train_and_evaluate(self):
        '''Execute training and evaluation and visualize kernels as well as
        activation maps at the end of all epochs.'''
        self.save_model_in_summary()
        with self.sess as default:
            self.est = tf.estimator.Estimator(
                model_fn=self.model, model_dir=self.get_outdir())

            train_spec = tf.estimator.TrainSpec(
                    input_fn=self.generate_dataset,
                    max_steps=self.max_steps)

            eval_spec = tf.estimator.EvalSpec(
                    input_fn=self.generate_eval_dataset,
                    steps=None)

            result = tf.estimator.train_and_evaluate(self.est, train_spec, eval_spec)

        self.save_kernels()
        self.save_activation_maps()

        return result

    def predict(self):
        '''Predict locations prediction data generator and store results
        as a list of carthesian coordinates.'''
        import time
        import csv
        with self.sess as default:
            self.est = tf.estimator.Estimator(
                model_fn=self.model, model_dir=self.get_outdir())
            predictions = []
            for i, p in enumerate(self.est.predict(
                    input_fn=self.generate_predict_dataset,
                    yield_single_examples=False)):

                if not i:
                    tstart = time.time()

                predictions.extend(p['predictions'])

        fn_out = 'predictions.csv'
        with open(fn_out, 'w') as f:
            w = csv.writer(f, delimiter=' ')
            for p in predictions:
                w.writerow(p)

        logger.info('This took %1.1f seconds ' % (time.time()-tstart))
        logger.info('Saved locations in %s' % fn_out)

    def detect(self, tinc=None, detector_threshold=1.8):
        '''Detect events

        Summarizes the energy of layers in your network that have their
        *is_detector* flag set to *True*.

        :param tinc: time increment to step through the dataset.
        :param detector_threshold: triggers a detection when summed energy
            exceeds this value.
        '''
        tpeaksearch = 5.
        self.tinc_detect = tinc or 1.0
        fn_detector_trace = 'detector.mseed'
        fn_detections = 'detections.pf'

        with self.sess as default:
            self.est = tf.estimator.Estimator(
                model_fn=self.model, model_dir=self.get_outdir())
            detector_level = []

            for ip, p in enumerate(self.est.predict(
                    input_fn=self.generate_detect_dataset,
                    yield_single_examples=True)):
                detector_level.append(p['level'])
            print(self.config.prediction_data_generator.tstart_data, self.tinc_detect)
            tr = trace.Trace(
                    tmin=self.config.prediction_data_generator.tstart_data,
                    ydata=num.array(detector_level),
                    deltat=self.tinc_detect)

            tpeaks, apeaks = tr.peaks(detector_threshold, tpeaksearch)
            logger.info('Fount %i detections' % len(tpeaks))

            markers = []
            for (tpeak, apeak) in zip(tpeaks, apeaks):
                markers.append(
                        EventMarker(pmodel.Event(time=tpeak,
                    name=str(apeak))))

            logger.info('Saving detections: %s' % fn_detections)
            Marker.save_markers(markers, fn_detections)

            logger.info('Saving detector level: %s' % fn_detector_trace)
            io.save([tr], fn_detector_trace)

    def evaluate_errors(self, n_predict=100, force_dropout=0.333):
        '''Repeatedly run the prediction for *n_predict* times where the first
        run is without and the subsequent are with enforced dropout rate
        *force_dropout*.

        This is allows to evaluate location accuracy without a given
        reference catatog of known event locations. It is basically a jacknife
        applied to the neural network layers.
        '''
        logger.debug('evaluation...')
        self.dropout_rate = force_dropout
        with self.sess as default:
            self.est = tf.estimator.Estimator(
                model_fn=self.model, model_dir=self.get_outdir())
            labels = [l for _, l in self.config.evaluation_data_generator.generate()]
            labels = self.denormalize_location(num.array(labels))

            all_predictions = []

            for n in range(n_predict):
                predictions = []
                for p in self.est.predict(
                        input_fn=self.generate_eval_dataset,
                        yield_single_examples=False):

                    predictions.append(p['predictions'])
                # predictions = self.denormalize_location(num.array(predictions))
                all_predictions.append(predictions)

                # activate dropout after first iteration. hence, first are
                # 'correct locations'
                self.force_dropout = True

            all_predictions = num.array(all_predictions)

            save_name = pjoin(self.get_plot_path(), 'errors')

            plot.evaluate_errors(
                    all_predictions, labels, name=save_name)

    def evaluate(self, annotate=False):
        ''' Run the evaluation and visualize the results.

        :param annotate: label all events
        '''
        logger.debug('evaluation...')

        with self.sess as default:
            self.est = tf.estimator.Estimator(
                model_fn=self.model, model_dir=self.get_outdir())
            labels = [l for _, l in self.config.evaluation_data_generator.generate()]
            predictions = []
            for p in self.est.predict(
                    input_fn=self.generate_eval_dataset,
                    yield_single_examples=False):

                predictions.extend(p['predictions'])

        save_name = pjoin(self.get_plot_path(), 'mislocation')
        predictions = num.array(predictions)
        labels = self.denormalize_location(num.array(labels))

        text_labels = None
        if annotate:
            text_labels = self.config.evaluation_data_generator.text_labels

        plot.plot_predictions_and_labels(
                predictions, labels, name=save_name, text_labels=text_labels)

        save_name = pjoin(self.get_plot_path(), 'mislocation_hists')
        plot.mislocation_hist(predictions, labels, name=save_name)

        save_name = pjoin(self.get_plot_path(), 'mislocation_snrs')
        snrs = self.config.evaluation_data_generator.snrs(split_factor=0.8)
        plot.mislocation_vs_snr(snrs, predictions, labels, name=save_name)

        save_name = pjoin(self.get_plot_path(), 'mislocation_vs_gaps')
        gaps = self.config.evaluation_data_generator.gaps()

        plot.mislocation_vs_gaps(predictions, labels,
                gaps,
                name=save_name)

    def evaluate_station_dropout(self, start=0., stop=0.8, inc=0.1):
        '''
        Predict for a range of station dropouts and visualize the results.
        '''
        with self.sess as default:
            self.est = tf.estimator.Estimator(
                model_fn=self.model, model_dir=self.get_outdir())
            labels = [l for _, l in self.config.evaluation_data_generator.generate()]
            sdropouts = num.linspace(start, stop, inc)
            results = {}
            for sdropout in sdropouts:
                predictions = []
                for p in self.est.predict(
                        input_fn=self.generate_eval_dataset,
                        yield_single_examples=False):

                    predictions.extend(p['predictions'])
                results[sdropout] = predictions

        plot.mislocation_vs_gaps_many(results, labels,
                self.config.evaluation_data_generator.gaps(),
                name=save_name)

    def train_multi_gpu(self, params=None):
        ''' Use multiple GPUs for training.  Buggy...'''
        params = params or {}
        self.training_hooks = []
        # saver_hook = tf.train.CheckpointSaverHook()
        # summary_hook = tf.train.SummarySaverHook()
        with tf.train.MonitoredSession(
                # session_creator=tf.train.ChiefSessionCreator(),
                # hooks=[summary_hook]) as sess:
                # hooks=[saver_hook, summary_hook]) as sess:
                ) as sess:
            distribution = tf.compat.v1.layers.distribute.MirroredStrategy(num_gpus=2)
            run_config = tf.estimator.RunConfig(train_distribute=distribution)
            est = tf.estimator.Estimator(
                model_fn=self.model,
                model_dir=self.outdir,
                # params=params,
                config=run_config)

            est.train(input_fn=self.generate_dataset)
            logger.info('====== start evaluation')
            return est.evaluate(input_fn=self.generate_eval_dataset)

    def save_kernels(self, index=0):
        '''save weight kernels of all layers (at index=`index`).'''
        save_path = pjoin(self.get_summary_outdir(), 'kernels')
        ensure_dir(save_path)
        logger.info('Storing weight matrices at %s' % save_path)
        for layer in self.layers:
            layer.visualize_kernel(self.est, save_path=save_path)

    def save_activation_maps(self, index=0):
        '''Visualizes all activation maps at given *index* of all layers.'''
        save_path = pjoin(self.get_summary_outdir(), 'kernels')
        ensure_dir(save_path)
    #    for layer in self.layers:
    #        plot.getActivations(layer, stimuli)

    def save_model_in_summary(self):
        '''Dump neural network configuration to summary directory as YAML.'''
        self.regularize()
        self.dump(filename=pjoin(self.get_summary_outdir(), 'model.config'))
コード例 #27
0
ファイル: automap.py プロジェクト: d-chambers/pyrocko
class Map(Object):
    lat = Float.T(optional=True)
    lon = Float.T(optional=True)
    radius = Float.T(optional=True)
    width = Float.T(default=20.)
    height = Float.T(default=14.)
    margins = List.T(Float.T())
    illuminate = Bool.T(default=True)
    skip_feature_factor = Float.T(default=0.02)
    show_grid = Bool.T(default=False)
    show_topo = Bool.T(default=True)
    show_topo_scale = Bool.T(default=False)
    show_center_mark = Bool.T(default=False)
    show_rivers = Bool.T(default=True)
    show_plates = Bool.T(default=False)
    illuminate_factor_land = Float.T(default=0.5)
    illuminate_factor_ocean = Float.T(default=0.25)
    color_wet = Tuple.T(3, Int.T(), default=(216, 242, 254))
    color_dry = Tuple.T(3, Int.T(), default=(172, 208, 165))
    topo_resolution_min = Float.T(
        default=40.,
        help='minimum resolution of topography [dpi]')
    topo_resolution_max = Float.T(
        default=200.,
        help='maximum resolution of topography [dpi]')
    replace_topo_color_only = FloatTile.T(
        optional=True,
        help='replace topo color while keeping topographic shading')
    topo_cpt_wet = String.T(default='light_sea')
    topo_cpt_dry = String.T(default='light_land')
    axes_layout = String.T(optional=True)
    custom_cities = List.T(City.T())
    gmt_config = Dict.T(String.T(), String.T())
    comment = String.T(optional=True)

    def __init__(self, gmtversion='newest', **kwargs):
        Object.__init__(self, **kwargs)
        self._gmt = None
        self._scaler = None
        self._widget = None
        self._corners = None
        self._wesn = None
        self._minarea = None
        self._coastline_resolution = None
        self._rivers = None
        self._dems = None
        self._have_topo_land = None
        self._have_topo_ocean = None
        self._jxyr = None
        self._prep_topo_have = None
        self._labels = []
        self._area_labels = []
        self._gmtversion = gmtversion

    def save(self, outpath, resolution=75., oversample=2., size=None,
             width=None, height=None):

        '''
        Save the image.

        Save the image to ``outpath``. The format is determined by the filename
        extension. Formats are handled as follows: ``'.eps'`` and ``'.ps'``
        produce EPS and PS, respectively, directly with GMT. If the file name
        ends with ``'.pdf'``, GMT output is fed through ``gmtpy-epstopdf`` to
        create a PDF file. For any other filename extension, output is first
        converted to PDF with ``gmtpy-epstopdf``, then with ``pdftocairo`` to
        PNG with a resolution oversampled by the factor ``oversample`` and
        finally the PNG is downsampled and converted to the target format with
        ``convert``. The resolution of rasterized target image can be
        controlled either by ``resolution`` in DPI or by specifying ``width``
        or ``height`` or ``size``, where the latter fits the image into a
        square with given side length.
        '''

        gmt = self.gmt
        self.draw_labels()
        self.draw_axes()
        if self.show_topo and self.show_topo_scale:
            self._draw_topo_scale()

        gmt.save(outpath, resolution=resolution, oversample=oversample,
                 size=size, width=width, height=height)

    @property
    def scaler(self):
        if self._scaler is None:
            self._setup_geometry()

        return self._scaler

    @property
    def wesn(self):
        if self._wesn is None:
            self._setup_geometry()

        return self._wesn

    @property
    def widget(self):
        if self._widget is None:
            self._setup()

        return self._widget

    @property
    def layout(self):
        if self._layout is None:
            self._setup()

        return self._layout

    @property
    def jxyr(self):
        if self._jxyr is None:
            self._setup()

        return self._jxyr

    @property
    def pxyr(self):
        if self._pxyr is None:
            self._setup()

        return self._pxyr

    @property
    def gmt(self):
        if self._gmt is None:
            self._setup()

        if self._have_topo_ocean is None:
            self._draw_background()

        return self._gmt

    def _setup(self):
        if not self._widget:
            self._setup_geometry()

        self._setup_lod()
        self._setup_gmt()

    def _setup_geometry(self):
        wpage, hpage = self.width, self.height
        ml, mr, mt, mb = self._expand_margins()
        wpage -= ml + mr
        hpage -= mt + mb

        wreg = self.radius * 2.0
        hreg = self.radius * 2.0
        if wpage >= hpage:
            wreg *= wpage/hpage
        else:
            hreg *= hpage/wpage

        self._wreg = wreg
        self._hreg = hreg

        self._corners = corners(self.lon, self.lat, wreg, hreg)
        west, east, south, north = extent(self.lon, self.lat, wreg, hreg, 10)

        x, y, z = ((west, east), (south, north), (-6000., 4500.))

        xax = gmtpy.Ax(mode='min-max', approx_ticks=4.)
        yax = gmtpy.Ax(mode='min-max', approx_ticks=4.)
        zax = gmtpy.Ax(mode='min-max', inc=1000., label='Height',
                       scaled_unit='km', scaled_unit_factor=0.001)

        scaler = gmtpy.ScaleGuru(data_tuples=[(x, y, z)], axes=(xax, yax, zax))

        par = scaler.get_params()

        west = par['xmin']
        east = par['xmax']
        south = par['ymin']
        north = par['ymax']

        self._wesn = west, east, south, north
        self._scaler = scaler

    def _setup_lod(self):
        w, e, s, n = self._wesn
        if self.radius > 1500.*km:
            coastline_resolution = 'i'
            rivers = False
        else:
            coastline_resolution = 'f'
            rivers = True

        self._minarea = (self.skip_feature_factor * self.radius/km)**2

        self._coastline_resolution = coastline_resolution
        self._rivers = rivers

        self._prep_topo_have = {}
        self._dems = {}

        cm2inch = gmtpy.cm/gmtpy.inch

        dmin = 2.0 * self.radius * m2d / (self.topo_resolution_max *
                                          (self.height * cm2inch))
        dmax = 2.0 * self.radius * m2d / (self.topo_resolution_min *
                                          (self.height * cm2inch))

        for k in ['ocean', 'land']:
            self._dems[k] = topo.select_dem_names(k, dmin, dmax, self._wesn)
            if self._dems[k]:
                logger.debug('using topography dataset %s for %s'
                             % (','.join(self._dems[k]), k))

    def _expand_margins(self):
        if len(self.margins) == 0 or len(self.margins) > 4:
            ml = mr = mt = mb = 2.0
        elif len(self.margins) == 1:
            ml = mr = mt = mb = self.margins[0]
        elif len(self.margins) == 2:
            ml = mr = self.margins[0]
            mt = mb = self.margins[1]
        elif len(self.margins) == 4:
            ml, mr, mt, mb = self.margins

        return ml, mr, mt, mb

    def _setup_gmt(self):
        w, h = self.width, self.height
        scaler = self._scaler

        if gmtpy.is_gmt5(self._gmtversion):
            gmtconf = dict(
                MAP_TICK_PEN_PRIMARY='1.25p',
                MAP_TICK_PEN_SECONDARY='1.25p',
                MAP_TICK_LENGTH_PRIMARY='0.2c',
                MAP_TICK_LENGTH_SECONDARY='0.6c',
                FONT_ANNOT_PRIMARY='12p,1,black',
                FONT_LABEL='12p,1,black',
                PS_CHAR_ENCODING='ISOLatin1+',
                MAP_FRAME_TYPE='fancy',
                FORMAT_GEO_MAP='D',
                PS_MEDIA='Custom_%ix%i' % (
                    w*gmtpy.cm,
                    h*gmtpy.cm),
                PS_PAGE_ORIENTATION='portrait',
                MAP_GRID_PEN_PRIMARY='thinnest,0/50/0',
                MAP_ANNOT_OBLIQUE='6')
        else:
            gmtconf = dict(
                TICK_PEN='1.25p',
                TICK_LENGTH='0.2c',
                ANNOT_FONT_PRIMARY='1',
                ANNOT_FONT_SIZE_PRIMARY='12p',
                LABEL_FONT='1',
                LABEL_FONT_SIZE='12p',
                CHAR_ENCODING='ISOLatin1+',
                BASEMAP_TYPE='fancy',
                PLOT_DEGREE_FORMAT='D',
                PAPER_MEDIA='Custom_%ix%i' % (
                    w*gmtpy.cm,
                    h*gmtpy.cm),
                GRID_PEN_PRIMARY='thinnest/0/50/0',
                DOTS_PR_INCH='1200',
                OBLIQUE_ANNOTATION='6')

        gmtconf.update(
            (k.upper(), v) for (k, v) in self.gmt_config.items())

        gmt = gmtpy.GMT(config=gmtconf, version=self._gmtversion)

        layout = gmt.default_layout()

        layout.set_fixed_margins(*[x*cm for x in self._expand_margins()])

        widget = layout.get_widget()
        widget['P'] = widget['J']
        widget['J'] = ('-JA%g/%g' % (self.lon, self.lat)) + '/%(width)gp'
        scaler['R'] = '-R%g/%g/%g/%gr' % self._corners

        # aspect = gmtpy.aspect_for_projection(
        #     gmt.installation['version'], *(widget.J() + scaler.R()))

        aspect = self._map_aspect(jr=widget.J() + scaler.R())
        widget.set_aspect(aspect)

        self._gmt = gmt
        self._layout = layout
        self._widget = widget
        self._jxyr = self._widget.JXY() + self._scaler.R()
        self._pxyr = self._widget.PXY() + [
            '-R%g/%g/%g/%g' % (0, widget.width(), 0, widget.height())]
        self._have_drawn_axes = False
        self._have_drawn_labels = False

    def _draw_background(self):
        self._have_topo_land = False
        self._have_topo_ocean = False
        if self.show_topo:
            self._have_topo = self._draw_topo()

        self._draw_basefeatures()

    def _get_topo_tile(self, k):
        t = None
        demname = None
        for dem in self._dems[k]:
            t = topo.get(dem, self._wesn)
            demname = dem
            if t is not None:
                break

        if not t:
            raise NoTopo()

        return t, demname

    def _prep_topo(self, k):
        gmt = self._gmt
        t, demname = self._get_topo_tile(k)

        if demname not in self._prep_topo_have:

            grdfile = gmt.tempfilename()

            is_flat = num.all(t.data[0] == t.data)

            gmtpy.savegrd(
                t.x(), t.y(), t.data, filename=grdfile, naming='lonlat')

            if self.illuminate and not is_flat:
                if k == 'ocean':
                    factor = self.illuminate_factor_ocean
                else:
                    factor = self.illuminate_factor_land

                ilumfn = gmt.tempfilename()
                gmt.grdgradient(
                    grdfile,
                    N='e%g' % factor,
                    A=-45,
                    G=ilumfn,
                    out_discard=True)

                ilumargs = ['-I%s' % ilumfn]
            else:
                ilumargs = []

            if self.replace_topo_color_only:
                t2 = self.replace_topo_color_only
                grdfile2 = gmt.tempfilename()

                gmtpy.savegrd(
                    t2.x(), t2.y(), t2.data, filename=grdfile2,
                    naming='lonlat')

                if gmt.is_gmt5():
                    gmt.grdsample(
                        grdfile2,
                        G=grdfile,
                        n='l',
                        I='%g/%g' % (t.dx, t.dy),  # noqa
                        R=grdfile,
                        out_discard=True)
                else:
                    gmt.grdsample(
                        grdfile2,
                        G=grdfile,
                        Q='l',
                        I='%g/%g' % (t.dx, t.dy),  # noqa
                        R=grdfile,
                        out_discard=True)

                gmt.grdmath(
                    grdfile, '0.0', 'AND', '=', grdfile2,
                    out_discard=True)

                grdfile = grdfile2

            self._prep_topo_have[demname] = grdfile, ilumargs

        return self._prep_topo_have[demname]

    def _draw_topo(self):
        widget = self._widget
        scaler = self._scaler
        gmt = self._gmt
        cres = self._coastline_resolution
        minarea = self._minarea

        JXY = widget.JXY()
        R = scaler.R()

        try:
            grdfile, ilumargs = self._prep_topo('ocean')
            gmt.pscoast(D=cres, S='c', A=minarea, *(JXY+R))
            gmt.grdimage(grdfile, C=topo.cpt(self.topo_cpt_wet),
                         *(ilumargs+JXY+R))
            gmt.pscoast(Q=True, *(JXY+R))
            self._have_topo_ocean = True
        except NoTopo:
            self._have_topo_ocean = False

        try:
            grdfile, ilumargs = self._prep_topo('land')
            gmt.pscoast(D=cres, G='c', A=minarea, *(JXY+R))
            gmt.grdimage(grdfile, C=topo.cpt(self.topo_cpt_dry),
                         *(ilumargs+JXY+R))
            gmt.pscoast(Q=True, *(JXY+R))
            self._have_topo_land = True
        except NoTopo:
            self._have_topo_land = False

    def _draw_topo_scale(self, label='Elevation [km]'):
        dry = read_cpt(topo.cpt(self.topo_cpt_dry))
        wet = read_cpt(topo.cpt(self.topo_cpt_wet))
        combi = cpt_merge_wet_dry(wet, dry)
        for level in combi.levels:
            level.vmin /= km
            level.vmax /= km

        topo_cpt = self.gmt.tempfilename() + '.cpt'
        write_cpt(combi, topo_cpt)

        (w, h), (xo, yo) = self.widget.get_size()
        self.gmt.psscale(
            D='%gp/%gp/%gp/%gph' % (xo + 0.5*w, yo - 2.0*gmtpy.cm, w,
                                    0.5*gmtpy.cm),
            C=topo_cpt,
            B='1:%s:' % label)

    def _draw_basefeatures(self):
        gmt = self._gmt
        cres = self._coastline_resolution
        rivers = self._rivers
        minarea = self._minarea

        color_wet = self.color_wet
        color_dry = self.color_dry

        if self.show_rivers and rivers:
            rivers = ['-Ir/0.25p,%s' % gmtpy.color(self.color_wet)]
        else:
            rivers = []

        fill = {}
        if not self._have_topo_land:
            fill['G'] = color_dry

        if not self._have_topo_ocean:
            fill['S'] = color_wet

        gmt.pscoast(
            D=cres,
            W='thinnest,%s' % gmtpy.color(darken(gmtpy.color_tup(color_dry))),
            A=minarea,
            *(rivers+self._jxyr), **fill)

        if self.show_plates:
            self.draw_plates()

    def _draw_axes(self):
        gmt = self._gmt
        scaler = self._scaler
        widget = self._widget

        if self.axes_layout is None:
            if self.lat > 0.0:
                axes_layout = 'WSen'
            else:
                axes_layout = 'WseN'
        else:
            axes_layout = self.axes_layout

        scale_km = gmtpy.nice_value(self.radius/5.) / 1000.

        if self.show_center_mark:
            gmt.psxy(
                in_rows=[[self.lon, self.lat]],
                S='c20p', W='2p,black',
                *self._jxyr)

        if self.show_grid:
            btmpl = ('%(xinc)gg%(xinc)g:%(xlabel)s:/'
                     '%(yinc)gg%(yinc)g:%(ylabel)s:')
        else:
            btmpl = '%(xinc)g:%(xlabel)s:/%(yinc)g:%(ylabel)s:'

        gmt.psbasemap(
            B=(btmpl % scaler.get_params())+axes_layout,
            L=('x%gp/%gp/%g/%g/%gk' % (
                6./7*widget.width(),
                widget.height()/7.,
                self.lon,
                self.lat,
                scale_km)),
            *self._jxyr)

        if self.comment:
            font_size = self.gmt.label_font_size()

            _, east, south, _ = self._wesn
            if gmt.is_gmt5():
                row = [
                    1, 0,
                    '%gp,%s,%s' % (font_size, 0, 'black'), 'BR',
                    self.comment]

                farg = ['-F+f+j']
            else:
                row = [1, 0, font_size, 0, 0, 'BR', self.comment]
                farg = []

            gmt.pstext(
                in_rows=[row],
                N=True,
                R=(0, 1, 0, 1),
                D='%gp/%gp' % (-font_size*0.2, font_size*0.3),
                *(widget.PXY() + farg))

    def draw_axes(self):
        if not self._have_drawn_axes:
            self._draw_axes()
            self._have_drawn_axes = True

    def _have_coastlines(self):
        gmt = self._gmt
        cres = self._coastline_resolution
        minarea = self._minarea

        checkfile = gmt.tempfilename()

        gmt.pscoast(
            M=True,
            D=cres,
            W='thinnest,black',
            A=minarea,
            out_filename=checkfile,
            *self._jxyr)

        points = []
        with open(checkfile, 'r') as f:
            for line in f:
                ls = line.strip()
                if ls.startswith('#') or ls.startswith('>') or ls == '':
                    continue
                plon, plat = [float(x) for x in ls.split()]
                points.append((plat, plon))

        points = num.array(points, dtype=num.float)
        return num.any(points_in_region(points, self._wesn))

    def have_coastlines(self):
        self.gmt
        return self._have_coastlines()

    def project(self, lats, lons, jr=None):
        onepoint = False
        if isinstance(lats, float) and isinstance(lons, float):
            lats = [lats]
            lons = [lons]
            onepoint = True

        if jr is not None:
            j, r = jr
            gmt = gmtpy.GMT(version=self._gmtversion)
        else:
            j, _, _, r = self.jxyr
            gmt = self.gmt

        f = BytesIO()
        gmt.mapproject(j, r, in_columns=(lons, lats), out_stream=f, D='p')
        f.seek(0)
        data = num.loadtxt(f, ndmin=2)
        xs, ys = data.T
        if onepoint:
            xs = xs[0]
            ys = ys[0]
        return xs, ys

    def _map_box(self, jr=None):
        ll_lon, ll_lat, ur_lon, ur_lat = self._corners

        xs_corner, ys_corner = self.project(
            (ll_lat, ur_lat), (ll_lon, ur_lon), jr=jr)

        w = xs_corner[1] - xs_corner[0]
        h = ys_corner[1] - ys_corner[0]

        return w, h

    def _map_aspect(self, jr=None):
        w, h = self._map_box(jr=jr)
        return h/w

    def _draw_labels(self):
        points_taken = []
        regions_taken = []

        def no_points_in_rect(xs, ys, xmin, ymin, xmax, ymax):
            xx = not num.any(la(la(xmin < xs, xs < xmax),
                                la(ymin < ys, ys < ymax)))
            return xx

        def roverlaps(a, b):
            return (a[0] < b[2] and b[0] < a[2] and
                    a[1] < b[3] and b[1] < a[3])

        w, h = self._map_box()

        label_font_size = self.gmt.label_font_size()

        if self._labels:

            n = len(self._labels)

            lons, lats, texts, sx, sy, colors, fonts, font_sizes, styles = \
                list(zip(*self._labels))

            font_sizes = [
                (font_size or label_font_size) for font_size in font_sizes]

            sx = num.array(sx, dtype=num.float)
            sy = num.array(sy, dtype=num.float)

            xs, ys = self.project(lats, lons)

            points_taken.append((xs, ys))

            dxs = num.zeros(n)
            dys = num.zeros(n)

            for i in range(n):
                dx, dy = gmtpy.text_box(
                    texts[i],
                    font=fonts[i],
                    font_size=font_sizes[i],
                    **styles[i])

                dxs[i] = dx
                dys[i] = dy

            la = num.logical_and
            anchors_ok = (
                la(xs + sx + dxs < w, ys + sy + dys < h),
                la(xs - sx - dxs > 0., ys - sy - dys > 0.),
                la(xs + sx + dxs < w, ys - sy - dys > 0.),
                la(xs - sx - dxs > 0., ys + sy + dys < h),
            )

            arects = [
                (xs, ys, xs + sx + dxs, ys + sy + dys),
                (xs - sx - dxs, ys - sy - dys, xs, ys),
                (xs, ys - sy - dys, xs + sx + dxs, ys),
                (xs - sx - dxs, ys, xs, ys + sy + dys)]

            for i in range(n):
                for ianch in range(4):
                    anchors_ok[ianch][i] &= no_points_in_rect(
                        xs, ys, *[xxx[i] for xxx in arects[ianch]])

            anchor_choices = []
            anchor_take = []
            for i in range(n):
                choices = [ianch for ianch in range(4)
                           if anchors_ok[ianch][i]]
                anchor_choices.append(choices)
                if choices:
                    anchor_take.append(choices[0])
                else:
                    anchor_take.append(None)

            def cost(anchor_take):
                noverlaps = 0
                for i in range(n):
                    for j in range(n):
                        if i != j:
                            i_take = anchor_take[i]
                            j_take = anchor_take[j]
                            if i_take is None or j_take is None:
                                continue
                            r_i = [xxx[i] for xxx in arects[i_take]]
                            r_j = [xxx[j] for xxx in arects[j_take]]
                            if roverlaps(r_i, r_j):
                                noverlaps += 1

                return noverlaps

            cur_cost = cost(anchor_take)
            imax = 30
            while cur_cost != 0 and imax > 0:
                for i in range(n):
                    for t in anchor_choices[i]:
                        anchor_take_new = list(anchor_take)
                        anchor_take_new[i] = t
                        new_cost = cost(anchor_take_new)
                        if new_cost < cur_cost:
                            anchor_take = anchor_take_new
                            cur_cost = new_cost

                imax -= 1

            while cur_cost != 0:
                for i in range(n):
                    anchor_take_new = list(anchor_take)
                    anchor_take_new[i] = None
                    new_cost = cost(anchor_take_new)
                    if new_cost < cur_cost:
                        anchor_take = anchor_take_new
                        cur_cost = new_cost
                        break

            anchor_strs = ['BL', 'TR', 'TL', 'BR']

            for i in range(n):
                ianchor = anchor_take[i]
                color = colors[i]
                if color is None:
                    color = 'black'

                if ianchor is not None:
                    regions_taken.append([xxx[i] for xxx in arects[ianchor]])

                    anchor = anchor_strs[ianchor]

                    yoff = [-sy[i], sy[i]][anchor[0] == 'B']
                    xoff = [-sx[i], sx[i]][anchor[1] == 'L']
                    if self.gmt.is_gmt5():
                        row = (
                            lons[i], lats[i],
                            '%i,%s,%s' % (font_sizes[i], fonts[i], color),
                            anchor,
                            texts[i])

                        farg = ['-F+f+j']
                    else:
                        row = (
                            lons[i], lats[i],
                            font_sizes[i], 0, fonts[i], anchor,
                            texts[i])
                        farg = ['-G%s' % color]

                    self.gmt.pstext(
                        in_rows=[row],
                        D='%gp/%gp' % (xoff, yoff),
                        *(self.jxyr + farg),
                        **styles[i])

        if self._area_labels:

            for lons, lats, text, color, font, font_size, style in \
                    self._area_labels:

                if font_size is None:
                    font_size = label_font_size

                if color is None:
                    color = 'black'

                if self.gmt.is_gmt5():
                    farg = ['-F+f+j']
                else:
                    farg = ['-G%s' % color]

                xs, ys = self.project(lats, lons)
                dx, dy = gmtpy.text_box(
                    text, font=font, font_size=font_size, **style)

                rects = [xs-0.5*dx, ys-0.5*dy, xs+0.5*dx, ys+0.5*dy]

                locs_ok = num.ones(xs.size, dtype=num.bool)

                for iloc in range(xs.size):
                    rcandi = [xxx[iloc] for xxx in rects]

                    locs_ok[iloc] = True
                    locs_ok[iloc] &= (
                        0 < rcandi[0] and rcandi[2] < w
                        and 0 < rcandi[1] and rcandi[3] < h)

                    overlap = False
                    for r in regions_taken:
                        if roverlaps(r, rcandi):
                            overlap = True
                            break

                    locs_ok[iloc] &= not overlap

                    for xs_taken, ys_taken in points_taken:
                        locs_ok[iloc] &= no_points_in_rect(
                            xs_taken, ys_taken, *rcandi)

                        if not locs_ok[iloc]:
                            break

                rows = []
                for iloc, (lon, lat) in enumerate(zip(lons, lats)):
                    if not locs_ok[iloc]:
                        continue

                    if self.gmt.is_gmt5():
                        row = (
                            lon, lat,
                            '%i,%s,%s' % (font_size, font, color),
                            'MC',
                            text)

                    else:
                        row = (
                            lon, lat,
                            font_size, 0, font, 'MC',
                            text)

                    rows.append(row)

                    regions_taken.append([xxx[iloc] for xxx in rects])
                    break

                self.gmt.pstext(
                    in_rows=rows,
                    *(self.jxyr + farg),
                    **style)

    def draw_labels(self):
        self.gmt
        if not self._have_drawn_labels:
            self._draw_labels()
            self._have_drawn_labels = True

    def add_label(
            self, lat, lon, text,
            offset_x=5., offset_y=5.,
            color=None,
            font='1',
            font_size=None,
            style={}):

        if 'G' in style:
            style = style.copy()
            color = style.pop('G')

        self._labels.append(
            (lon, lat, text, offset_x, offset_y, color, font, font_size,
             style))

    def add_area_label(
            self, lat, lon, text,
            color=None,
            font='3',
            font_size=None,
            style={}):

        self._area_labels.append(
            (lon, lat, text, color, font, font_size, style))

    def cities_in_region(self):
        from pyrocko.dataset import geonames
        cities = geonames.get_cities_region(region=self.wesn, minpop=0)
        cities.extend(self.custom_cities)
        cities.sort(key=lambda x: x.population)
        return cities

    def draw_cities(self,
                    exact=None,
                    include=[],
                    exclude=[],
                    nmax_soft=10,
                    psxy_style=dict(S='s5p', G='black')):

        cities = self.cities_in_region()

        if exact is not None:
            cities = [c for c in cities if c.name in exact]
            minpop = None
        else:
            cities = [c for c in cities if c.name not in exclude]
            minpop = 10**3
            for minpop_new in [1e3, 3e3, 1e4, 3e4, 1e5, 3e5, 1e6, 3e6, 1e7]:
                cities_new = [
                    c for c in cities
                    if c.population > minpop_new or c.name in include]

                if len(cities_new) == 0 or (
                        len(cities_new) < 3 and len(cities) < nmax_soft*2):
                    break

                cities = cities_new
                minpop = minpop_new
                if len(cities) <= nmax_soft:
                    break

        if cities:
            lats = [c.lat for c in cities]
            lons = [c.lon for c in cities]

            self.gmt.psxy(
                in_columns=(lons, lats),
                *self.jxyr, **psxy_style)

            for c in cities:
                try:
                    text = c.name.encode('iso-8859-1').decode('iso-8859-1')
                except UnicodeEncodeError:
                    text = c.asciiname

                self.add_label(c.lat, c.lon, text)

        self._cities_minpop = minpop

    def add_stations(self, stations, psxy_style=dict(S='t8p', G='black')):
        lats = [s.lat for s in stations]
        lons = [s.lon for s in stations]

        self.gmt.psxy(
            in_columns=(lons, lats),
            *self.jxyr, **psxy_style)

        for station in stations:
            self.add_label(station.lat, station.lon, '.'.join(
                x for x in (station.network, station.station) if x))

    def add_kite_scene(self, scene):
        tile = FloatTile(
            scene.frame.llLon,
            scene.frame.llLat,
            scene.frame.dLon,
            scene.frame.dLat,
            scene.displacement)

        return tile

    def add_gnss_campaign(self, campaign,
                          psxy_style=dict(), labels=True):

        offsets = num.array([math.sqrt(s.east.shift**2 + s.north.shift**2)
                             for s in campaign.stations])
        scale = 1./offsets.max()

        default_psxy_style = {
            'h': 2,
            'h': 2,
            'W': '0.5p,black',
            't': '30',
            'G': 'black',
            'L': True,
            'S': 'e%d/0.95/8' % scale,
        }
        default_psxy_style.update(psxy_style)

        if labels:
            rows = [(s.lon, s.lat,
                     s.east.shift, s.north.shift,
                     s.east.sigma, s.north.sigma, 0)
                    for s in campaign.stations]
        else:
            rows = [(s.lon, s.lat,
                     s.east.shift, s.north.shift,
                     s.east.sigma, s.north.sigma, 0,
                     s.code)
                    for s in campaign.stations]

        kwargs = {}
        kwargs.update(default_psxy_style)
        kwargs.update(self.jxyr)

        self.gmt.psvelo(in_rows=rows, **kwargs)

    def draw_plates(self):
        from pyrocko.dataset import tectonics

        neast = 20
        nnorth = max(1, int(round(num.round(self._hreg/self._wreg * neast))))
        norths = num.linspace(-self._hreg*0.5, self._hreg*0.5, nnorth)
        easts = num.linspace(-self._wreg*0.5, self._wreg*0.5, neast)
        norths2 = num.repeat(norths, neast)
        easts2 = num.tile(easts, nnorth)
        lats, lons = od.ne_to_latlon(
            self.lat, self.lon, norths2, easts2)

        bird = tectonics.PeterBird2003()
        plates = bird.get_plates()

        color_plates = gmtpy.color('aluminium5')
        color_velocities = gmtpy.color('skyblue1')
        color_velocities_lab = gmtpy.color(darken(gmtpy.color_tup('skyblue1')))

        points = num.vstack((lats, lons)).T
        used = []
        for plate in plates:
            mask = plate.contains_points(points)
            if num.any(mask):
                used.append((plate, mask))

        if len(used) > 1:

            candi_fixed = {}

            label_data = []
            for plate, mask in used:

                mean_north = num.mean(norths2[mask])
                mean_east = num.mean(easts2[mask])
                iorder = num.argsort(num.sqrt(
                        (norths2[mask] - mean_north)**2 +
                        (easts2[mask] - mean_east)**2))

                lat_candis = lats[mask][iorder]
                lon_candis = lons[mask][iorder]

                candi_fixed[plate.name] = lat_candis.size

                label_data.append((
                    lat_candis, lon_candis, plate, color_plates))

            boundaries = bird.get_boundaries()

            size = 2

            psxy_kwargs = []

            for boundary in boundaries:
                if num.any(points_in_region(boundary.points, self._wesn)):
                    for typ, part in boundary.split_types(
                            [['SUB'],
                             ['OSR', 'OTF', 'OCB', 'CTF', 'CCB', 'CRB']]):

                        lats, lons = part.T

                        kwargs = {}
                        if typ[0] == 'SUB':
                            if boundary.kind == '\\':
                                kwargs['S'] = 'f%g/%gp+t+r' % (
                                    0.45*size, 3.*size)
                            elif boundary.kind == '/':
                                kwargs['S'] = 'f%g/%gp+t+l' % (
                                    0.45*size, 3.*size)

                            kwargs['G'] = color_plates

                        kwargs['in_columns'] = (lons, lats)
                        kwargs['W'] = '%gp,%s' % (size, color_plates),

                        psxy_kwargs.append(kwargs)

                        if boundary.kind == '\\':
                            if boundary.name2 in candi_fixed:
                                candi_fixed[boundary.name2] += neast*nnorth

                        elif boundary.kind == '/':
                            if boundary.name1 in candi_fixed:
                                candi_fixed[boundary.name1] += neast*nnorth

            candi_fixed = [name for name in sorted(
                list(candi_fixed.keys()), key=lambda name: -candi_fixed[name])]

            candi_fixed.append(None)

            gsrm = tectonics.GSRM1()

            for name in candi_fixed:
                if name not in gsrm.plate_names() \
                        and name not in gsrm.plate_alt_names():

                    continue

                lats, lons, vnorth, veast, vnorth_err, veast_err, corr = \
                    gsrm.get_velocities(name, region=self._wesn)

                fixed_plate_name = name

                self.gmt.psvelo(
                    in_columns=(
                        lons, lats, veast, vnorth, veast_err, vnorth_err,
                        corr),
                    W='0.25p,%s' % color_velocities,
                    A='9p+e+g%s' % color_velocities,
                    S='e0.2p/0.95/10',
                    *self.jxyr)

                for _ in range(len(lons) // 50 + 1):
                    ii = random.randint(0, len(lons)-1)
                    v = math.sqrt(vnorth[ii]**2 + veast[ii]**2)
                    self.add_label(
                        lats[ii], lons[ii], '%.0f' % v,
                        font_size=0.7*self.gmt.label_font_size(),
                        style=dict(
                            G=color_velocities_lab))

                break

            for (lat_candis, lon_candis, plate, color) in label_data:
                full_name = bird.full_name(plate.name)
                if plate.name == fixed_plate_name:
                    full_name = '@_' + full_name + '@_'

                self.add_area_label(
                    lat_candis, lon_candis,
                    full_name,
                    color=color,
                    font='3')

            for kwargs in psxy_kwargs:
                self.gmt.psxy(*self.jxyr, **kwargs)
コード例 #28
0
ファイル: model.py プロジェクト: braunfuss/silvertine
class CNNLayer(Layer):

    '''2D CNN layer'''
    kernel_width = Int.T()
    kernel_height = Int.T(optional=True,
        help='If this parameter is not set use *N* channels as height.')

    pool_width = Int.T(
        optional=True,
        help='If not set pool_height=kernel_height')

    pool_height = Int.T(
        optional=True,
        help='If not set pool_height=kernel_height')

    dilation_rate = Int.T(default=0)

    strides = Tuple.T(2, Int.T(), default=(1, 1))

    is_detector= Bool.T(default=False,
        help='If *True* this layer\'s activations contributes to detector.')

    def __init__(self, *args, **kwargs):
        Layer.__init__(self, *args, **kwargs)

        if not self.pool_width:
            logger.info(
                'Pool width is undefined. Setting equal to kernel width')
            self.pool_width = self.kernel_width

        if not self.pool_height:
            logger.info(
                'Pool heigth is undefined. Setting equal to kernel height')
            self.pool_height = self.kernel_height

    def chain(self, input, level, training=False, dropout_rate=0.):
        '''
        :param level: detection level
        '''
        _, n_channels, n_samples, _ = input.shape

        logger.debug('input shape %s' % input.shape)
        kernel_height = self.kernel_height or n_channels

        kwargs = {}
        if self.dilation_rate:
            kwargs.update({'dilation_rate': self.dilation_rate})

        inpower = tf.sqrt(tf.reduce_sum(tf.square(input)))

        input = tf.layers.conv2d(
            inputs=input,
            filters=self.n_filters,
            kernel_size=(kernel_height, self.kernel_width),
            activation=self.get_activation(),
            strides=self.strides,
            name=self.name,
            **kwargs)

        input = tf.layers.max_pooling2d(input,
            pool_size=(self.pool_width, self.pool_height),
            strides=(1, 1), name=self.name+'maxpool')

        if logger.getEffectiveLevel() == logging.DEBUG:
            tf.summary.image(
                'post-%s' % self.name, tf.split(
                    input, num_or_size_splits=self.n_filters, axis=-1)[0])

        if self.is_detector:
            batch_mean = tf.reduce_mean(input, reduction_indices=(1, 2, 3),
                    keepdims=True)

            stdev = tf.sqrt(tf.reduce_mean(tf.square(input - batch_mean),
                    reduction_indices=(1, 2, 3)))

            level += (tf.sqrt(tf.reduce_sum(tf.square(input))) / inpower)

        input = tf.layers.dropout(
            input, rate=dropout_rate, training=training)

        return tf.layers.batch_normalization(input, training=training), level

    def visualize_kernel(self, estimator, index=0, save_path=None, **kwargs):
        save_name = pjoin(save_path, 'kernel-%s' % self.name)
        weights = estimator.get_variable_value('%s/kernel' % self.name)
        plot.show_kernels(weights[:, :, index, ...], name=save_name)
コード例 #29
0
class GNSSTargetMisfitPlot(PlotConfig):
    ''' Maps showing horizontal surface displacements
        of a GNSS campaign and model '''

    name = 'gnss'

    size_cm = Tuple.T(2,
                      Float.T(),
                      default=(30., 30.),
                      help='width and length of the figure in cm')
    show_topo = Bool.T(default=False, help='show topography')
    show_grid = Bool.T(default=True, help='show the lat/lon grid')
    show_rivers = Bool.T(default=True, help='show rivers on the map')
    radius = Float.T(optional=True,
                     help='radius of the map around campaign center lat/lon')

    def make(self, environ):
        cm = environ.get_plot_collection_manager()
        history = environ.get_history(subset='harvest')
        optimiser = environ.get_optimiser()
        ds = environ.get_dataset()

        environ.setup_modelling()

        cm.create_group_automap(self,
                                self.draw_gnss_fits(ds, history, optimiser),
                                title=u'GNSS Displacements',
                                section='fits',
                                feather_icon='map',
                                description=u'''
Maps showing station positions and statiom names of the GNSS targets.

Arrows the observed surface displacements (black arrows) and synthetic
displacements (red arrows). The top plot shows the horizontal displacements and
the bottom plot the vertical displacements. The grey filled box shows the
surface projection of the modelled source, with the thick-lined edge marking
the upper fault edge.
''')

    def draw_gnss_fits(self, ds, history, optimiser, vertical=False):
        problem = history.problem

        gnss_targets = problem.gnss_targets
        for target in gnss_targets:
            target.set_dataset(ds)

        xbest = history.get_best_model()
        source = history.get_best_source()

        results = problem.evaluate(xbest,
                                   result_mode='full',
                                   targets=gnss_targets)

        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)

        ifig = 0
        for vertical in (False, True):
            for gnss_target, result in zip(problem.gnss_targets, results):
                yield plot_gnss(gnss_target, result, ifig, vertical)
                ifig += 1
コード例 #30
0
class HistogramPlot(PlotConfig):
    '''
    Histograms or Gaussian kernel densities (default) of all parameters
    (marginal distributions of model parameters).

    The histograms (by default shown as Gaussian kernel densities) show (red
    curved solid line) the distributions of the parameters (marginals) along
    with some characteristics: The red solid vertical line gives the median of
    the distribution and the dashed red vertical line the mean value. Dark gray
    vertical lines show reference values (given in the event.txt file). The
    overlapping red-shaded areas show the 68% confidence intervals (innermost
    area), the 90% confidence intervals (middle area) and the minimum and
    maximum values (widest area). The plot ranges are defined by the given
    parameter bounds and show the model space. Well resolved model parameters
    show peaked distributions.
    '''

    name = 'histogram'
    size_cm = Tuple.T(2, Float.T(), default=(12.5, 7.5))
    exclude = List.T(String.T())
    include = List.T(String.T())
    method = StringChoice.T(
        choices=['gaussian_kde', 'histogram'],
        default='gaussian_kde')
    show_reference = Bool.T(default=True)

    def make(self, environ):
        cm = environ.get_plot_collection_manager()
        history = environ.get_history(subset='harvest')

        mpl_init(fontsize=self.font_size)
        cm.create_group_mpl(
            self,
            self.draw_figures(history),
            title=u'Histogram',
            section='solution',
            feather_icon='bar-chart-2',
            description=u'''
Distribution of the problem's parameters.

The histograms are shown either as Gaussian kernel densities (red curved solid
line) or as bar plots the distributions of the parameters (marginals) along
with some characteristics:

The red solid vertical line gives the median of the distribution and the dashed
red vertical line the mean value. Dark gray vertical lines show reference
parameter values if given in the event.txt file. The overlapping red-shaded
areas show the 68% confidence intervals (innermost area), the 90% confidence
intervals (middle area) and the minimum and maximum values (widest area). The
plot ranges are defined by the given parameter bounds and show the model
space.
''')

    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