def call(self): '''Main work routine of the snuffling.''' # to select a reasonable increment for the chopping, the smallest # sampling interval in the pile is looked at. this is only done, # the first time the snuffling is called. if self.tinc is None: self.tinc = self.get_pile().get_deltats()[0] * 10000. # the chopper yields lists of traces but for minmax() below, an # iterator yielding single traces is needed; using a converter: def iter_single_traces(): for traces in self.chopper_selected_traces( tinc=self.tinc, degap=False, fallback=True): for tr in traces: yield tr # the function minmax() in the trace module can get minima and maxima # grouped by (network,station,location,channel): mima = trace.minmax(iter_single_traces()) for nslc in sorted(mima.keys()): p2p = mima[nslc][1] - mima[nslc][0] print '%s.%s.%s.%s: %12.5g %12.5g %12.5g' % ( nslc + mima[nslc] + (p2p,))
def call(self): '''Main work routine of the snuffling.''' # to select a reasonable increment for the chopping, the smallest # sampling interval in the pile is looked at. this is only done, # the first time the snuffling is called. if self.tinc is None: self.tinc = self.get_pile().get_deltats()[0] * 10000. # the chopper yields lists of traces but for minmax() below, an # iterator yielding single traces is needed; using a converter: def iter_single_traces(): for traces in self.chopper_selected_traces(tinc=self.tinc, degap=False, fallback=True): for tr in traces: yield tr # the function minmax() in the trace module can get minima and maxima # grouped by (network,station,location,channel): mima = trace.minmax(iter_single_traces()) for nslc in sorted(mima.keys()): p2p = mima[nslc][1] - mima[nslc][0] print('%s.%s.%s.%s: %12.5g %12.5g %12.5g' % (nslc + mima[nslc] + (p2p, )))
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, 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 call(self): self.cleanup() viewer = self.get_viewer() event = viewer.get_active_event() stations = self.get_stations() for s in stations: print(s.nsl()) nsl_to_station = dict((s.nsl(), s) for s in stations) if event is None: self.error('No active event set.') markers = self.get_selected_markers() if len(markers) != 1: self.error('Exactly one marker must be selected.') marker = markers[0] try: nslc = marker.one_nslc() except pmarker.MarkerOneNSLCRequired: self.error('Marker must be picked on a single trace.') marker_station = nsl_to_station[nslc[:3]] mod = cake.load_model() def traveltime(station): dist = event.distance_to(station) arrivals = mod.arrivals(zstart=event.depth, zstop=0., distances=[dist * cake.m2d], phases=[cake.PhaseDef(self.phasename)]) if not arrivals: raise NoArrival() return arrivals[0].t try: tt_marker_station = traveltime(marker_station) except NoArrival: self.error('Selected phase does not arrive at station.') nsl_to_delay = {} for station in stations: nsl_to_delay[station.nsl()] = \ traveltime(station) - tt_marker_station pile = self.get_pile() nsl_to_traces = {} nsl_to_tspan = {} fs = [f for f in [viewer.lowpass, viewer.highpass] if f is not None] if fs: tpad = 2.0 / min(fs) else: tpad = 0.0 deltats = set() for nsl in nsl_to_delay.keys(): delay = nsl_to_delay[nsl] tmin = marker.tmin + delay tmax = marker.tmax + delay nsl_to_tspan[nsl] = (tmin, tmax) trs = pile.all(tmin=tmin, tmax=tmax, tpad=tpad, trace_selector=lambda tr: tr.nslc_id[:3] == nsl, want_incomplete=False) for tr in trs: if viewer.lowpass is not None: tr.lowpass(4, viewer.lowpass) if viewer.highpass is not None: tr.highpass(4, viewer.highpass) tr.chop(tr.wmin, tr.wmax) deltats.add(tr.deltat) if trs: nsl_to_traces[nsl] = trs if len(deltats) != 1: self.error('All traces must have same sampling rate.') # add markers for nsl in nsl_to_traces.keys(): tmin, tmax = nsl_to_tspan[nsl] for tr in nsl_to_traces[nsl]: mark = PhaseMarker([tr.nslc_id], tmin=tmin, tmax=tmax, kind=1, phasename=self.phasename) self.add_marker(mark) # cross correlations nsls = sorted(list(nsl_to_traces.keys())) pair_corrs = [] for nsl_a in nsls: trs_a = nsl_to_traces[nsl_a] if self.channels_relamp == 'All': comps = sorted(set([tr.channel[-1] for tr in trs_a])) else: comps = [c.strip() for c in self.channels_relamp.split(',')] for nsl_b in nsls: trs_b = nsl_to_traces[nsl_b] for comp in comps: try: tr_a = get_trace(trs_a, lambda tr: tr.channel.endswith(comp)) tr_b = get_trace(trs_b, lambda tr: tr.channel.endswith(comp)) except NotFound: continue if tr_a is tr_b: continue tr_cor = trace.correlate(tr_a, tr_b, mode='full', normalization='normal') delaymax, ccmax = tr_cor.max() delaymin, ccmin = tr_cor.min() delay_syn = nsl_to_delay[nsl_b] - nsl_to_delay[nsl_a] if abs(ccmin) < abs(ccmax): delay = delaymax ccabsmax = abs(ccmax) ccsignedmax = ccmax else: delay = delaymin ccabsmax = abs(ccmin) ccsignedmax = ccmin tr_b_shifted = tr_b.copy() tr_b_shifted.shift(-delay) tmin_com = max(tr_b_shifted.tmin, tr_a.tmin) tmax_com = min(tr_b_shifted.tmax, tr_a.tmax) tr_a_chopped = tr_a.chop(tmin_com, tmax_com, inplace=False) tr_b_chopped = tr_b_shifted.chop(tmin_com, tmax_com, inplace=False) ya = tr_a_chopped.ydata yb = tr_b_chopped.ydata relamp1 = num.sum(ya * yb) / num.sum(yb**2) relamp2 = num.sum(ya * yb) / num.sum(ya**2) if nsl_a[1] == 'LYKK': print(ccabsmax, relamp1, relamp2, abs((relamp1 / (1.0 / relamp2) - 1.0))) if ccabsmax < self.cc_min: continue if abs((relamp1 / (1.0 / relamp2) - 1.0)) > 0.2: continue relamp = (relamp1 + 1. / relamp2) * 0.5 pair_corrs.append((tr_a.nslc_id, tr_b.nslc_id, ccsignedmax, relamp, delay, delay_syn)) nslc_to_relamp = invert_relative_amplitudes(pair_corrs) self._nslc_to_relamp = nslc_to_relamp nsl_to_xy = {} for nsl in nsl_to_traces.keys(): trs = nsl_to_traces[nsl] try: cc = [c.strip() for c in self.channels_polar.split(',')] tr_y, tr_x = [ get_trace(trs, lambda tr: tr.channel.endswith(c)) for c in cc ] x = tr_x.get_ydata() y = tr_y.get_ydata() nsl_to_xy[nsl] = (x, y) except NotFound: pass nsls = sorted(list(nsl_to_xy.keys())) n = len(nsls) xs_l = [nsl_to_xy[nsl][0] for nsl in nsls] ys_l = [nsl_to_xy[nsl][1] for nsl in nsls] nsamp = min(min(x.size for x in xs_l), min(y.size for y in ys_l)) xs = num.vstack(x[:nsamp] for x in xs_l) ys = num.vstack(y[:nsamp] for y in ys_l) amps = num.sqrt(xs**2 + ys**2) amp_maxs = num.max(amps, axis=1) xs = xs / amp_maxs[:, num.newaxis] ys = ys / amp_maxs[:, num.newaxis] nphi = 73 phis = num.linspace(-180., 180., nphi) d = num.zeros((n, n, nphi)) for ia in range(n): for iphi, phi in enumerate(phis): x = xs[ia, :] y = ys[ia, :] xrot = num.cos(phi * d2r) * x + num.sin(phi * d2r) * y yrot = -num.sin(phi * d2r) * x + num.cos(phi * d2r) * y d[ia, :, iphi] = num.sqrt( num.sum((xrot[num.newaxis, :] - xs)**2 + (yrot[num.newaxis, :] - ys)**2, axis=1)) imins = num.argmin(d, axis=2) dmins = num.min(d, axis=2) dmin_median = num.median(dmins) phimins = phis[imins] nsl_to_rot = {} for nsl in nsls: nsl_to_rot[nsl] = 0. failed = set() for i in range(n): mean_min_error = num.mean(dmins[i, :] / dmin_median) print(mean_min_error, nsls[i]) if mean_min_error > 3.0: failed.add(nsls[i]) while True: ia_worst = num.argmax(num.mean(num.abs(phimins), axis=1)) phimod = ((phis[num.newaxis, :] + phimins[ia_worst, :, num.newaxis] + 180.) % 360.) - 180. phirot = phis[num.argmin(num.mean(num.abs(phimod), axis=0))] if abs(phirot) < 10.: break nsl = nsls[ia_worst] mean_min_error = num.mean(dmins[ia_worst, :] / dmin_median) phimins[ia_worst, :] = ( (phimins[ia_worst, :] + phirot) + 180.) % 360. - 180. phimins[:, ia_worst] = ( (phimins[:, ia_worst] - phirot) + 180.) % 360. - 180. if nsl not in failed: print('%-20s %8.0f' % ('.'.join(nsl), phirot)) nsl_to_rot[nsl] += phirot fframe = self.figure_frame() fig = fframe.gcf() fig.clf() if n == 0: self.error('No matching traces found.') ncols = 1 while ncols**2 < n: ncols += 1 nrows = ncols axes = fig.add_subplot(1, 2, 1, aspect=1.0) axes.axison = False axes.set_xlim(-0.05 - ncols, ncols + 0.05) axes.set_ylim(-0.05 - nrows, nrows + 0.05) axes.set_title('Event: %s, Phase: %s' % (event.name, self.phasename)) for insl, nsl in enumerate(nsls): irow = insl // ncols icol = insl % ncols trs = nsl_to_traces[nsl] try: x, y = nsl_to_xy[nsl] cc = [c.strip() for c in self.channels_polar.split(',')] tr_y, tr_x = [ get_trace(trs, lambda tr: tr.channel.endswith(c)) for c in cc ] xpos = icol * 2 - ncols + 1 ypos = -irow * 2 + nrows - 1 x = tr_x.get_ydata() y = tr_y.get_ydata() a = num.sqrt(x**2 + y**2) amax = num.max(a) phi = nsl_to_rot[nsl] color = 'black' if num.abs(phi) > 0: color = mpl_color('chocolate2') if num.abs(phi) > 30: color = mpl_color('orange2') if nsl in failed: color = mpl_color('scarletred2') axes.plot(x / amax + xpos, y / amax + ypos, color=color, alpha=0.7) if nsl not in failed: xrot = num.cos(phi * d2r) * x - num.sin(phi * d2r) * y yrot = num.sin(phi * d2r) * x + num.cos(phi * d2r) * y axes.plot(xrot / amax + xpos, yrot / amax + ypos, color='black', alpha=0.5) # axes.plot( # [xpos, num.sin(phi*d2r) + xpos], # [ypos, num.cos(phi*d2r) + ypos], # color=color, alpha=0.5) axes.annotate('.'.join(_ for _ in nsl if _), xy=(icol * 2 - ncols + 1, -irow * 2 + nrows - 2), xycoords='data', xytext=(0, 0), textcoords='offset points', verticalalignment='center', horizontalalignment='center', rotation=0.) except NotFound: pass axes = fig.add_subplot(1, 2, 2) nslcs = sorted(nslc_to_relamp.keys()) pdata = [] for inslc, nslc in enumerate(nslcs): nsl = nslc[:3] cha = nslc[3] tr = get_trace(nsl_to_traces[nsl], lambda tr: tr.channel == cha).copy() tr.shift(-(event.time + tt_marker_station + nsl_to_delay[nsl])) relamp = nslc_to_relamp[nslc] tr.ydata /= relamp color = 'black' if abs(num.log10(relamp)) > num.log10(1.1): color = mpl_color('chocolate2') if abs(num.log10(relamp)) > num.log10(2.0): color = mpl_color('orange2') if abs(num.log10(relamp)) > num.log10(10.0): color = mpl_color('scarletred2') pdata.append((tr, relamp, color, inslc, nslc)) ranges = trace.minmax([aa[0] for aa in pdata], lambda tr: None) ymin, ymax = ranges[None] yabsmax = max(abs(ymin), abs(ymax)) for (tr, relamp, color, inslc, nslc) in pdata: axes.plot(tr.get_xdata(), inslc + tr.get_ydata() / yabsmax, color=color) axes.annotate('.'.join(_ for _ in nslc if _), xy=(0, inslc), xycoords=('axes fraction', 'data'), xytext=(-5, 0), textcoords='offset points', verticalalignment='center', horizontalalignment='right', rotation=0., color=color) axes.annotate('x %g' % (1.0 / relamp), xy=(1., inslc), xycoords=('axes fraction', 'data'), xytext=(+5, 0), textcoords='offset points', verticalalignment='center', horizontalalignment='left', rotation=0., color=color) axes.get_yaxis().set_visible(False) for which in ['top', 'right', 'left']: axes.spines[which].set_visible(False) axes.set_xlabel('Time [s]') fframe.draw()
def yminmax(self, traces): return trace.minmax(traces, key=self.map_yscaling)
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 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): 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