Ejemplo n.º 1
0
def plot_waveforms_raw(traces, savedir, iter=None):
    fig = plt.figure()

    tap_color_annot = (0.35, 0.35, 0.25)
    tap_color_edge = (0.85, 0.85, 0.80)
    waveform_color = scolor('aluminium5')
    misfit_color = scolor('scarletred1')
    for i, tr in enumerate(traces):
        comp = tr.channel
        dtrace = tr

        axes2 = fig.add_subplot(len(traces) / 8, len(traces) / 3, i + 1)

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

        axes = axes2.twinx()
        axes.set_axis_off()
        plot_trace(axes, dtrace, color=waveform_color, lw=0.5, zorder=5)
    if iter is None:
        fig.savefig(savedir + "waveforms.png")
    else:
        fig.savefig(savedir + "_%s_.png" % iter)


#    plt.show()
    plt.close()
    return fig
Ejemplo n.º 2
0
def bayesian_model_plot(models, axes=None, draw_bg=True, highlightidx=[]):
    """
    Plot cake layered earth models.
    """
    fontsize = 10
    if axes is None:
        mpl_init(fontsize=fontsize)
        fig, axes = plt.subplots(
            nrows=1, ncols=1, figsize=mpl_papersize('a6', 'portrait'))
        labelpos = mpl_margins(
            fig, left=6, bottom=4, top=1.5, right=0.5, units=fontsize)
        labelpos(axes, 2., 1.5)

    def plot_profile(mod, axes, vp_c, vs_c, lw=0.5):
        z = mod.profile('z')
        vp = mod.profile('vp')
        vs = mod.profile('vs')
        axes.plot(vp, z, color=vp_c, lw=lw)
        axes.plot(vs, z, color=vs_c, lw=lw)

    cp.labelspace(axes)
    cp.labels_model(axes=axes)
    if draw_bg:
        cp.sketch_model(models[0], axes=axes)
    else:
        axes.spines['right'].set_visible(False)
        axes.spines['top'].set_visible(False)

    ref_vp_c = scolor('aluminium5')
    ref_vs_c = scolor('aluminium5')
    vp_c = scolor('scarletred2')
    vs_c = scolor('skyblue2')

    for i, mod in enumerate(models):
            plot_profile(
            mod, axes, vp_c=light(vp_c, 0.3), vs_c=light(vs_c, 0.3), lw=1.)

    for count, i in enumerate(sorted(highlightidx)):
        if count == 0:
            vpcolor = ref_vp_c
            vscolor = ref_vs_c
        elif count == 1:
            vpcolor = scolor('butter3')
            vscolor = scolor('butter3')
        elif count == 2:
            vpcolor = scolor('skyblue2')
            vscolor = scolor('skyblue2')
        elif count == 3:
            vpcolor = scolor('plum2')
            vscolor = scolor('plum2')
        else:
            vpcolor = scolor('scarletred2')
            vscolor = scolor('scarletred2')

        plot_profile(
            models[i], axes, vp_c=vpcolor, vs_c=vscolor, lw=2.)

    ymin, ymax = axes.get_ylim()
    xmin, xmax = axes.get_xlim()
    xmin = 0.
    my = (ymax - ymin) * 0.05
    mx = (xmax - xmin) * 0.2
    axes.set_ylim(ymax, ymin - my)
    axes.set_xlim(xmin, xmax + mx)
    return fig, axes
