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