def draw_figures(self, ds, history, optimiser): fontsize = self.font_size fontsize_title = self.font_size_title nxmax = self.nx nymax = self.ny problem = history.problem for target in problem.targets: target.set_dataset(ds) target_index = {} i = 0 for target in problem.targets: target_index[target] = i, i+target.nmisfits i += target.nmisfits xbest = history.get_best_model() misfits = history.misfits[history.get_sorted_misfits_idx(chain=0), ...] ws = problem.get_target_weights() gcms = problem.combine_misfits( misfits[:1, :, :], extra_correlated_weights=optimiser.get_correlated_weights(problem), get_contributions=True)[0, :] w_max = num.nanmax(ws) gcm_max = num.nanmax(gcms) source = problem.get_source(xbest) target_to_result = {} all_syn_trs = [] all_syn_specs = [] results = problem.evaluate(xbest) dtraces = [] for target, result in zip(problem.targets, results): if not isinstance(result, WaveformMisfitResult): dtraces.extend([None] * target.nmisfits) continue itarget, itarget_end = target_index[target] assert itarget_end == itarget + 1 w = target.get_combined_weight() if target.misfit_config.domain == 'cc_max_norm': tref = ( result.filtered_obs.tmin + result.filtered_obs.tmax) * 0.5 for tr_filt, tr_proc, tshift in ( (result.filtered_obs, result.processed_obs, 0.), (result.filtered_syn, result.processed_syn, result.tshift)): norm = num.sum(num.abs(tr_proc.ydata)) / tr_proc.data_len() tr_filt.ydata /= norm tr_proc.ydata /= norm tr_filt.shift(tshift) tr_proc.shift(tshift) ctr = result.cc ctr.shift(tref) dtrace = ctr else: for tr in ( result.filtered_obs, result.filtered_syn, result.processed_obs, result.processed_syn): tr.ydata *= w for spec in ( result.spectrum_obs, result.spectrum_syn): if spec is not None: spec.ydata *= w if result.tshift is not None and result.tshift != 0.0: # result.filtered_syn.shift(result.tshift) result.processed_syn.shift(result.tshift) dtrace = make_norm_trace( result.processed_syn, result.processed_obs, problem.norm_exponent) target_to_result[target] = result dtrace.meta = dict( normalisation_family=target.normalisation_family, path=target.path) dtraces.append(dtrace) result.processed_syn.meta = dict( normalisation_family=target.normalisation_family, path=target.path) all_syn_trs.append(result.processed_syn) if result.spectrum_syn: result.spectrum_syn.meta = dict( normalisation_family=target.normalisation_family, path=target.path) all_syn_specs.append(result.spectrum_syn) if not all_syn_trs: logger.warn('No traces to show!') return def skey(tr): return tr.meta['normalisation_family'], tr.meta['path'] trace_minmaxs = trace.minmax(all_syn_trs, skey) amp_spec_maxs = amp_spec_max(all_syn_specs, skey) dminmaxs = trace.minmax([x for x in dtraces if x is not None], skey) for tr in dtraces: if tr: dmin, dmax = dminmaxs[skey(tr)] tr.ydata /= max(abs(dmin), abs(dmax)) cg_to_targets = meta.gather( problem.waveform_targets, lambda t: (t.path, t.codes[3]), filter=lambda t: t in target_to_result) cgs = sorted(cg_to_targets.keys()) for cg in cgs: targets = cg_to_targets[cg] frame_to_target, nx, ny, nxx, nyy = layout( source, targets, nxmax, nymax) figures = {} for iy in range(ny): for ix in range(nx): if (iy, ix) not in frame_to_target: continue ixx = ix // nxmax iyy = iy // nymax if (iyy, ixx) not in figures: title = '_'.join(x for x in cg if x) item = PlotItem( name='fig_%s_%i_%i' % (title, ixx, iyy)) item.attributes['targets'] = [] figures[iyy, ixx] = ( item, plt.figure(figsize=self.size_inch)) figures[iyy, ixx][1].subplots_adjust( left=0.03, right=1.0 - 0.03, bottom=0.03, top=1.0 - 0.06, wspace=0.2, hspace=0.2) item, fig = figures[iyy, ixx] target = frame_to_target[iy, ix] item.attributes['targets'].append(target.string_id()) amin, amax = trace_minmaxs[ target.normalisation_family, target.path] absmax = max(abs(amin), abs(amax)) ny_this = nymax # min(ny, nymax) nx_this = nxmax # min(nx, nxmax) i_this = (iy % ny_this) * nx_this + (ix % nx_this) + 1 axes2 = fig.add_subplot(ny_this, nx_this, i_this) space = 0.5 space_factor = 1.0 + space axes2.set_axis_off() axes2.set_ylim(-1.05 * space_factor, 1.05) axes = axes2.twinx() axes.set_axis_off() if target.misfit_config.domain == 'cc_max_norm': axes.set_ylim(-10. * space_factor, 10.) else: axes.set_ylim( -absmax * 1.33 * space_factor, absmax * 1.33) itarget, itarget_end = target_index[target] assert itarget_end == itarget + 1 result = target_to_result[target] dtrace = dtraces[itarget] tap_color_annot = (0.35, 0.35, 0.25) tap_color_edge = (0.85, 0.85, 0.80) tap_color_fill = (0.95, 0.95, 0.90) plot_taper( axes2, result.processed_obs.get_xdata(), result.taper, fc=tap_color_fill, ec=tap_color_edge) obs_color = mpl_color('aluminium5') obs_color_light = light(obs_color, 0.5) syn_color = mpl_color('scarletred2') syn_color_light = light(syn_color, 0.5) misfit_color = mpl_color('scarletred2') weight_color = mpl_color('chocolate2') cc_color = mpl_color('aluminium5') if target.misfit_config.domain == 'cc_max_norm': tref = (result.filtered_obs.tmin + result.filtered_obs.tmax) * 0.5 plot_dtrace( axes2, dtrace, space, -1., 1., fc=light(cc_color, 0.5), ec=cc_color) plot_dtrace_vline( axes2, tref, space, color=tap_color_annot) elif target.misfit_config.domain == 'frequency_domain': asmax = amp_spec_maxs[ target.normalisation_family, target.path] fmin, fmax = \ target.misfit_config.get_full_frequency_range() plot_spectrum( axes2, result.spectrum_syn, result.spectrum_obs, fmin, fmax, space, 0., asmax, syn_color=syn_color, obs_color=obs_color, syn_lw=1.0, obs_lw=0.75, color_vline=tap_color_annot, fontsize=fontsize) else: plot_dtrace( axes2, dtrace, space, 0., 1., fc=light(misfit_color, 0.3), ec=misfit_color) plot_trace( axes, result.filtered_syn, color=syn_color_light, lw=1.0) plot_trace( axes, result.filtered_obs, color=obs_color_light, lw=0.75) plot_trace( axes, result.processed_syn, color=syn_color, lw=1.0) plot_trace( axes, result.processed_obs, color=obs_color, lw=0.75) # xdata = result.filtered_obs.get_xdata() tmarks = [ result.processed_obs.tmin, result.processed_obs.tmax] for tmark in tmarks: axes2.plot( [tmark, tmark], [-0.9, 0.1], color=tap_color_annot) dur = tmarks[1] - tmarks[0] for tmark, text, ha in [ (tmarks[0], '$\\,$ ' + meta.str_duration( tmarks[0] - source.time), 'left'), (tmarks[1], '$\\Delta$ ' + meta.str_duration(dur), 'right')]: axes2.annotate( text, xy=(tmark, -0.9), xycoords='data', xytext=( fontsize * 0.4 * [-1, 1][ha == 'left'], fontsize * 0.2), textcoords='offset points', ha=ha, va='bottom', color=tap_color_annot, fontsize=fontsize) axes2.set_xlim(tmarks[0] - dur*0.1, tmarks[1] + dur*0.1) rel_w = ws[itarget] / w_max rel_c = gcms[itarget] / gcm_max sw = 0.25 sh = 0.1 ph = 0.01 for (ih, rw, facecolor, edgecolor) in [ (0, rel_w, light(weight_color, 0.5), weight_color), (1, rel_c, light(misfit_color, 0.5), misfit_color)]: bar = patches.Rectangle( (1.0 - rw * sw, 1.0 - (ih + 1) * sh + ph), rw * sw, sh - 2 * ph, facecolor=facecolor, edgecolor=edgecolor, zorder=10, transform=axes.transAxes, clip_on=False) axes.add_patch(bar) scale_string = None if target.misfit_config.domain == 'cc_max_norm': scale_string = 'Syn/obs scales differ!' infos = [] if scale_string: infos.append(scale_string) if self.nx == 1 and self.ny == 1: infos.append(target.string_id()) else: infos.append('.'.join(x for x in target.codes if x)) dist = source.distance_to(target) azi = source.azibazi_to(target)[0] infos.append(meta.str_dist(dist)) infos.append('%.0f\u00B0' % azi) infos.append('%.3g' % ws[itarget]) infos.append('%.3g' % gcms[itarget]) axes2.annotate( '\n'.join(infos), xy=(0., 1.), xycoords='axes fraction', xytext=(2., 2.), textcoords='offset points', ha='left', va='top', fontsize=fontsize, fontstyle='normal') if (self.nx == 1 and self.ny == 1): yield item, fig del figures[iyy, ixx] if not (self.nx == 1 and self.ny == 1): for (iyy, ixx), (_, fig) in figures.items(): title = '.'.join(x for x in cg if x) if len(figures) > 1: title += ' (%i/%i, %i/%i)' % ( iyy + 1, nyy, ixx + 1, nxx) fig.suptitle(title, fontsize=fontsize_title) for item, fig in figures.values(): yield item, fig
def draw_figures(self, ds, history): fontsize = self.font_size fontsize_title = self.font_size_title problem = history.problem for target in problem.targets: target.set_dataset(ds) target_index = dict( (target, i) for (i, target) in enumerate(problem.targets)) gms = problem.combine_misfits(history.misfits) isort = num.argsort(gms) gms = gms[isort] models = history.models[isort, :] misfits = history.misfits[isort, :] xbest = models[0, :] ws = problem.get_target_weights() gcms = problem.combine_misfits(misfits[:1, :, :], get_contributions=True)[0, :] w_max = num.nanmax(ws) gcm_max = num.nanmax(gcms) source = problem.get_source(xbest) target_to_result = {} all_syn_trs = [] all_syn_specs = [] results = problem.evaluate(xbest) dtraces = [] for target, result in zip(problem.targets, results): if not isinstance(result, WaveformMisfitResult): dtraces.append(None) continue itarget = target_index[target] w = target.get_combined_weight() if target.misfit_config.domain == 'cc_max_norm': tref = (result.filtered_obs.tmin + result.filtered_obs.tmax) * 0.5 for tr_filt, tr_proc, tshift in ((result.filtered_obs, result.processed_obs, 0.), (result.filtered_syn, result.processed_syn, result.tshift)): norm = num.sum(num.abs(tr_proc.ydata)) / tr_proc.data_len() tr_filt.ydata /= norm tr_proc.ydata /= norm tr_filt.shift(tshift) tr_proc.shift(tshift) ctr = result.cc ctr.shift(tref) dtrace = ctr else: for tr in (result.filtered_obs, result.filtered_syn, result.processed_obs, result.processed_syn): tr.ydata *= w for spec in (result.spectrum_obs, result.spectrum_syn): if spec is not None: spec.ydata *= w if result.tshift is not None and result.tshift != 0.0: # result.filtered_syn.shift(result.tshift) result.processed_syn.shift(result.tshift) dtrace = make_norm_trace(result.processed_syn, result.processed_obs, problem.norm_exponent) target_to_result[target] = result dtrace.meta = dict( normalisation_family=target.normalisation_family, path=target.path) dtraces.append(dtrace) result.processed_syn.meta = dict( normalisation_family=target.normalisation_family, path=target.path) all_syn_trs.append(result.processed_syn) if result.spectrum_syn: result.spectrum_syn.meta = dict( normalisation_family=target.normalisation_family, path=target.path) all_syn_specs.append(result.spectrum_syn) if not all_syn_trs: logger.warn('no traces to show') return [] def skey(tr): return tr.meta['normalisation_family'], tr.meta['path'] trace_minmaxs = trace.minmax(all_syn_trs, skey) amp_spec_maxs = amp_spec_max(all_syn_specs, skey) dminmaxs = trace.minmax([x for x in dtraces if x is not None], skey) for tr in dtraces: if tr: dmin, dmax = dminmaxs[skey(tr)] tr.ydata /= max(abs(dmin), abs(dmax)) cg_to_targets = meta.gather(problem.waveform_targets, lambda t: (t.path, t.codes[3]), filter=lambda t: t in target_to_result) cgs = sorted(cg_to_targets.keys()) figs = [] for cg in cgs: targets = cg_to_targets[cg] nframes = len(targets) nx = int(math.ceil(math.sqrt(nframes))) ny = (nframes - 1) // nx + 1 nxmax = 4 nymax = 4 nxx = (nx - 1) // nxmax + 1 nyy = (ny - 1) // nymax + 1 # nz = nxx * nyy xs = num.arange(nx) // ((max(2, nx) - 1.0) / 2.) ys = num.arange(ny) // ((max(2, ny) - 1.0) / 2.) xs -= num.mean(xs) ys -= num.mean(ys) fxs = num.tile(xs, ny) fys = num.repeat(ys, nx) data = [] for target in targets: azi = source.azibazi_to(target)[0] dist = source.distance_to(target) x = dist * num.sin(num.deg2rad(azi)) y = dist * num.cos(num.deg2rad(azi)) data.append((x, y, dist)) gxs, gys, dists = num.array(data, dtype=num.float).T iorder = num.argsort(dists) gxs = gxs[iorder] gys = gys[iorder] targets_sorted = [targets[ii] for ii in iorder] gxs -= num.mean(gxs) gys -= num.mean(gys) gmax = max(num.max(num.abs(gys)), num.max(num.abs(gxs))) if gmax == 0.: gmax = 1. gxs /= gmax gys /= gmax dists = num.sqrt((fxs[num.newaxis, :] - gxs[:, num.newaxis])**2 + (fys[num.newaxis, :] - gys[:, num.newaxis])**2) distmax = num.max(dists) availmask = num.ones(dists.shape[1], dtype=num.bool) frame_to_target = {} for itarget, target in enumerate(targets_sorted): iframe = num.argmin( num.where(availmask, dists[itarget], distmax + 1.)) availmask[iframe] = False iy, ix = num.unravel_index(iframe, (ny, nx)) frame_to_target[iy, ix] = target figures = {} for iy in range(ny): for ix in range(nx): if (iy, ix) not in frame_to_target: continue ixx = ix // nxmax iyy = iy // nymax if (iyy, ixx) not in figures: title = '_'.join(x for x in cg if x) item = PlotItem(name='fig_%s_%i_%i' % (title, ixx, iyy)) item.attributes['targets'] = [] figures[iyy, ixx] = (item, plt.figure(figsize=self.size_inch)) figures[iyy, ixx][1].subplots_adjust(left=0.03, right=1.0 - 0.03, bottom=0.03, top=1.0 - 0.06, wspace=0.2, hspace=0.2) figs.append(figures[iyy, ixx]) item, fig = figures[iyy, ixx] target = frame_to_target[iy, ix] item.attributes['targets'].append(target.string_id()) amin, amax = trace_minmaxs[target.normalisation_family, target.path] absmax = max(abs(amin), abs(amax)) ny_this = nymax # min(ny, nymax) nx_this = nxmax # min(nx, nxmax) i_this = (iy % ny_this) * nx_this + (ix % nx_this) + 1 axes2 = fig.add_subplot(ny_this, nx_this, i_this) space = 0.5 space_factor = 1.0 + space axes2.set_axis_off() axes2.set_ylim(-1.05 * space_factor, 1.05) axes = axes2.twinx() axes.set_axis_off() if target.misfit_config.domain == 'cc_max_norm': axes.set_ylim(-10. * space_factor, 10.) else: axes.set_ylim(-absmax * 1.33 * space_factor, absmax * 1.33) itarget = target_index[target] result = target_to_result[target] dtrace = dtraces[itarget] tap_color_annot = (0.35, 0.35, 0.25) tap_color_edge = (0.85, 0.85, 0.80) tap_color_fill = (0.95, 0.95, 0.90) plot_taper(axes2, result.processed_obs.get_xdata(), result.taper, fc=tap_color_fill, ec=tap_color_edge) obs_color = mpl_color('aluminium5') obs_color_light = light(obs_color, 0.5) syn_color = mpl_color('scarletred2') syn_color_light = light(syn_color, 0.5) misfit_color = mpl_color('scarletred2') weight_color = mpl_color('chocolate2') cc_color = mpl_color('aluminium5') if target.misfit_config.domain == 'cc_max_norm': tref = (result.filtered_obs.tmin + result.filtered_obs.tmax) * 0.5 plot_dtrace(axes2, dtrace, space, -1., 1., fc=light(cc_color, 0.5), ec=cc_color) plot_dtrace_vline(axes2, tref, space, color=tap_color_annot) elif target.misfit_config.domain == 'frequency_domain': asmax = amp_spec_maxs[target.normalisation_family, target.path] fmin, fmax = \ target.misfit_config.get_full_frequency_range() plot_spectrum(axes2, result.spectrum_syn, result.spectrum_obs, fmin, fmax, space, 0., asmax, syn_color=syn_color, obs_color=obs_color, syn_lw=1.0, obs_lw=0.75, color_vline=tap_color_annot, fontsize=fontsize) else: plot_dtrace(axes2, dtrace, space, 0., 1., fc=light(misfit_color, 0.3), ec=misfit_color) plot_trace(axes, result.filtered_syn, color=syn_color_light, lw=1.0) plot_trace(axes, result.filtered_obs, color=obs_color_light, lw=0.75) plot_trace(axes, result.processed_syn, color=syn_color, lw=1.0) plot_trace(axes, result.processed_obs, color=obs_color, lw=0.75) xdata = result.filtered_obs.get_xdata() axes.set_xlim(xdata[0], xdata[-1]) tmarks = [ result.processed_obs.tmin, result.processed_obs.tmax ] for tmark in tmarks: axes2.plot([tmark, tmark], [-0.9, 0.1], color=tap_color_annot) for tmark, text, ha in [ (tmarks[0], '$\\,$ ' + meta.str_duration(tmarks[0] - source.time), 'right'), (tmarks[1], '$\\Delta$ ' + meta.str_duration(tmarks[1] - tmarks[0]), 'left') ]: axes2.annotate( text, xy=(tmark, -0.9), xycoords='data', xytext=(fontsize * 0.4 * [-1, 1][ha == 'left'], fontsize * 0.2), textcoords='offset points', ha=ha, va='bottom', color=tap_color_annot, fontsize=fontsize) rel_w = ws[itarget] / w_max rel_c = gcms[itarget] / gcm_max sw = 0.25 sh = 0.1 ph = 0.01 for (ih, rw, facecolor, edgecolor) in [ (0, rel_w, light(weight_color, 0.5), weight_color), (1, rel_c, light(misfit_color, 0.5), misfit_color) ]: bar = patches.Rectangle( (1.0 - rw * sw, 1.0 - (ih + 1) * sh + ph), rw * sw, sh - 2 * ph, facecolor=facecolor, edgecolor=edgecolor, zorder=10, transform=axes.transAxes, clip_on=False) axes.add_patch(bar) scale_string = None if target.misfit_config.domain == 'cc_max_norm': scale_string = 'Syn/obs scales differ!' infos = [] if scale_string: infos.append(scale_string) infos.append('.'.join(x for x in target.codes if x)) dist = source.distance_to(target) azi = source.azibazi_to(target)[0] infos.append(meta.str_dist(dist)) infos.append('%.0f\u00B0' % azi) infos.append('%.3g' % ws[itarget]) infos.append('%.3g' % gcms[itarget]) axes2.annotate('\n'.join(infos), xy=(0., 1.), xycoords='axes fraction', xytext=(2., 2.), textcoords='offset points', ha='left', va='top', fontsize=fontsize, fontstyle='normal') for (iyy, ixx), (_, fig) in figures.items(): title = '.'.join(x for x in cg if x) if len(figures) > 1: title += ' (%i/%i, %i/%i)' % (iyy + 1, nyy, ixx + 1, nxx) fig.suptitle(title, fontsize=fontsize_title) return figs
def draw_figures(self, ds, history, optimiser): color_parameter = self.color_parameter misfit_cutoff = self.misfit_cutoff fontsize = self.font_size fontsize_title = self.font_size_title nxmax = self.nx nymax = self.ny problem = history.problem for target in problem.targets: target.set_dataset(ds) target_index = {} i = 0 for target in problem.targets: target_index[target] = i, i+target.nmisfits i += target.nmisfits gms = history.get_sorted_primary_misfits()[::-1] models = history.get_sorted_primary_models()[::-1] if misfit_cutoff is not None: ibest = gms < misfit_cutoff gms = gms[ibest] models = models[ibest] gms = gms[::10] models = models[::10] nmodels = models.shape[0] if color_parameter == 'dist': mx = num.mean(models, axis=0) cov = num.cov(models.T) mdists = core.mahalanobis_distance(models, mx, cov) icolor = meta.ordersort(mdists) elif color_parameter == 'misfit': iorder = num.arange(nmodels) icolor = iorder elif color_parameter in problem.parameter_names: ind = problem.name_to_index(color_parameter) icolor = problem.extract(models, ind) target_to_results = defaultdict(list) all_syn_trs = [] dtraces = [] for imodel in range(nmodels): model = models[imodel, :] source = problem.get_source(model) results = problem.evaluate(model) dtraces.append([]) for target, result in zip(problem.targets, results): w = target.get_combined_weight() if isinstance(result, gf.SeismosizerError) or \ not isinstance(target, WaveformMisfitTarget) or \ not num.all(num.isfinite(w)): dtraces[-1].extend([None] * target.nmisfits) continue itarget, itarget_end = target_index[target] assert itarget_end == itarget + 1 if target.misfit_config.domain == 'cc_max_norm': tref = ( result.filtered_obs.tmin + result.filtered_obs.tmax) \ * 0.5 for tr_filt, tr_proc, tshift in ( (result.filtered_obs, result.processed_obs, 0.), (result.filtered_syn, result.processed_syn, result.tshift)): norm = num.sum(num.abs(tr_proc.ydata)) \ / tr_proc.data_len() tr_filt.ydata /= norm tr_proc.ydata /= norm tr_filt.shift(tshift) tr_proc.shift(tshift) ctr = result.cc ctr.shift(tref) dtrace = ctr else: for tr in ( result.filtered_obs, result.filtered_syn, result.processed_obs, result.processed_syn): tr.ydata *= w if result.tshift is not None and result.tshift != 0.0: # result.filtered_syn.shift(result.tshift) result.processed_syn.shift(result.tshift) dtrace = make_norm_trace( result.processed_syn, result.processed_obs, problem.norm_exponent) target_to_results[target].append(result) dtrace.meta = dict( normalisation_family=target.normalisation_family, path=target.path) dtraces[-1].append(dtrace) result.processed_syn.meta = dict( normalisation_family=target.normalisation_family, path=target.path) all_syn_trs.append(result.processed_syn) if not all_syn_trs: logger.warn('No traces to show!') return def skey(tr): return tr.meta['normalisation_family'], tr.meta['path'] trace_minmaxs = trace.minmax(all_syn_trs, skey) dtraces_all = [] for dtraces_group in dtraces: dtraces_all.extend(dtraces_group) dminmaxs = trace.minmax([ dtrace_ for dtrace_ in dtraces_all if dtrace_ is not None], skey) for tr in dtraces_all: if tr: dmin, dmax = dminmaxs[skey(tr)] tr.ydata /= max(abs(dmin), abs(dmax)) cg_to_targets = meta.gather( problem.waveform_targets, lambda t: (t.path, t.codes[3]), filter=lambda t: t in target_to_results) cgs = sorted(cg_to_targets.keys()) from matplotlib import colors cmap = cm.ScalarMappable( norm=colors.Normalize(vmin=num.min(icolor), vmax=num.max(icolor)), cmap=plt.get_cmap('coolwarm')) imodel_to_color = [] for imodel in range(nmodels): imodel_to_color.append(cmap.to_rgba(icolor[imodel])) for cg in cgs: targets = cg_to_targets[cg] frame_to_target, nx, ny, nxx, nyy = layout( source, targets, nxmax, nymax) figures = {} for iy in range(ny): for ix in range(nx): if (iy, ix) not in frame_to_target: continue ixx = ix // nxmax iyy = iy // nymax if (iyy, ixx) not in figures: title = '_'.join(x for x in cg if x) item = PlotItem( name='fig_%s_%i_%i' % (title, ixx, iyy)) item.attributes['targets'] = [] figures[iyy, ixx] = ( item, plt.figure(figsize=self.size_inch)) figures[iyy, ixx][1].subplots_adjust( left=0.03, right=1.0 - 0.03, bottom=0.03, top=1.0 - 0.06, wspace=0.2, hspace=0.2) item, fig = figures[iyy, ixx] target = frame_to_target[iy, ix] item.attributes['targets'].append(target.string_id()) amin, amax = trace_minmaxs[ target.normalisation_family, target.path] absmax = max(abs(amin), abs(amax)) ny_this = nymax # min(ny, nymax) nx_this = nxmax # min(nx, nxmax) i_this = (iy % ny_this) * nx_this + (ix % nx_this) + 1 axes2 = fig.add_subplot(ny_this, nx_this, i_this) space = 0.5 space_factor = 1.0 + space axes2.set_axis_off() axes2.set_ylim(-1.05 * space_factor, 1.05) axes = axes2.twinx() axes.set_axis_off() if target.misfit_config.domain == 'cc_max_norm': axes.set_ylim(-10. * space_factor, 10.) else: axes.set_ylim(-absmax*1.33 * space_factor, absmax*1.33) itarget, itarget_end = target_index[target] assert itarget_end == itarget + 1 for imodel, result in enumerate(target_to_results[target]): syn_color = imodel_to_color[imodel] dtrace = dtraces[imodel][itarget] tap_color_annot = (0.35, 0.35, 0.25) tap_color_edge = (0.85, 0.85, 0.80) tap_color_fill = (0.95, 0.95, 0.90) plot_taper( axes2, result.processed_obs.get_xdata(), result.taper, fc=tap_color_fill, ec=tap_color_edge, alpha=0.2) obs_color = mpl_color('aluminium5') obs_color_light = light(obs_color, 0.5) plot_dtrace( axes2, dtrace, space, 0., 1., fc='none', ec=syn_color) # plot_trace( # axes, result.filtered_syn, # color=syn_color_light, lw=1.0) if imodel == 0: plot_trace( axes, result.filtered_obs, color=obs_color_light, lw=0.75) plot_trace( axes, result.processed_syn, color=syn_color, lw=1.0, alpha=0.3) plot_trace( axes, result.processed_obs, color=obs_color, lw=0.75, alpha=0.3) if imodel != 0: continue xdata = result.filtered_obs.get_xdata() axes.set_xlim(xdata[0], xdata[-1]) tmarks = [ result.processed_obs.tmin, result.processed_obs.tmax] for tmark in tmarks: axes2.plot( [tmark, tmark], [-0.9, 0.1], color=tap_color_annot) dur = tmarks[1] - tmarks[0] for tmark, text, ha in [ (tmarks[0], '$\\,$ ' + meta.str_duration( tmarks[0] - source.time), 'left'), (tmarks[1], '$\\Delta$ ' + meta.str_duration( dur), 'right')]: axes2.annotate( text, xy=(tmark, -0.9), xycoords='data', xytext=( fontsize*0.4 * [-1, 1][ha == 'left'], fontsize*0.2), textcoords='offset points', ha=ha, va='bottom', color=tap_color_annot, fontsize=fontsize) axes2.set_xlim( tmarks[0] - dur*0.1, tmarks[1] + dur*0.1) scale_string = None if target.misfit_config.domain == 'cc_max_norm': scale_string = 'Syn/obs scales differ!' infos = [] if scale_string: infos.append(scale_string) if self.nx == 1 and self.ny == 1: infos.append(target.string_id()) else: infos.append('.'.join(x for x in target.codes if x)) dist = source.distance_to(target) azi = source.azibazi_to(target)[0] infos.append(meta.str_dist(dist)) infos.append(u'%.0f\u00B0' % azi) axes2.annotate( '\n'.join(infos), xy=(0., 1.), xycoords='axes fraction', xytext=(2., 2.), textcoords='offset points', ha='left', va='top', fontsize=fontsize, fontstyle='normal') if (self.nx == 1 and self.ny == 1): yield item, fig del figures[iyy, ixx] if not (self.nx == 1 and self.ny == 1): for (iyy, ixx), (_, fig) in figures.items(): title = '.'.join(x for x in cg if x) if len(figures) > 1: title += ' (%i/%i, %i/%i)' % (iyy+1, nyy, ixx+1, nxx) fig.suptitle(title, fontsize=fontsize_title) for item, fig in figures.values(): yield item, fig
def draw_figures(self, ds, history): color_parameter = self.color_parameter misfit_cutoff = self.misfit_cutoff fontsize = self.font_size fontsize_title = self.font_size_title problem = history.problem for target in problem.targets: target.set_dataset(ds) target_index = dict( (target, i) for (i, target) in enumerate(problem.targets)) gms = problem.combine_misfits(history.misfits) isort = num.argsort(gms)[::-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[::10] models = models[::10] nmodels = models.shape[0] if color_parameter == 'dist': mx = num.mean(models, axis=0) cov = num.cov(models.T) mdists = core.mahalanobis_distance(models, mx, cov) icolor = meta.ordersort(mdists) elif color_parameter == 'misfit': iorder = num.arange(nmodels) icolor = iorder elif color_parameter in problem.parameter_names: ind = problem.name_to_index(color_parameter) icolor = problem.extract(models, ind) target_to_results = defaultdict(list) all_syn_trs = [] dtraces = [] for imodel in range(nmodels): model = models[imodel, :] source = problem.get_source(model) results = problem.evaluate(model) dtraces.append([]) for target, result in zip(problem.targets, results): if isinstance(result, gf.SeismosizerError): dtraces[-1].append(None) continue if not isinstance(target, WaveformMisfitTarget): dtraces[-1].append(None) continue itarget = target_index[target] w = target.get_combined_weight() if target.misfit_config.domain == 'cc_max_norm': tref = ( result.filtered_obs.tmin + result.filtered_obs.tmax) \ * 0.5 for tr_filt, tr_proc, tshift in ((result.filtered_obs, result.processed_obs, 0.), (result.filtered_syn, result.processed_syn, result.tshift)): norm = num.sum(num.abs(tr_proc.ydata)) \ / tr_proc.data_len() tr_filt.ydata /= norm tr_proc.ydata /= norm tr_filt.shift(tshift) tr_proc.shift(tshift) ctr = result.cc ctr.shift(tref) dtrace = ctr else: for tr in (result.filtered_obs, result.filtered_syn, result.processed_obs, result.processed_syn): tr.ydata *= w if result.tshift is not None and result.tshift != 0.0: # result.filtered_syn.shift(result.tshift) result.processed_syn.shift(result.tshift) dtrace = make_norm_trace(result.processed_syn, result.processed_obs, problem.norm_exponent) target_to_results[target].append(result) dtrace.meta = dict( normalisation_family=target.normalisation_family, path=target.path) dtraces[-1].append(dtrace) result.processed_syn.meta = dict( normalisation_family=target.normalisation_family, path=target.path) all_syn_trs.append(result.processed_syn) if not all_syn_trs: logger.warn('no traces to show') return [] def skey(tr): return tr.meta['normalisation_family'], tr.meta['path'] trace_minmaxs = trace.minmax(all_syn_trs, skey) dtraces_all = [] for dtraces_group in dtraces: dtraces_all.extend(dtraces_group) dminmaxs = trace.minmax( [dtrace_ for dtrace_ in dtraces_all if dtrace_ is not None], skey) for tr in dtraces_all: if tr: dmin, dmax = dminmaxs[skey(tr)] tr.ydata /= max(abs(dmin), abs(dmax)) cg_to_targets = meta.gather(problem.waveform_targets, lambda t: (t.path, t.codes[3]), filter=lambda t: t in target_to_results) cgs = sorted(cg_to_targets.keys()) from matplotlib import colors cmap = cm.ScalarMappable(norm=colors.Normalize(vmin=num.min(icolor), vmax=num.max(icolor)), cmap=plt.get_cmap('coolwarm')) imodel_to_color = [] for imodel in range(nmodels): imodel_to_color.append(cmap.to_rgba(icolor[imodel])) figs = [] for cg in cgs: targets = cg_to_targets[cg] nframes = len(targets) nx = int(math.ceil(math.sqrt(nframes))) ny = (nframes - 1) // nx + 1 nxmax = 4 nymax = 4 nxx = (nx - 1) // nxmax + 1 nyy = (ny - 1) // nymax + 1 # nz = nxx * nyy xs = num.arange(nx) / ((max(2, nx) - 1.0) / 2.) ys = num.arange(ny) / ((max(2, ny) - 1.0) / 2.) xs -= num.mean(xs) ys -= num.mean(ys) fxs = num.tile(xs, ny) fys = num.repeat(ys, nx) data = [] for target in targets: azi = source.azibazi_to(target)[0] dist = source.distance_to(target) x = dist * num.sin(num.deg2rad(azi)) y = dist * num.cos(num.deg2rad(azi)) data.append((x, y, dist)) gxs, gys, dists = num.array(data, dtype=num.float).T iorder = num.argsort(dists) gxs = gxs[iorder] gys = gys[iorder] targets_sorted = [targets[ii] for ii in iorder] gxs -= num.mean(gxs) gys -= num.mean(gys) gmax = max(num.max(num.abs(gys)), num.max(num.abs(gxs))) if gmax == 0.: gmax = 1. gxs /= gmax gys /= gmax dists = num.sqrt((fxs[num.newaxis, :] - gxs[:, num.newaxis])**2 + (fys[num.newaxis, :] - gys[:, num.newaxis])**2) distmax = num.max(dists) availmask = num.ones(dists.shape[1], dtype=num.bool) frame_to_target = {} for itarget, target in enumerate(targets_sorted): iframe = num.argmin( num.where(availmask, dists[itarget], distmax + 1.)) availmask[iframe] = False iy, ix = num.unravel_index(iframe, (ny, nx)) frame_to_target[iy, ix] = target figures = {} for iy in range(ny): for ix in range(nx): if (iy, ix) not in frame_to_target: continue ixx = ix // nxmax iyy = iy // nymax if (iyy, ixx) not in figures: title = '_'.join(x for x in cg if x) item = PlotItem(name='fig_%s_%i_%i' % (title, ixx, iyy)) item.attributes['targets'] = [] figures[iyy, ixx] = (item, plt.figure(figsize=self.size_inch)) figures[iyy, ixx][1].subplots_adjust(left=0.03, right=1.0 - 0.03, bottom=0.03, top=1.0 - 0.06, wspace=0.2, hspace=0.2) figs.append(figures[iyy, ixx]) item, fig = figures[iyy, ixx] target = frame_to_target[iy, ix] item.attributes['targets'].append(target.string_id()) amin, amax = trace_minmaxs[target.normalisation_family, target.path] absmax = max(abs(amin), abs(amax)) ny_this = nymax # min(ny, nymax) nx_this = nxmax # min(nx, nxmax) i_this = (iy % ny_this) * nx_this + (ix % nx_this) + 1 axes2 = fig.add_subplot(ny_this, nx_this, i_this) space = 0.5 space_factor = 1.0 + space axes2.set_axis_off() axes2.set_ylim(-1.05 * space_factor, 1.05) axes = axes2.twinx() axes.set_axis_off() if target.misfit_config.domain == 'cc_max_norm': axes.set_ylim(-10. * space_factor, 10.) else: axes.set_ylim(-absmax * 1.33 * space_factor, absmax * 1.33) itarget = target_index[target] for imodel, result in enumerate(target_to_results[target]): syn_color = imodel_to_color[imodel] dtrace = dtraces[imodel][itarget] tap_color_annot = (0.35, 0.35, 0.25) tap_color_edge = (0.85, 0.85, 0.80) tap_color_fill = (0.95, 0.95, 0.90) plot_taper(axes2, result.processed_obs.get_xdata(), result.taper, fc=tap_color_fill, ec=tap_color_edge, alpha=0.2) obs_color = mpl_color('aluminium5') obs_color_light = light(obs_color, 0.5) plot_dtrace(axes2, dtrace, space, 0., 1., fc='none', ec=syn_color) # plot_trace( # axes, result.filtered_syn, # color=syn_color_light, lw=1.0) if imodel == 0: plot_trace(axes, result.filtered_obs, color=obs_color_light, lw=0.75) plot_trace(axes, result.processed_syn, color=syn_color, lw=1.0, alpha=0.3) plot_trace(axes, result.processed_obs, color=obs_color, lw=0.75, alpha=0.3) if imodel != 0: continue xdata = result.filtered_obs.get_xdata() axes.set_xlim(xdata[0], xdata[-1]) tmarks = [ result.processed_obs.tmin, result.processed_obs.tmax ] for tmark in tmarks: axes2.plot([tmark, tmark], [-0.9, 0.1], color=tap_color_annot) for tmark, text, ha in [ (tmarks[0], '$\\,$ ' + meta.str_duration(tmarks[0] - source.time), 'right'), (tmarks[1], '$\\Delta$ ' + meta.str_duration(tmarks[1] - tmarks[0]), 'left') ]: axes2.annotate( text, xy=(tmark, -0.9), xycoords='data', xytext=(fontsize * 0.4 * [-1, 1][ha == 'left'], fontsize * 0.2), textcoords='offset points', ha=ha, va='bottom', color=tap_color_annot, fontsize=fontsize) scale_string = None if target.misfit_config.domain == 'cc_max_norm': scale_string = 'Syn/obs scales differ!' infos = [] if scale_string: infos.append(scale_string) infos.append('.'.join(x for x in target.codes if x)) dist = source.distance_to(target) azi = source.azibazi_to(target)[0] infos.append(meta.str_dist(dist)) infos.append(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') for (iyy, ixx), (_, fig) in figures.items(): title = '.'.join(x for x in cg if x) if len(figures) > 1: title += ' (%i/%i, %i/%i)' % (iyy + 1, nyy, ixx + 1, nxx) fig.suptitle(title, fontsize=fontsize_title) return figs