Ejemplo n.º 3
0
def traceplot(trace, varnames=None, transform=lambda x: x, figsize=None,
              lines=None, combined=False, grid=False, varbins=None, nbins=40,
              alpha=0.35, priors=None, prior_alpha=1, prior_style='--',
              axs=None, posterior=None):
    """
    Plots posterior pdfs as histograms from multiple mtrace objects.

    Modified from pymc3.

    Parameters
    ----------

    trace : result of MCMC run
    varnames : list of variable names
        Variables to be plotted, if None all variable are plotted
    transform : callable
        Function to transform data (defaults to identity)
    posterior : str
        To mark posterior value in distribution 'max', 'min', 'mean', 'all'
    figsize : figure size tuple
        If None, size is (12, num of variables * 2) inch
    lines : dict
        Dictionary of variable name / value  to be overplotted as vertical
        lines to the posteriors and horizontal lines on sample values
        e.g. mean of posteriors, true values of a simulation
    combined : bool
        Flag for combining multiple chains into a single chain. If False
        (default), chains will be plotted separately.
    grid : bool
        Flag for adding gridlines to histogram. Defaults to True.
    varbins : list of arrays
        List containing the binning arrays for the variables, if None they will
        be created.
    nbins : int
        Number of bins for each histogram
    alpha : float
        Alpha value for plot line. Defaults to 0.35.
    axs : axes
        Matplotlib axes. Defaults to None.

    Returns
    -------

    ax : matplotlib axes
    """

    def make_bins(data, nbins=40):
        d = data.flatten()
        mind = d.min()
        maxd = d.max()
        return num.linspace(mind, maxd, nbins)

    def remove_var(varnames, varname):
        idx = varnames.index(varname)
        varnames.pop(idx)

    if varnames is None:
        varnames = [name for name in trace.varnames if not name.endswith('_')]

    if 'geo_like' in varnames:
        remove_var(varnames, varname='geo_like')

    if 'seis_like' in varnames:
        remove_var(varnames, varname='seis_like')

    if posterior:
        llk = trace.get_values('like', combine=combined, squeeze=False)
        llk = num.squeeze(transform(llk[0]))
        llk = pmp.make_2d(llk)

        posterior_idxs = get_fit_indexes(llk)

        colors = {
            'mean': scolor('orange1'),
            'min': scolor('butter1'),
            'max': scolor('scarletred2')}

    n = len(varnames)
    nrow = int(num.ceil(n / 2.))
    ncol = 2

    n_fig = nrow * ncol

    if figsize is None:
        figsize = (8.2, 11.7)

    if axs is None:
        fig, axs = plt.subplots(nrow, ncol, figsize=figsize)
        axs = num.atleast_2d(axs)
    elif axs.shape != (nrow, ncol):
        logger.warn('traceplot requires n*2 subplots')
        return None

    if varbins is None:
        make_bins_flag = True
        varbins = []
    else:
        make_bins_flag = False

    for i in range(n_fig):
        coli, rowi = utility.mod_i(i, nrow)

        if i > len(varnames) - 1:
            fig.delaxes(axs[rowi, coli])
        else:
            v = varnames[i]

            for d in trace.get_values(v, combine=combined, squeeze=False):
                d = num.squeeze(transform(d))
                d = pmp.make_2d(d)

                if make_bins_flag:
                    varbin = make_bins(d, nbins=nbins)
                    varbins.append(varbin)
                else:
                    varbin = varbins[i]

                histplot_op(
                    axs[rowi, coli], d, bins=varbin, alpha=alpha,
                    color=scolor('aluminium3'))
                axs[rowi, coli].set_title(str(v))
                axs[rowi, coli].grid(grid)
                axs[rowi, coli].set_ylabel("Frequency")

                if lines:
                    try:
                        axs[rowi, coli].axvline(x=lines[v], color="k", lw=1.5)
                    except KeyError:
                        pass

                if posterior:
                    for k, idx in posterior_idxs.iteritems():
                        axs[rowi, coli].axvline(
                            x=d[idx], color=colors[k], lw=1.5)

    fig.tight_layout()
    return fig, axs, varbins
