def plot_init(size, save, show): fontsize = 9 mpl_init() fig = plt.figure(figsize=mpl_papersize(size, 'landscape')) labelpos = mpl_margins(fig, w=7., h=5., units=fontsize) axes = fig.add_subplot(1, 1, 1) labelpos(axes, 2., 1.5) showplt = bool(show or not save) return fig, axes, showplt
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
def draw_figures(self, environ): nwindow = 200 show_raw_acceptance_rates = False optimiser = environ.get_optimiser() problem = environ.get_problem() history = environ.get_history() chains = optimiser.chains(problem, history) chains.load() acceptance = chains.acceptance_history nmodels_rate = history.nmodels - (nwindow - 1) if nmodels_rate < 1: logger.warning( 'Cannot create plot acceptance: insufficient number of tested ' 'models.') return acceptance_rate = num.zeros((history.nchains, nmodels_rate)) for ichain in range(history.nchains): acceptance_rate[ichain, :] = trace.moving_sum( acceptance[ichain, :], nwindow, mode='valid') / float(nwindow) acceptance_n = num.sum(acceptance, axis=0) acceptance_any = num.minimum(acceptance_n, 1) acceptance_any_rate = trace.moving_sum( acceptance_any, nwindow, mode='valid') / float(nwindow) acceptance_p = acceptance_n / float(history.nchains) popularity = trace.moving_sum( acceptance_p, nwindow, mode='valid') \ / float(nwindow) / acceptance_any_rate mpl_init(fontsize=self.font_size) fig = plt.figure(figsize=self.size_inch) labelpos = mpl_margins(fig, w=7., h=5., units=self.font_size) axes = fig.add_subplot(1, 1, 1) labelpos(axes, 2.5, 2.0) imodels = num.arange(history.nmodels) imodels_rate = imodels[nwindow - 1:] axes.plot(acceptance_n / history.nchains * 100., '.', ms=2.0, color=mpl_color('skyblue2'), label='Popularity of Accepted Models', alpha=0.3) if show_raw_acceptance_rates: for ichain in range(chains.nchains): axes.plot(imodels_rate, acceptance_rate[ichain, :] * 100., color=mpl_color('scarletred2'), alpha=0.2) axes.plot(imodels_rate, popularity * 100., color=mpl_color('skyblue2'), label='Popularity (moving average)') axes.plot(imodels_rate, acceptance_any_rate * 100., color='black', label='Acceptance Rate (any chain)') axes.legend() axes.set_xlabel('Iteration') axes.set_ylabel('Acceptance Rate, Model Popularity') axes.set_ylim(0., 100.) axes.set_xlim(0., history.nmodels - 1) axes.grid(alpha=.2) axes.yaxis.set_major_formatter(FuncFormatter(lambda v, p: '%d%%' % v)) iiter = 0 bgcolors = [mpl_color('aluminium1'), mpl_color('aluminium2')] for iphase, phase in enumerate(optimiser.sampler_phases): axes.axvspan(iiter, iiter + phase.niterations, color=bgcolors[iphase % len(bgcolors)]) iiter += phase.niterations yield (PlotItem(name='acceptance', description=u''' Acceptance rate (black line) within a moving window of %d iterations. A model is considered accepted, if it is accepted in at least one chain. The popularity of accepted models is shown as blue dots. Popularity is defined as the percentage of chains accepting the model (100%% meaning acceptance in all chains). A moving average of the popularities is shown as blue line (same averaging interval as for the acceptance rate). Different background colors represent different sampler phases. ''' % nwindow), fig) mpl_init(fontsize=self.font_size) fig = plt.figure(figsize=self.size_inch) labelpos = mpl_margins(fig, w=7., h=5., units=self.font_size) axes = fig.add_subplot(1, 1, 1) labelpos(axes, 2.5, 2.0) nwindow2 = max(1, int(history.nmodels / (self.size_inch[1] * 100))) nmodels_rate2 = history.nmodels - (nwindow2 - 1) acceptance_rate2 = num.zeros((history.nchains, nmodels_rate2)) for ichain in range(history.nchains): acceptance_rate2[ichain, :] = trace.moving_sum( acceptance[ichain, :], nwindow2, mode='valid') \ / float(nwindow2) imodels_rate2 = imodels[nwindow2 - 1:] axes.pcolormesh(imodels_rate2, num.arange(history.nchains), num.log(0.01 + acceptance_rate2), cmap='GnBu') if history.sampler_contexts is not None: axes.plot(imodels, history.sampler_contexts[:, 1], '.', ms=2.0, color='black', label='Breeding Chain', alpha=0.3) axes.set_xlabel('Iteration') axes.set_ylabel('Bootstrap Chain') axes.set_xlim(0, history.nmodels - 1) axes.set_ylim(0, history.nchains - 1) axes.xaxis.grid(alpha=.4) yield (PlotItem(name='acceptance_img', description=u''' Model acceptance per bootstrap chain averaged over %d models (background color, low to high acceptance as light to dark colors). Black dots mark the base chains used when sampling new models (directed sampler phases only). ''' % nwindow2), fig)
def plot_polarizations(stations, trs, event=None, size_factor=0.05, fontsize=10., output_filename=None, output_format=None, output_dpi=None): if event is None: slats = num.array([s.lat for s in stations], dtype=num.float) slons = num.array([s.lon for s in stations], dtype=num.float) clat, clon = od.geographic_midpoint(slats, slons) event = od.Loc(clat, clon) nsl_c_to_trs = defaultdict(dict) for tr in trs: nsl_c_to_trs[tr.nslc_id[:3]][tr.nslc_id[3]] = tr nsl_to_station = dict((s.nsl(), s) for s in stations) plot.mpl_init(fontsize=fontsize) fig = plt.figure(figsize=plot.mpl_papersize('a4', 'landscape')) plot.mpl_margins(fig, w=7., h=6., units=fontsize) grid = ImageGrid(fig, 111, nrows_ncols=(2, 2), axes_pad=0.5, add_all=True, label_mode='L', aspect=True) axes_en = grid[0] axes_en.set_ylabel('Northing [km]') axes_dn = grid[1] axes_dn.locator_params(axis='x', nbins=4) axes_dn.set_xlabel('Depth [km]') axes_ed = grid[2] axes_ed.locator_params(axis='y', nbins=4) axes_ed.set_ylabel('Depth [km]') axes_ed.set_xlabel('Easting [km]') if isinstance(event, model.Event): axes_en.plot(0., 0., '*') axes_dn.plot(event.depth / km, 0., '*') axes_ed.plot(0., event.depth / km, '*') grid[3].set_axis_off() locations = [] for nsl in sorted(nsl_c_to_trs.keys()): station = nsl_to_station[nsl] n, e = od.latlon_to_ne(event.lat, event.lon, station.lat, station.lon) locations.append((n, e)) ns, es = num.array(locations, dtype=num.float).T n_min = num.min(ns) n_max = num.max(ns) e_min = num.min(es) e_max = num.max(es) factor = max((n_max - n_min) * size_factor, (e_max - e_min) * size_factor) fontsize_annot = fontsize * 0.7 data = {} for insl, nsl in enumerate(sorted(nsl_c_to_trs.keys())): color = plot.mpl_graph_color(insl) try: tr_e = nsl_c_to_trs[nsl]['E'] tr_n = nsl_c_to_trs[nsl]['N'] tr_z = nsl_c_to_trs[nsl]['Z'] except KeyError: continue station = nsl_to_station[nsl] n, e = od.latlon_to_ne(event.lat, event.lon, station.lat, station.lon) d = station.depth axes_en.annotate('.'.join(x for x in nsl if x), xy=(e / km, n / km), xycoords='data', xytext=(fontsize_annot / 3., fontsize_annot / 3.), textcoords='offset points', verticalalignment='bottom', horizontalalignment='left', rotation=0., size=fontsize_annot) axes_en.plot(e / km, n / km, '^', mfc=color, mec=darken(color)) axes_dn.plot(d / km, n / km, '^', mfc=color, mec=darken(color)) axes_ed.plot(e / km, d / km, '^', mfc=color, mec=darken(color)) arr_e = tr_e.ydata arr_n = tr_n.ydata arr_z = tr_z.ydata arr_t = tr_z.get_xdata() data[nsl] = (arr_e, arr_n, arr_z, arr_t, n, e, d, color) amaxs = [] amax_hors = [] for nsl in sorted(data.keys()): arr_e, arr_n, arr_z, arr_t, n, e, d, color = data[nsl] amaxs.append(num.max(num.abs(num.sqrt(arr_e**2 + arr_n**2 + arr_z**2)))) amax_hors.append(num.max(num.abs(num.sqrt(arr_e**2 + arr_n**2)))) amax = num.median(amaxs) amax_hor = num.median(amax_hors) for nsl in sorted(data.keys()): arr_e, arr_n, arr_z, arr_t, n, e, d, color = data[nsl] tmin = arr_t.min() tmax = arr_t.max() plot_color_line(axes_en, (e + arr_e / amax_hor * factor) / km, (n + arr_n / amax_hor * factor) / km, arr_t, color, tmin, tmax) plot_color_line(axes_dn, (d - arr_z / amax * factor) / km, (n + arr_n / amax * factor) / km, arr_t, color, tmin, tmax) plot_color_line(axes_ed, (e + arr_e / amax * factor) / km, (d - arr_z / amax * factor) / km, arr_t, color, tmin, tmax) axes_ed.invert_yaxis() for axes in (axes_dn, axes_ed, axes_en): axes.autoscale_view(tight=True) if output_filename is None: plt.show() else: fig.savefig(output_filename, format=output_format, dpi=output_dpi)
def draw_figures(self, history, optimiser): misfit_cutoff = self.misfit_cutoff sort_by = self.sort_by problem = history.problem models = history.models npar = problem.nparameters ndep = problem.ndependants fontsize = self.font_size nfx, nfy = self.subplot_layout imodels = num.arange(history.nmodels) bounds = problem.get_combined_bounds() xref = problem.get_reference_model() gms = history.get_primary_chain_misfits() gms_softclip = num.where(gms > 1.0, 0.2 * num.log10(gms) + 1.0, gms) isort = num.argsort(gms)[::-1] if sort_by == 'iteration': imodels = imodels[isort] elif sort_by == 'misfit': imodels = num.arange(imodels.size) else: assert False gms = gms[isort] gms_softclip = gms_softclip[isort] models = models[isort, :] iorder = num.empty_like(isort) iorder = num.arange(iorder.size) if misfit_cutoff is None: ibest = num.ones(gms.size, dtype=num.bool) else: ibest = gms < misfit_cutoff def config_axes(axes, nfx, nfy, impl, iplot, nplots): if (impl - 1) % nfx != nfx - 1: axes.get_yaxis().tick_left() if (impl - 1) >= (nfx * (nfy - 1)) or iplot >= nplots - nfx: axes.set_xlabel('Iteration') if not (impl - 1) // nfx == 0: axes.get_xaxis().tick_bottom() elif (impl - 1) // nfx == 0: axes.get_xaxis().tick_top() axes.set_xticklabels([]) else: axes.get_xaxis().set_visible(False) # nfz = (npar + ndep + 1 - 1) / (nfx*nfy) + 1 cmap = cm.YlOrRd cmap = cm.jet msize = self.marker_size axes = None fig = None item_fig = None nfigs = 0 alpha = 0.5 for ipar in range(npar): impl = ipar % (nfx * nfy) + 1 if impl == 1: if item_fig: yield item_fig nfigs += 1 fig = plt.figure(figsize=self.size_inch) labelpos = mpl_margins(fig, nw=nfx, nh=nfy, left=7., right=2., top=1., bottom=5., wspace=7., hspace=2., units=fontsize) item = PlotItem(name='fig_%i' % (nfigs + 1)) item.attributes['parameters'] = [] item_fig = (item, fig) par = problem.parameters[ipar] item_fig[0].attributes['parameters'].append(par.name) axes = fig.add_subplot(nfy, nfx, impl) labelpos(axes, 2.5, 2.0) axes.set_ylabel(par.get_label()) axes.get_yaxis().set_major_locator(plt.MaxNLocator(4)) config_axes(axes, nfx, nfy, impl, ipar, npar + ndep + 1) axes.set_ylim(*fixlim(*par.scaled(bounds[ipar]))) axes.set_xlim(0, history.nmodels) axes.scatter(imodels[ibest], par.scaled(models[ibest, ipar]), s=msize, c=iorder[ibest], edgecolors='none', cmap=cmap, alpha=alpha, rasterized=True) if self.show_reference: axes.axhline(par.scaled(xref[ipar]), color='black', alpha=0.3) for idep in range(ndep): # ifz, ify, ifx = num.unravel_index(ipar, (nfz, nfy, nfx)) impl = (npar + idep) % (nfx * nfy) + 1 if impl == 1: if item_fig: yield item_fig nfigs += 1 fig = plt.figure(figsize=self.size_inch) labelpos = mpl_margins(fig, nw=nfx, nh=nfy, left=7., right=2., top=1., bottom=5., wspace=7., hspace=2., units=fontsize) item = PlotItem(name='fig_%i' % (nfigs + 1)) item.attributes['parameters'] = [] item_fig = (item, fig) par = problem.dependants[idep] item_fig[0].attributes['parameters'].append(par.name) axes = fig.add_subplot(nfy, nfx, impl) labelpos(axes, 2.5, 2.0) axes.set_ylabel(par.get_label()) axes.get_yaxis().set_major_locator(plt.MaxNLocator(4)) config_axes(axes, nfx, nfy, impl, npar + idep, npar + ndep + 1) axes.set_ylim(*fixlim(*par.scaled(bounds[npar + idep]))) axes.set_xlim(0, history.nmodels) ys = problem.make_dependant(models[ibest, :], par.name) axes.scatter(imodels[ibest], par.scaled(ys), s=msize, c=iorder[ibest], edgecolors='none', cmap=cmap, alpha=alpha, rasterized=True) if self.show_reference: y = problem.make_dependant(xref, par.name) axes.axhline(par.scaled(y), color='black', alpha=0.3) impl = (npar + ndep) % (nfx * nfy) + 1 if impl == 1: if item_fig: yield item_fig nfigs += 1 fig = plt.figure(figsize=self.size_inch) labelpos = mpl_margins(fig, nw=nfx, nh=nfy, left=7., right=2., top=1., bottom=5., wspace=7., hspace=2., units=fontsize) item = PlotItem(name='fig_%i' % (nfigs + 1)) item.attributes['parameters'] = [] item_fig = (item, fig) axes = fig.add_subplot(nfy, nfx, impl) labelpos(axes, 2.5, 2.0) config_axes(axes, nfx, nfy, impl, npar + ndep, npar + ndep + 1) axes.set_ylim(0., 1.5) axes.set_yticks([0., 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4]) axes.set_yticklabels( ['0.0', '0.2', '0.4', '0.6', '0.8', '1', '10', '100']) axes.scatter(imodels[ibest], gms_softclip[ibest], c=iorder[ibest], s=msize, edgecolors='none', cmap=cmap, alpha=alpha) axes.axhspan(1.0, 1.5, color=(0.8, 0.8, 0.8), alpha=0.2) axes.axhline(1.0, color=(0.5, 0.5, 0.5), zorder=2) axes.set_xlim(0, history.nmodels) axes.set_xlabel('Iteration') axes.set_ylabel('Misfit') yield item_fig nfigs += 1
def draw_figures(self, dataset, history, optimiser): fontsize = self.font_size fig = plt.figure(figsize=self.size_inch) labelpos = mpl_margins(fig, nw=2, nh=2, w=7., h=5., wspace=2., hspace=5., units=fontsize) problem = history.problem if not problem: logger.warn('Problem not set.') return [] models = history.models if models.size == 0: logger.warn('Empty models vector.') return [] for target in problem.targets: target.set_dataset(dataset) imodels = num.arange(history.nmodels) gms = history.get_sorted_primary_misfits()[::-1] isort = history.get_sorted_misfits_idx(chain=0)[::-1] gms **= problem.norm_exponent gms_softclip = num.where(gms > 1.0, 0.1 * num.log10(gms) + 1.0, gms) gcms = problem.combine_misfits( history.misfits, extra_correlated_weights=optimiser.get_correlated_weights(problem), get_contributions=True) gcms = gcms[isort, :] nmisfits = gcms.shape[1] # noqa ncontributions = sum([ 1 if t.plot_misfits_cumulative else t.nmisfits for t in problem.targets ]) cum_gcms = num.zeros((history.nmodels, ncontributions)) # Squash matrix and sum large targets.nmisifts, eg SatelliteTarget plot_target_labels = [] idx = 0 idx_cum = 0 for itarget, target in enumerate(problem.targets): target_gcms = gcms[:, idx:idx + target.nmisfits] if target.plot_misfits_cumulative: cum_gcms[:, idx_cum] = target_gcms.sum(axis=1) plot_target_labels.append(target.string_id()) idx_cum += 1 else: cum_gcms[:, idx_cum:idx_cum + target.nmisfits] = target_gcms plot_target_labels.extend(target.misfits_string_ids()) idx_cum += target.nmisfits idx += target.nmisfits jsort = num.argsort(cum_gcms[-1, :])[::-1] # ncols = 4 # nrows = ((problem.ntargets + 1) - 1) / ncols + 1 axes = fig.add_subplot(2, 2, 1) labelpos(axes, 2.5, 2.0) axes.set_ylabel('Relative contribution (smoothed)') axes.set_ylim(0.0, 1.0) axes2 = fig.add_subplot(2, 2, 3, sharex=axes) labelpos(axes2, 2.5, 2.0) axes2.set_xlabel( 'Tested model, sorted descending by global misfit value') axes2.set_ylabel('Square of misfit') axes2.set_ylim(0., 1.5) axes2.axhspan(1.0, 1.5, color=(0.8, 0.8, 0.8)) axes2.set_yticks( [0., 0.2, 0.4, 0.6, 0.8, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5]) axes2.set_yticklabels([ '0.0', '0.2', '0.4', '0.6', '0.8', '1', '10', '100', '1000', '10000', '100000' ]) axes2.set_xlim(imodels[0], imodels[-1]) rel_ms_sum = num.zeros(history.nmodels) rel_ms_smooth_sum = num.zeros(history.nmodels) ms_smooth_sum = num.zeros(history.nmodels) b = num.hanning(min(100, history.nmodels // 5)) b /= num.sum(b) a = [1] ii = 0 for idx in jsort: target_label = plot_target_labels[idx] ms = cum_gcms[:, idx] ms = num.where(num.isfinite(ms), ms, 0.0) if num.all(ms == 0.0): continue rel_ms = ms / gms if b.shape[0] > 5: rel_ms_smooth = signal.filtfilt(b, a, rel_ms) else: rel_ms_smooth = rel_ms ms_smooth = rel_ms_smooth * gms_softclip rel_poly_y = num.concatenate( [rel_ms_smooth_sum[::-1], rel_ms_smooth_sum + rel_ms_smooth]) poly_x = num.concatenate([imodels[::-1], imodels]) add_args = {} if ii < 20: add_args['label'] = '%s (%.2g)' % (target_label, num.mean(rel_ms[-1])) axes.fill(poly_x, rel_poly_y, alpha=0.5, color=mpl_graph_color(ii), **add_args) poly_y = num.concatenate( [ms_smooth_sum[::-1], ms_smooth_sum + ms_smooth]) axes2.fill(poly_x, poly_y, alpha=0.5, color=mpl_graph_color(ii)) rel_ms_sum += rel_ms # axes.plot( # imodels, rel_ms_sum, color='black', alpha=0.1, zorder=-1) ms_smooth_sum += ms_smooth rel_ms_smooth_sum += rel_ms_smooth ii += 1 axes.legend(title='Contributions (top twenty)', bbox_to_anchor=(1.05, 0.0, 1.0, 1.0), loc='upper left', ncol=1, borderaxespad=0., prop={'size': 9}) axes2.plot(imodels, gms_softclip, color='black') axes2.axhline(1.0, color=(0.5, 0.5, 0.5)) return [[PlotItem(name='main'), fig]]
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
from matplotlib import pyplot as plt from pyrocko.plot import mpl_init, mpl_margins, mpl_papersize # from pyrocko.plot import mpl_labelspace fontsize = 9. # in points # set some Pyrocko style defaults mpl_init(fontsize=fontsize) fig = plt.figure(figsize=mpl_papersize('a4', 'landscape')) # let margins be proportional to selected font size, e.g. top and bottom # margin are set to be 5*fontsize = 45 [points] labelpos = mpl_margins(fig, w=7., h=5., units=fontsize) axes = fig.add_subplot(1, 1, 1) # positioning of axis labels # mpl_labelspace(axes) # either: relative to axis tick labels labelpos(axes, 2., 1.5) # or: relative to left/bottom paper edge axes.plot([0, 1], [0, 9]) axes.set_xlabel('Time [s]') axes.set_ylabel('Amplitude [m]') fig.savefig('plot_skeleton.pdf') plt.show()
def plot( responses, filename=None, dpi=100, fmin=0.01, fmax=100., nf=100, normalize=False, fontsize=10., figsize=None, styles=None, labels=None): ''' Draw instrument responses in Bode plot style. :param responses: instrument responses as :py:class:`pyrocko.trace.FrequencyResponse` objects :param fmin: minimum frequency [Hz] :param fmax: maximum frequency [Hz] :param nf: number of frequencies where to evaluate the response :param normalize: if ``True`` normalize flat part of response to be ``1`` :param styles: :py:class:`list` of :py:class:`dict` objects with keyword arguments to be passed to matplotlib's :py:meth:`matplotlib.axes.Axes.plot` function when drawing the response lines. Length must match number of responses. :param filename: file name to pass to matplotlib's ``savefig`` function. If ``None``, the plot is shown with :py:func:`matplotlib.pyplot.show`. :param fontsize: font size in points used in axis labels and legend :param figsize: :py:class:`tuple`, ``(width, height)`` in inches :param labels: :py:class:`list` of names to show in legend. Length must correspond to number of responses. ''' from matplotlib import pyplot as plt from pyrocko.plot import mpl_init, mpl_margins, mpl_papersize from pyrocko.plot import graph_colors, to01 mpl_init(fontsize=fontsize) if figsize is None: figsize = mpl_papersize('a4', 'portrait') fig = plt.figure(figsize=figsize) labelpos = mpl_margins( fig, w=7., h=5., units=fontsize, nw=1, nh=2, hspace=2.) axes_amplitude = fig.add_subplot(2, 1, 1) labelpos(axes_amplitude, 2., 1.5) axes_phase = fig.add_subplot(2, 1, 2) labelpos(axes_phase, 2., 1.5) setup_axes(axes_amplitude, axes_phase) if styles is None: styles = [ dict(color=to01(graph_colors[i % len(graph_colors)])) for i in range(len(responses))] else: assert len(styles) == len(responses) if labels is None: labels = [None] * len(responses) else: assert len(labels) == len(responses) a_ranges, p_ranges = [], [] have_labels = False for style, resp, label in zip(styles, responses, labels): a_range, p_range = draw( response=resp, axes_amplitude=axes_amplitude, axes_phase=axes_phase, fmin=fmin, fmax=fmax, nf=nf, normalize=normalize, style=style, label=label) if label is not None: have_labels = True a_ranges.append(a_range) p_ranges.append(p_range) if have_labels: axes_amplitude.legend(loc='lower right', prop=dict(size=fontsize)) a_ranges = num.array(a_ranges) p_ranges = num.array(p_ranges) amin, amax = num.min(a_ranges), num.max(a_ranges) pmin, pmax = num.min(p_ranges), num.max(p_ranges) amin *= 0.5 amax *= 2.0 pmin -= 0.5 pmax += 0.5 axes_amplitude.set_ylim(amin, amax) axes_phase.set_ylim(pmin, pmax) axes_amplitude.set_xlim(fmin, fmax) axes_phase.set_xlim(fmin, fmax) if filename is not None: fig.savefig(filename, dpi=dpi) else: plt.show()
def plot_station_distribution(self, azimuths, distances, weights, labels=None, scatter_kwargs=dict(), annotate_kwargs=dict(), maxsize=10**2): invalid_color = plot.mpl_color('aluminium3') scatter_default = { 'alpha': .5, 'zorder': 10, 'c': plot.mpl_color('skyblue2'), } annotate_default = { 'alpha': .8, 'color': 'k', 'fontsize': self.font_size_labels, 'ha': 'right', 'va': 'top', 'xytext': (-5, -5), 'textcoords': 'offset points' } scatter_default.update(scatter_kwargs) annotate_default.update(annotate_kwargs) fig = plt.figure(figsize=self.size_inch) plot.mpl_margins(fig, nw=1, nh=1, left=3., right=10., top=3., bottom=3., units=self.font_size) ax = fig.add_subplot(111, projection='polar') valid = ~num.isnan(weights) weights = weights.copy() weights[~valid] = weights[valid].min() colors = [scatter_default['c'] if s else invalid_color for s in valid] scatter_default.pop('c') weights_ref = plot.nice_value(weights[valid].max()) weights_scaled = (weights / weights_ref) * maxsize stations = ax.scatter(azimuths * d2r, distances, s=weights_scaled, c=colors, **scatter_default) if len(labels) < 30: # TODO: remove after impl. of collision detection if labels is not None: for ilbl, label in enumerate(labels): ax.annotate(label, (azimuths[ilbl] * d2r, distances[ilbl]), **annotate_default) ax.set_theta_zero_location('N') ax.set_theta_direction(-1) ax.tick_params('y', labelsize=self.font_size, labelcolor='gray') ax.grid(alpha=.3) ax.set_ylim(0, distances.max() * 1.1) ax.yaxis.set_major_locator(plt.MaxNLocator(4)) ax.yaxis.set_major_formatter( FuncFormatter(lambda x, pos: '%d km' % (x / km))) # Legend entries = 4 valid_marker = num.argmax(valid) fc = stations.get_facecolor()[valid_marker] ec = stations.get_edgecolor()[valid_marker] def get_min_precision(values): sig_prec = num.floor(num.isfinite(num.log10(weights))) return int(abs(sig_prec.min())) + 1 legend_artists = [ lines.Line2D([0], [0], ls='none', marker='o', ms=num.sqrt(rad), mfc=fc, mec=ec) for rad in num.linspace(maxsize, .1 * maxsize, entries) ] sig_prec = get_min_precision(weights) legend_annot = [ '{value:.{prec}f}'.format(value=val, prec=sig_prec) for val in num.linspace(weights_ref, .1 * weights_ref, entries) ] if not num.all(valid): legend_artists.append( lines.Line2D([0], [0], ls='none', marker='o', ms=num.sqrt(maxsize), mfc=invalid_color, mec=invalid_color)) legend_annot.append('Excluded') legend = fig.legend(legend_artists, legend_annot, fontsize=self.font_size, loc=4, markerscale=1, numpoints=1, frameon=False) return fig, ax, legend
def draw_figures(self, history): fontsize = self.font_size fig = plt.figure(figsize=self.size_inch) labelpos = mpl_margins(fig, nw=2, nh=2, w=7., h=5., wspace=2., hspace=5., units=fontsize) problem = history.problem if not problem: logger.warn('problem not set') return [] models = history.models if models.size == 0: logger.warn('empty models vector') return [] imodels = num.arange(history.nmodels) gms = problem.combine_misfits(history.misfits)**problem.norm_exponent isort = num.argsort(gms)[::-1] gms = gms[isort] gms_softclip = num.where(gms > 1.0, 0.1 * num.log10(gms) + 1.0, gms) gcms = problem.combine_misfits(history.misfits, get_contributions=True) gcms = gcms[isort, :] jsort = num.argsort(gcms[-1, :])[::-1] # ncols = 4 # nrows = ((problem.ntargets + 1) - 1) / ncols + 1 axes = fig.add_subplot(2, 2, 1) labelpos(axes, 2.5, 2.0) axes.set_ylabel('Relative contribution (smoothed)') axes.set_ylim(0.0, 1.0) axes2 = fig.add_subplot(2, 2, 3, sharex=axes) labelpos(axes2, 2.5, 2.0) axes2.set_xlabel( 'Tested model, sorted descending by global misfit value') axes2.set_ylabel('Square of misfit') axes2.set_ylim(0., 1.5) axes2.axhspan(1.0, 1.5, color=(0.8, 0.8, 0.8)) axes2.set_yticks( [0., 0.2, 0.4, 0.6, 0.8, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5]) axes2.set_yticklabels([ '0.0', '0.2', '0.4', '0.6', '0.8', '1', '10', '100', '1000', '10000', '100000' ]) axes2.set_xlim(imodels[0], imodels[-1]) rel_ms_sum = num.zeros(history.nmodels) rel_ms_smooth_sum = num.zeros(history.nmodels) ms_smooth_sum = num.zeros(history.nmodels) b = num.hanning(min(100, history.nmodels // 3)) b /= num.sum(b) a = [1] ii = 0 target_idx = [ str(it) * t.nmisfits for it, t in enumerate(problem.targets) ] target_idx = num.fromiter(map(float, ''.join(target_idx)), dtype=int) for idx in jsort: target = problem.targets[target_idx[idx]] ms = gcms[:, idx] ms = num.where(num.isfinite(ms), ms, 0.0) if num.all(ms == 0.0): continue rel_ms = ms / gms rel_ms_smooth = signal.filtfilt(b, a, rel_ms) ms_smooth = rel_ms_smooth * gms_softclip rel_poly_y = num.concatenate( [rel_ms_smooth_sum[::-1], rel_ms_smooth_sum + rel_ms_smooth]) poly_x = num.concatenate([imodels[::-1], imodels]) add_args = {} if ii < 20: add_args['label'] = '%s (%.2g)' % (target.string_id(), num.mean(rel_ms[-1])) axes.fill(poly_x, rel_poly_y, alpha=0.5, color=mpl_graph_color(ii), **add_args) poly_y = num.concatenate( [ms_smooth_sum[::-1], ms_smooth_sum + ms_smooth]) axes2.fill(poly_x, poly_y, alpha=0.5, color=mpl_graph_color(ii)) rel_ms_sum += rel_ms # axes.plot( # imodels, rel_ms_sum, color='black', alpha=0.1, zorder=-1) ms_smooth_sum += ms_smooth rel_ms_smooth_sum += rel_ms_smooth ii += 1 axes.legend(title='Contributions (top twenty)', bbox_to_anchor=(1.05, 0.0, 1.0, 1.0), loc='upper left', ncol=1, borderaxespad=0., prop={'size': 9}) axes2.plot(imodels, gms_softclip, color='black') axes2.axhline(1.0, color=(0.5, 0.5, 0.5)) return [[PlotItem(name='main'), fig]]
mod = cake.load_model('ak135-f-continental.m') phases = cake.PhaseDef.classic('Pg') source_depth = 20. * km distances = num.linspace(100. * km, 1000. * km, 100) data = [] for distance in distances: rays = mod.arrivals(phases=phases, distances=[distance * cake.m2d], zstart=source_depth) for ray in rays[:1]: data.append((distance, ray.t)) phase_distances, phase_time = num.array(data, dtype=num.float).T # Plot the arrival times mpl_init(fontsize=fontsize) fig = plt.figure(figsize=mpl_papersize('a5', 'landscape')) labelpos = mpl_margins(fig, w=7., h=5., units=fontsize) axes = fig.add_subplot(1, 1, 1) labelpos(axes, 2., 1.5) axes.set_xlabel('Distance [km]') axes.set_ylabel('Time [s]') axes.plot(phase_distances / km, phase_time, 'o', ms=3., color='black') fig.savefig('cake_first_arrivals.pdf')
def plot_station_distribution(self, azimuths, distances, weights, labels=None, colors=None, cmap=None, cnorm=None, clabel=None, scatter_kwargs=dict(), annotate_kwargs=dict(), maxsize=10**2, legend_title=''): invalid_color = plot.mpl_color('aluminium3') scatter_default = { 'alpha': .5, 'zorder': 10, 'c': plot.mpl_color('skyblue2'), } annotate_default = { 'alpha': .8, 'color': 'k', 'fontsize': self.font_size_labels, 'ha': 'right', 'va': 'top', 'xytext': (-5, -5), 'textcoords': 'offset points' } scatter_default.update(scatter_kwargs) annotate_default.update(annotate_kwargs) fig = plt.figure(figsize=self.size_inch) plot.mpl_margins(fig, nw=1, nh=1, left=3., right=10., top=3., bottom=3., units=self.font_size) ax = fig.add_subplot(111, projection='polar') valid = num.isfinite(weights) valid[valid] = num.logical_and(valid[valid], weights[valid] > 0.0) weights = weights.copy() if num.sum(valid) == 0: weights[:] = 1.0 weights_ref = 1.0 else: weights[~valid] = weights[valid].min() weights_ref = plot.nice_value(weights[valid].max()) if weights_ref == 0.: weights_ref = 1.0 if colors is None: scolors = [ scatter_default['c'] if s else invalid_color for s in valid ] else: if cnorm is None: cnorm = mcolors.Normalize() elif isinstance(cnorm, tuple): cnorm = mcolors.Normalize(vmin=cnorm[0], vmax=cnorm[1]) if cmap is None: cmap = plt.get_cmap('viridis') elif isinstance(cmap, str): cmap = plt.get_cmap(cmap) sm = mcm.ScalarMappable(norm=cnorm, cmap=cmap) sm.set_array(colors) scolors = [sm.to_rgba(value) for value in colors] scolors = num.array(scolors) scatter_default.pop('c') weights_scaled = (weights / weights_ref) * maxsize ws, exp, fmt = make_scale(0., weights_ref) ws = ws[1:] weight_clip_min = ws[0] weight_clip_min_scaled = (weight_clip_min / weights_ref) * maxsize weights_scaled = num.maximum(weight_clip_min_scaled, weights_scaled) stations = ax.scatter(azimuths * d2r, distances, s=weights_scaled, c=scolors, edgecolors=darken(0.5, scolors), linewidths=1.0, **scatter_default) if len(labels) < 30: # TODO: remove after impl. of collision detection if labels is not None: for ilbl, label in enumerate(labels): ax.annotate(label, (azimuths[ilbl] * d2r, distances[ilbl]), **annotate_default) ax.set_theta_zero_location('N') ax.set_theta_direction(-1) ax.tick_params('y', labelsize=self.font_size, labelcolor='gray') ax.grid(alpha=.2) ax.set_ylim(0, distances.max() * 1.1) ax.yaxis.set_major_locator(plt.MaxNLocator(4)) ax.yaxis.set_major_formatter( FuncFormatter(lambda x, pos: '%d km' % (x / km) if x != 0.0 else '')) # Legend valid_marker = num.argmax(valid) ecl = stations.get_edgecolor() fc = tuple(stations.get_facecolor()[valid_marker]) ec = tuple(ecl[min(valid_marker, len(ecl) - 1)]) legend_data = [] for w in ws[::-1]: legend_data.append( (lines.Line2D([0], [0], ls='none', marker='o', ms=num.sqrt(w / weights_ref * maxsize), mfc=fc, mec=ec), fmt % (w / 10**exp) + ('$\\times 10^{%i}$' % exp if exp != 0 else ''))) if not num.all(valid): legend_data.append((lines.Line2D([0], [0], marker='o', ms=num.sqrt(maxsize), mfc=invalid_color, mec=darken(0.5, invalid_color), mew=1.0), 'Excluded')) legend = fig.legend(*zip(*legend_data), fontsize=self.font_size, loc='upper left', bbox_to_anchor=(0.77, 0.4), markerscale=1, numpoints=1, frameon=False) legend.set_title(legend_title, prop=dict(size=self.font_size)) cb_axes = fig.add_axes([0.8, 0.6, 0.02, 0.3]) if clabel is not None: fig.colorbar(sm, cax=cb_axes, label=clabel, extend='both') return fig, ax, legend
def start(self): nfx = 1 nfy = 1 problem = self.problem ixpar = problem.name_to_index(self.xpar_name) iypar = problem.name_to_index(self.ypar_name) mpl_init(fontsize=self.fontsize) fig = plt.figure(figsize=(9.6, 5.4)) labelpos = mpl_margins(fig, nw=nfx, nh=nfy, w=7., h=5., wspace=7., hspace=2., units=self.fontsize) xpar = problem.parameters[ixpar] ypar = problem.parameters[iypar] if xpar.unit == ypar.unit: axes = fig.add_subplot(nfy, nfx, 1, aspect=1.0) else: axes = fig.add_subplot(nfy, nfx, 1) labelpos(axes, 2.5, 2.0) axes.set_xlabel(xpar.get_label()) axes.set_ylabel(ypar.get_label()) axes.get_xaxis().set_major_locator(plt.MaxNLocator(4)) axes.get_yaxis().set_major_locator(plt.MaxNLocator(4)) xref = problem.get_reference_model() axes.axvline(xpar.scaled(xref[ixpar]), color='black', alpha=0.3) axes.axhline(ypar.scaled(xref[iypar]), color='black', alpha=0.3) self.fig = fig self.problem = problem self.xpar = xpar self.ypar = ypar self.axes = axes self.ixpar = ixpar self.iypar = iypar from matplotlib import colors n = self.optimiser.nbootstrap + 1 hsv = num.vstack((num.random.uniform(0., 1., n), num.random.uniform(0.5, 0.9, n), num.repeat(0.7, n))).T self.bcolors = colors.hsv_to_rgb(hsv[num.newaxis, :, :])[0, :, :] self.bcolors[0, :] = [0., 0., 0.] bounds = self.problem.get_combined_bounds() from grond import plot self.xlim = plot.fixlim(*xpar.scaled(bounds[ixpar])) self.ylim = plot.fixlim(*ypar.scaled(bounds[iypar])) self.set_limits() from matplotlib.colors import LinearSegmentedColormap self.cmap = LinearSegmentedColormap.from_list('probability', [(1.0, 1.0, 1.0), (0.5, 0.9, 0.6)]) self.writer = None if self.movie_filename: from matplotlib.animation import FFMpegWriter metadata = dict(title=problem.name, artist='Grond') self.writer = FFMpegWriter(fps=30, metadata=metadata, codec='libx264', bitrate=200000, extra_args=[ '-pix_fmt', 'yuv420p', '-profile:v', 'baseline', '-level', '3', '-an' ]) self.writer.setup(self.fig, self.movie_filename, dpi=200) if self.show: plt.ion() plt.show()
def draw_figure(self, ds, history, tpath): problem = history.problem color_parameter = self.color_parameter misfit_cutoff = self.misfit_cutoff fontsize = self.font_size targets = [ t for t in problem.targets if isinstance(t, PhaseRatioTarget) and t.path == tpath ] gms = problem.combine_misfits(history.misfits) isort = num.argsort(gms)[::-1] gms = gms[isort] models = history.models[isort, :] if misfit_cutoff is not None: ibest = gms < misfit_cutoff gms = gms[ibest] models = models[ibest] gms = gms[::self.istride_ensemble] models = models[::self.istride_ensemble] nmodels = models.shape[0] if color_parameter == 'dist': mx = num.mean(models, axis=0) cov = num.cov(models.T) mdists = core.mahalanobis_distance(models, mx, cov) icolor = meta.ordersort(mdists) elif color_parameter == 'misfit': iorder = num.arange(nmodels) icolor = iorder elif color_parameter in problem.parameter_names: ind = problem.name_to_index(color_parameter) icolor = problem.extract(models, ind) from matplotlib import colors cmap = cm.ScalarMappable(norm=colors.Normalize(vmin=num.min(icolor), vmax=num.max(icolor)), cmap=plt.get_cmap('coolwarm')) imodel_to_color = [] for imodel in range(nmodels): imodel_to_color.append(cmap.to_rgba(icolor[imodel])) data = [] for imodel in range(nmodels): model = models[imodel, :] # source = problem.get_source(model) results = problem.evaluate(model, targets=targets) for target, result in zip(targets, results): if isinstance(result, gf.SeismosizerError): continue if not isinstance(target, PhaseRatioTarget): continue a_obs = result.a_obs b_obs = result.b_obs a_syn = result.a_syn b_syn = result.b_syn r_obs = a_obs / (a_obs + b_obs) r_syn = a_syn / (a_syn + b_syn) data.append(('.'.join(target.codes), imodel, r_obs, r_syn)) fontsize = self.font_size item = PlotItem(name='fig_%s' % tpath) item.attributes['targets'] = [t.string_id() for t in targets] fig = plt.figure(figsize=self.size_inch) labelpos = mpl_margins(fig, nw=1, nh=1, left=7., right=1., bottom=10., top=3, units=fontsize) axes = fig.add_subplot(1, 1, 1) labelpos(axes, 2.5, 2.0) labels = sorted(set(x[0] for x in data)) ntargets = len(labels) string_id_to_itarget = dict((x, i) for (i, x) in enumerate(labels)) itargets = num.array([string_id_to_itarget[x[0]] for x in data]) imodels = num.array([x[1] for x in data], dtype=num.int).T r_obs, r_syn = num.array([x[2:] for x in data]).T r_obs_median = num.zeros(ntargets) for itarget in range(ntargets): r_obs_median[itarget] = num.median(r_obs[itargets == itarget]) iorder = meta.ordersort(r_obs_median) for imodel in range(nmodels): mask = imodels == imodel axes.plot(iorder[itargets[mask]], r_obs[mask], '_', ms=20., zorder=-10, alpha=0.5, color='black') axes.plot(iorder[itargets[mask]], r_syn[mask], '_', ms=10., alpha=0.5, color=imodel_to_color[imodel]) axes.set_yscale('log') axes.set_ylabel('Ratio') axes.set_xticks(iorder[num.arange(ntargets)]) axes.set_xticklabels(labels, rotation='vertical') fig.suptitle(tpath, fontsize=self.font_size_title) yield item, fig
def draw_figure(self, sources, target, results): t0_mean = num.mean([s.time for s in sources]) # distances = [ # s.distance_to(target) for s in sources] # distance_min = num.min(distances) # distance_max = num.max(distances) yabsmaxs = [] for result in results: if isinstance(result, WaveformMisfitResult): yabsmaxs.append( num.max(num.abs( result.filtered_obs.get_ydata()))) if yabsmaxs: yabsmax = max(yabsmaxs) or 1.0 else: yabsmax = None fontsize = self.font_size fig = plt.figure(figsize=self.size_inch) labelpos = plot.mpl_margins( fig, nw=1, nh=1, w=1., h=5., units=fontsize) axes = fig.add_subplot(1, 1, 1) labelpos(axes, 2.5, 2.0) axes.set_frame_on(False) axes.set_ylim(1., 4.) axes.get_yaxis().set_visible(False) axes.set_title('%s' % target.string_id()) axes.set_xlabel('Time [s]') ii = 0 for source, result in zip(sources, results): if not isinstance(result, WaveformMisfitResult): continue if result.tobs_shift != 0.0: t0 = result.tsyn_pick else: t0 = t0_mean t = result.filtered_obs.get_xdata() ydata = result.filtered_obs.get_ydata() / yabsmax axes.plot( t-t0, ydata*0.40 + 3.5, color='black', lw=1.0) color = plot.mpl_graph_color(ii) t = result.filtered_syn.get_xdata() ydata = result.filtered_syn.get_ydata() ydata = ydata / (num.max(num.abs(ydata)) or 1.0) axes.plot(t-t0, ydata*0.47 + 2.5, color=color, alpha=0.5, lw=1.0) t = result.processed_syn.get_xdata() ydata = result.processed_syn.get_ydata() ydata = ydata / (num.max(num.abs(ydata)) or 1.0) axes.plot(t-t0, ydata*0.47 + 1.5, color=color, alpha=0.5, lw=1.0) if result.tobs_shift != 0.0: axes.axvline( result.tsyn_pick - t0, color=(0.7, 0.7, 0.7), zorder=2) t = result.processed_syn.get_xdata() taper = result.taper y = num.ones(t.size) * 0.9 taper(y, t[0], t[1] - t[0]) y2 = num.concatenate((y, -y[::-1])) t2 = num.concatenate((t, t[::-1])) axes.plot(t2-t0, y2 * 0.47 + 3.5, color=color, alpha=0.2, lw=1.0) ii += 1 return fig
def draw_figures(self, ds, history, optimiser): show_mean_residuals = False # gms = history.get_sorted_primary_misfits()[::-1] models = history.get_sorted_primary_models()[::-1] problem = history.problem targets = [ t for t in problem.targets if isinstance(t, PhasePickTarget) ] # targets.sort(key=lambda t: t.distance_to(problem.base_source)) # tpaths = sorted(set(t.path for t in targets)) ntargets = len(targets) nmodels = history.nmodels tts = num.zeros((nmodels, ntargets, 2)) distances = num.zeros((nmodels, ntargets)) azimuths = num.zeros((nmodels, ntargets)) for imodel in range(nmodels): model = models[imodel, :] source = problem.get_source(model) results = problem.evaluate(model, targets=targets) for itarget, result in enumerate(results): result = results[itarget] tts[imodel, itarget, :] = result.tobs, result.tsyn distances[imodel, itarget] = source.distance_to(targets[itarget]) azimuths[imodel, itarget] = source.azibazi_to(targets[itarget])[0] ok = num.all(num.isfinite(tts), axis=2) ok = num.all(ok, axis=0) targets = [ target for (itarget, target) in enumerate(targets) if ok[itarget] ] tts = tts[:, ok, :] distances = distances[:, ok] azimuths = azimuths[:, ok] residuals = tts[:, :, 0] - tts[:, :, 1] residual_amax = num.max(num.abs(residuals)) mean_residuals = num.mean(residuals, axis=0) mean_distances = num.mean(distances, axis=0) isort = num.array([ x[2] for x in sorted(zip(targets, mean_distances, range(len(targets))), key=lambda x: (x[0].path, x[1])) ], dtype=num.int) distances = distances[:, isort] distance_min = num.min(distances) distance_max = num.max(distances) azimuths = azimuths[:, isort] targets = [targets[i] for i in isort] ntargets = len(targets) residuals = residuals[:, isort] mean_residuals = mean_residuals[isort] icolor = num.arange(nmodels) norm = mcolors.Normalize(vmin=num.min(icolor), vmax=num.max(icolor)) cmap = plt.get_cmap('coolwarm') napprox = max(1, int(round( (self.size_points[1] / self.font_size - 7)))) npages = (ntargets - 1) // napprox + 1 ntargets_page = (ntargets - 1) // npages + 1 for ipage in range(npages): ilo, ihi = ipage * ntargets_page, (ipage + 1) * ntargets_page ihi = min(len(targets), ihi) targets_page = targets[ilo:ihi] item = PlotItem(name='fig_%02i' % ipage) item.attributes['targets'] = [t.string_id() for t in targets_page] fig = plt.figure(figsize=self.size_inch) labelpos = mpl_margins(fig, nw=2, nh=1, left=12., right=1., bottom=5., top=1., wspace=1., units=self.font_size) axes1 = fig.add_subplot(1, 3, 1) axes2 = fig.add_subplot(1, 3, 2) axes3 = fig.add_subplot(1, 3, 3) for axes in (axes1, axes2, axes3): axes.set_ylim(-0.5, len(targets_page) - 0.5) axes.invert_yaxis() labelpos(axes, 2.5, 2.0) axes1.axvline(0.0, color='black') labels = [] lastpath = None for ipos, t in enumerate(targets_page): scodes = '.'.join(t.codes) if lastpath is None or lastpath != t.path: labels.append(t.path + '.' + scodes) if lastpath is not None: for axes in (axes1, axes2, axes3): axes.axhline(ipos - 0.5, color='black') else: labels.append(scodes) lastpath = t.path for ipos, itarget in enumerate(range(ilo, ihi)): axes1.plot(residuals[-1, itarget], ipos, '|', ms=self.font_size, color='black') if show_mean_residuals: axes1.plot(mean_residuals[itarget], ipos, 's', ms=self.font_size, color='none', mec='black') axes1.scatter(residuals[::10, itarget], util.num_full(icolor[::10].size, ipos, dtype=num.float), c=icolor[::10], cmap=cmap, norm=norm, alpha=0.5) axes2.scatter(distances[::10, itarget] / km, util.num_full(icolor[::10].size, ipos, dtype=num.float), c=icolor[::10], cmap=cmap, norm=norm, alpha=0.5) axes3.scatter(azimuths[::10, itarget], util.num_full(icolor[::10].size, ipos, dtype=num.float), c=icolor[::10], cmap=cmap, norm=norm, alpha=0.5) axes1.set_yticks(num.arange(len(labels))) axes1.set_yticklabels(labels) axes1.set_xlabel('$T_{obs} - T_{syn}$ [s]') axes1.set_xlim(-residual_amax, residual_amax) axes2.set_xlabel('Distance [km]') axes2.set_xlim(distance_min / km, distance_max / km) axes3.set_xlabel('Azimuth [deg]') axes3.set_xlim(-180., 180.) axes2.get_yaxis().set_ticks([]) axes2.get_yaxis().set_ticks([]) axes3.get_yaxis().set_ticks([]) axes3.get_yaxis().set_ticks([]) yield item, fig
def plot(responses, filename=None, dpi=100, fmin=0.01, fmax=100., nf=100, fontsize=10., figsize=None, styles=None, labels=None): ''' Draw instrument responses in Bode plot style. :param responses: instrument responses as :py:class:`pyrocko.trace.FrequencyResponse` objects :param fmin: minimum frequency [Hz] :param fmax: maximum frequency [Hz] :param nf: number of frequencies where to evaluate the response :param styles: :py:class:`list` of :py:class:`dict` objects with keyword arguments to be passed to matplotlib's :py:meth:`matplotlib.axes.Axes.plot` function when drawing the response lines. Length must match number of responses. :param filename: file name to pass to matplotlib's ``savefig`` function. If ``None``, the plot is shown with :py:func:`matplotlib.pyplot.show`. :param fontsize: font size in points used in axis labels and legend :param figsize: :py:class:`tuple`, ``(width, height)`` in inches :param labels: :py:class:`list` of names to show in legend. Length must correspond to number of responses. ''' from matplotlib import pyplot as plt from pyrocko.plot import mpl_init, mpl_margins, mpl_papersize from pyrocko.plot import graph_colors, to01 mpl_init(fontsize=fontsize) if figsize is None: figsize = mpl_papersize('a4', 'portrait') fig = plt.figure(figsize=figsize) labelpos = mpl_margins(fig, w=7., h=5., units=fontsize, nw=1, nh=2, hspace=2.) axes_amplitude = fig.add_subplot(2, 1, 1) labelpos(axes_amplitude, 2., 1.5) axes_phase = fig.add_subplot(2, 1, 2) labelpos(axes_phase, 2., 1.5) setup_axes(axes_amplitude, axes_phase) if styles is None: styles = [ dict(color=to01(graph_colors[i % len(graph_colors)])) for i in xrange(len(responses)) ] else: assert len(styles) == len(responses) if labels is None: labels = [None] * len(responses) else: assert len(labels) == len(responses) a_ranges, p_ranges = [], [] for style, resp, label in zip(styles, responses, labels): a_range, p_range = draw(response=resp, axes_amplitude=axes_amplitude, axes_phase=axes_phase, fmin=fmin, fmax=fmax, nf=nf, style=style, label=label) a_ranges.append(a_range) p_ranges.append(p_range) axes_amplitude.legend(loc='lower right', prop=dict(size=fontsize)) a_ranges = num.array(a_ranges) p_ranges = num.array(p_ranges) amin, amax = num.min(a_ranges), num.max(a_ranges) pmin, pmax = num.min(p_ranges), num.max(p_ranges) amin *= 0.5 amax *= 2.0 pmin -= 0.5 pmax += 0.5 axes_amplitude.set_ylim(amin, amax) axes_phase.set_ylim(pmin, pmax) axes_amplitude.set_xlim(fmin, fmax) axes_phase.set_xlim(fmin, fmax) if filename is not None: fig.savefig(filename, dpi=dpi) else: plt.show()
def run_plot(results_path, formats=['png'], min_bin_count=10, mag_step=0.1, nbins_dist=20): config = wconfig.read_config(op.join(results_path, 'config.yaml')) dists = [] mags = [] measures = [] old_event_name = None with open(op.join(results_path, 'measures.txt'), 'r') as f: for line in f: if line.strip().startswith('#'): continue toks = line.split() event_name, station_codes = toks[:2] measures_this = list(map(float, toks[2:])) if event_name != old_event_name: ds = config.get_dataset(event_name) old_event_name = event_name station = ds.get_station(tuple(station_codes.split('.'))) event = ds.get_event() dist = station.distance_to(event) mag = event.magnitude dists.append(dist) mags.append(mag) measures.append(measures_this) dists = num.array(dists, dtype=num.float) mags = num.array(mags, dtype=num.float) measures = num.array(measures, dtype=num.float) from matplotlib import pyplot as plt from pyrocko import plot from scipy.stats import binned_statistic_2d plot.mpl_init() mag_min = num.floor(num.min(mags) / mag_step) * mag_step - mag_step / 2. mag_max = num.ceil(num.max(mags) / mag_step) * mag_step + mag_step / 2. nbins_mag = int(round((mag_max - mag_min) / mag_step)) mag_bins = num.linspace(mag_min, mag_max, nbins_mag + 1) # mag_centers = 0.5*(mag_bins[:-1] + mag_bins[1:]) dist_min = num.min(dists) dist_max = num.max(dists) dist_bins = num.linspace(dist_min, dist_max, nbins_dist + 1) # dist_centers = 0.5*(dist_bins[:-1] + dist_bins[1:]) measure_names = [m.name for m in config.measures] for imeasure, measure_name in enumerate(measure_names): fontsize = 9.0 fig = plt.figure(figsize=plot.mpl_papersize('a5', 'landscape')) labelpos = plot.mpl_margins(fig, w=7, h=5., units=fontsize) axes = fig.add_subplot(1, 1, 1) axes.set_xlabel('Distance [km]') axes.set_ylabel('Magnitude') labelpos(axes, 2., 1.5) fig.suptitle(measure_name) medians, _, _, _ = binned_statistic_2d(dists, mags, measures[:, imeasure], statistic='median', bins=[dist_bins, mag_bins]) counts, _, _, _ = binned_statistic_2d(dists, mags, measures[:, imeasure], statistic='count', bins=[dist_bins, mag_bins]) medians[counts < min_bin_count] = None medians = num.log10(medians) im = axes.pcolorfast(dist_bins / km, mag_bins, medians.T, vmin=num.nanmin(medians), vmax=num.nanmax(medians), cmap='YlOrBr') fig.colorbar(im).set_label('$log_{10}$ measure') for fmt in formats: plot_path = op.join(results_path, 'plots', 'dist_mag_median_%s.%s' % (measure_name, fmt)) util.ensuredirs(plot_path) fig.savefig(plot_path) logger.info('plot saved: %s' % plot_path)