Ejemplo n.º 4
0
def seismic_fits(problem, stage, plot_options):
    """
    Modified from grond. Plot synthetic and data waveforms and the misfit for
    the selected posterior model.
    """

    fontsize = 8
    fontsize_title = 10

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

    po = plot_options

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

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

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

    out_point = population[idx]

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

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

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

    skey = lambda tr: tr.channel

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

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

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

    cgs = cg_to_targets.keys()

    figs = []

    for cg in cgs:
        targets = cg_to_targets[cg]

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

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

        nxmax = 4
        nymax = 4

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

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

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

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

        data = []

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

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

        iorder = num.argsort(dists)

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

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

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

        gxs /= gmax
        gys /= gmax

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

        distmax = num.max(dists)

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

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

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

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

                    figs.append(figures[iyy, ixx])

                fig = figures[iyy, ixx]

                target = frame_to_target[iy, ix]

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

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

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

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

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

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

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

                dtrace = dtraces[itarget]

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

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

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

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

                misfit_color = scolor('scarletred2')

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

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

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

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

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

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

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

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

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

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

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

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

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

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

#                    axes.add_patch(bar)

                scale_string = None

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

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

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

            fig.suptitle(title, fontsize=fontsize_title)

    return figs
Ejemplo n.º 5
0
def geodetic_fits(problem, stage, plot_options):
    """
    Plot geodetic data, synthetics and residuals.
    """
    scattersize = 16
    fontsize = 10
    fontsize_title = 12
    ndmax = 3
    nxmax = 3
    cmap = plt.cm.jet

    po = plot_options

    if po.reference is not None:
        problem.get_synthetics(po.reference)
        ref_sources = copy.deepcopy(problem.sources)

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

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

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

    out_point = population[idx]
    results = problem.assemble_geodetic_results(out_point)
    nrmax = len(results)

    target_to_result = {}
    for target, result in zip(problem.gtargets, results):
        target_to_result[target] = result

    nfigs = int(num.ceil(float(nrmax) / float(ndmax)))

    figures = []
    axes = []

    for f in range(nfigs):
        fig, ax = plt.subplots(
            nrows=ndmax, ncols=nxmax, figsize=mpl_papersize('a4', 'portrait'))
        fig.tight_layout()
        fig.subplots_adjust(
                        left=0.08,
                        right=1.0 - 0.03,
                        bottom=0.06,
                        top=1.0 - 0.06,
                        wspace=0.,
                        hspace=0.3)
        figures.append(fig)
        axes.append(ax)

    def axis_config(axes, po):
        axes[1].get_yaxis().set_ticklabels([])
        axes[2].get_yaxis().set_ticklabels([])
        axes[1].get_xaxis().set_ticklabels([])
        axes[2].get_xaxis().set_ticklabels([])

        if po.plot_projection == 'latlon':
            ystr = 'Latitude [deg]'
            xstr = 'Longitude [deg]'
        elif po.plot_projection == 'utm':
            ystr = 'UTM Northing [km]'
            xstr = 'UTM Easting [km]'
        elif po.plot_projection == 'local':
            ystr = 'Distance [km]'
            xstr = 'Distance [km]'
        else:
            raise Exception(
                'Plot projection %s not available' % po.plot_projection)

        axes[0].set_ylabel(ystr, fontsize=fontsize)
        axes[0].set_xlabel(xstr, fontsize=fontsize)

    def draw_sources(ax, sources, po, **kwargs):
        for source in sources:
            rf = source.patches(1, 1, 'seismic')[0]
            if po.plot_projection == 'latlon':
                outline = rf.outline(cs='lonlat')
            elif po.plot_projection == 'utm':
                outline = rf.outline(cs='lonlat')
                utme, utmn = utility.lonlat_to_utm(
                    lon=outline[:, 0], lat=outline[:, 1], zone=po.utm_zone)
                outline = num.vstack([utme / km, utmn / km]).T
            elif po.plot_projection == 'local':
                outline = rf.outline(cs='xy')
            ax.plot(outline[:, 0], outline[:, 1], '-', linewidth=1.0, **kwargs)
            ax.plot(
                outline[0:2, 0], outline[0:2, 1], '-k', linewidth=1.0)

    def cbtick(x):
        rx = math.floor(x * 1000.) / 1000.
        return [-rx, rx]

    def str_title(track):
        if track[0] == 'A':
            orbit = 'ascending'
        elif track[0] == 'D':
            orbit = 'descending'

        title = 'Orbit: ' + orbit
        return title

    orbits_to_targets = utility.gather(
        problem.gtargets,
        lambda t: t.track,
        filter=lambda t: t in target_to_result)

    ott = orbits_to_targets.keys()

    colims = [num.max([
        num.max(num.abs(r.processed_obs)),
        num.max(num.abs(r.processed_syn))]) for r in results]
    dcolims = [num.max(num.abs(r.processed_res)) for r in results]

    for o in ott:
        targets = orbits_to_targets[o]

        for target in targets:
            if po.plot_projection == 'local':
                target.update_local_coords(problem.event)

            result = target_to_result[target]
            tidx = target_index[target]

            figidx, rowidx = utility.mod_i(tidx, ndmax)

            plot_scene(
                axes[figidx][rowidx, 0],
                target,
                result.processed_obs,
                scattersize,
                colim=colims[tidx],
                outmode=po.plot_projection,
                cmap=cmap)

            syn = plot_scene(
                axes[figidx][rowidx, 1],
                target,
                result.processed_syn,
                scattersize,
                colim=colims[tidx],
                outmode=po.plot_projection,
                cmap=cmap)

            res = plot_scene(
                axes[figidx][rowidx, 2],
                target,
                result.processed_res,
                scattersize,
                colim=dcolims[tidx],
                outmode=po.plot_projection,
                cmap=cmap)

            titley = 0.91
            titlex = 0.16

            axes[figidx][rowidx, 0].annotate(
                o,
                xy=(titlex, titley),
                xycoords='axes fraction',
                xytext=(2., 2.),
                textcoords='offset points',
                weight='bold',
                fontsize=fontsize_title)

            syn_color = scolor('plum1')
            ref_color = scolor('aluminium3')

            draw_sources(
                axes[figidx][rowidx, 1], problem.sources, po, color=syn_color)

            if po.reference is not None:
                draw_sources(
                    axes[figidx][rowidx, 1],
                    ref_sources, po, color=ref_color)

            cbb = 0.68 - (0.3175 * rowidx)
            cbl = 0.46
            cbw = 0.15
            cbh = 0.01

            cbaxes = figures[figidx].add_axes([cbl, cbb, cbw, cbh])
            dcbaxes = figures[figidx].add_axes([cbl + 0.3, cbb, cbw, cbh])

            cblabel = 'LOS displacement [m]'
            cbs = plt.colorbar(syn,
                ax=axes[figidx][rowidx, 0],
                ticks=cbtick(colims[tidx]),
                cax=cbaxes,
                orientation='horizontal',
                cmap=cmap)
            cbs.set_label(cblabel, fontsize=fontsize)

            cbr = plt.colorbar(res,
                ax=axes[figidx][rowidx, 2],
                ticks=cbtick(dcolims[tidx]),
                cax=dcbaxes,
                orientation='horizontal',
                cmap=cmap)
            cbr.set_label(cblabel, fontsize=fontsize)

            axis_config(axes[figidx][rowidx, :], po)

            title = str_title(o) + ' Llk_' + po.post_llk
            figures[figidx].suptitle(
                title, fontsize=fontsize_title, weight='bold')

    nplots = ndmax * nfigs
    for delidx in range(nrmax, nplots):
        figidx, rowidx = utility.mod_i(delidx, ndmax)
        for colidx in range(nxmax):
            figures[figidx].delaxes(axes[figidx][rowidx, colidx])

    return figures
Ejemplo n.º 6
0
def plot_waveforms(traces, event, stations, savedir, picks, show=True):
    fig = plt.figure(figsize=plot.mpl_papersize('a4', 'landscape'))
    tap_color_annot = (0.35, 0.35, 0.25)
    tap_color_edge = (0.85, 0.85, 0.80)
    waveform_color = scolor('aluminium5')
    misfit_color = scolor('scarletred1')
    ncomps = 3
    k = 0
    nstations = len(stations)
    ntraces = nstations * ncomps
    i = 0
    for st in stations:
        for comp in st.channels:
            for tr in traces:
                if tr.station == st.station:
                    if comp.name == tr.channel:
                        #    tr.downsample_to(0.05)
                        #    tr.highpass(4, 0.01)
                        #    tr.lowpass(4, 0.2)
                        dtrace = tr
                        i = i + 1
            target = st

            tmin_fit = dtrace.tmin
            tmax_fit = dtrace.tmax

            tfade_taper = 1. / 0.2

            taper = trace.CosTaper(tmin_fit - 20, tmin_fit, tmax_fit,
                                   tmax_fit + 30)
            k = k + 1
            axes2 = fig.add_subplot(nstations / 3, nstations / 3, k)
            space = 0.5
            space_factor = 1.0 + space
            axes2.set_axis_off()
            axes2.set_ylim(-1.05 * space_factor, 1.05)

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

            bw_filter = trace.ButterworthResponse(corner=2,
                                                  order=4,
                                                  type='low')

            setup = trace.MisfitSetup(description='setup',
                                      norm=2,
                                      taper=taper,
                                      filter=bw_filter,
                                      domain='time_domain')

            abs_tr = dtrace.copy()
            abs_tr.set_ydata(abs(dtrace.get_ydata()))

            plot_cc(axes2,
                    abs_tr,
                    space,
                    0.,
                    num.max(abs_tr.get_ydata()),
                    fc=light(misfit_color, 0.3),
                    ec=misfit_color,
                    zorder=4)

            plot_trace(axes, dtrace, color=waveform_color, lw=0.5, zorder=5)

            tmarks = [dtrace.tmin, dtrace.tmax]

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

            for tmark, text, ha, va in [
                (tmarks[0], '$\,$ ' + str_duration(tmarks[0]), 'left',
                 'bottom'),
                (tmarks[1], '$\Delta$ ' + str_duration(tmarks[1] - tmarks[0]),
                 'right', 'bottom')
            ]:
                axes2.annotate(text,
                               xy=(tmark, -0.9),
                               xycoords='data',
                               xytext=(fontsize * 0.4 * [-1, 1][ha == 'left'],
                                       fontsize * 0.2),
                               textcoords='offset points',
                               ha=ha,
                               va=va,
                               color=tap_color_annot,
                               fontsize=fontsize,
                               zorder=10)

            if picks is not None:
                for stp in picks["phases"]:
                    phases_station = []
                    picks_station = []
                    if st.station == stp["station"]:
                        phases_station.append(str(stp["phase"]))
                        picks_station.append(event.time + float(stp["pick"]))
                        picks_station.append(event.time)

                    tmarks = picks_station

                    for tmark in tmarks:
                        axes2.plot([tmark, tmark], [-1, 1.], color="blue")

                    for tmark, text, ha, va in [(tmarks, phases_station,
                                                 'left', 'bottom')]:
                        try:
                            axes2.annotate(
                                text[0],
                                xy=(tmark[0], -1.2),
                                xycoords='data',
                                xytext=(8 * 0.4 * [-1, 1][ha == 'left'],
                                        8 * 0.2),
                                textcoords='offset points',
                                ha=ha,
                                va=va,
                                color=tap_color_annot,
                                fontsize=8,
                                zorder=10)
                        except:
                            pass
            infos = []

            infos.append(target.network + "." + target.station + "." +
                         dtrace.channel)
            dist = event.distance_to(target)
            azi = event.azibazi_to(target)[0]
            infos.append(str_dist(dist))
            infos.append(u'%.0f\u00B0' % azi)

            axes2.annotate('\n'.join(infos),
                           xy=(0., 1.),
                           xycoords='axes fraction',
                           xytext=(2., 2.),
                           textcoords='offset points',
                           ha='left',
                           va='top',
                           fontsize=fontsize,
                           fontstyle='normal')
            if i / nstations == 1 or i / nstations == 2 or i / nstations == 3:
                fig.savefig(savedir +
                            "waveforms_%s.png" % str(int(i / nstations)),
                            dpi=100)

                if show is True:
                    plt.show()
                else:
                    plt.close()
                fig = plt.figure(figsize=plot.mpl_papersize('a4', 'landscape'))
                k = 0