amax = num.max(num.abs(spec_tr.ydata)) k = key(spec_tr) if k not in amaxs: amaxs[k] = amax else: amaxs[k] = max(amaxs[k], amax)
(ma - mi) * space - (1.0 + space) t2, y2, clip_on=False, **kwargs)
axes, spec_syn, spec_obs, fmin, fmax, space, mi, ma, syn_color='red', obs_color='black', syn_lw=1.5, obs_lw=1.0, color_vline='gray', fontsize=9.):
fpad = (fmax - fmin) / 6.
for spec, color, lw in [ (spec_syn, syn_color, syn_lw), (spec_obs, obs_color, obs_lw)]:
f = spec.get_xdata() mask = num.logical_and(fmin - fpad <= f, f <= fmax + fpad)
f = f[mask] y = num.abs(spec.get_ydata())[mask]
y2 = (num.concatenate((y, num.zeros(y.size))) - mi) / \ (ma - mi) * space - (1.0 + space) f2 = num.concatenate((f, f[::-1])) axes2 = axes.twiny() axes2.set_axis_off()
axes2.set_xlim(fmin - fpad * 5, fmax + fpad * 5)
axes2.plot(f2, y2, clip_on=False, color=color, lw=lw) axes2.fill(f2, y2, alpha=0.1, clip_on=False, color=color)
axes2.plot([fmin, fmin], [-1.0 - space, -1.0], color=color_vline) axes2.plot([fmax, fmax], [-1.0 - space, -1.0], color=color_vline)
for (text, fx, ha) in [ ('%.3g Hz' % fmin, fmin, 'right'), ('%.3g Hz' % fmax, fmax, 'left')]:
axes2.annotate( text, xy=(fx, -1.0), xycoords='data', xytext=( fontsize * 0.4 * [-1, 1][ha == 'left'], -fontsize * 0.2), textcoords='offset points', ha=ha, va='top', color=color_vline, fontsize=fontsize)
axes.plot([t, t], [-1.0 - space, -1.0], **kwargs)
nframes = len(targets)
nx = int(math.ceil(math.sqrt(nframes))) ny = (nframes - 1) // nx + 1
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
return frame_to_target, nx, ny, nxx, nyy
''' Plot for checking the waveforms fit with a number of synthetics '''
2, Float.T(), default=(9., 7.5), help='width and length of the figure in cm') default=10, help='Number of Synthetics to generate')
x = problem.preconstrain(problem.get_reference_model()) sources.append(problem.base_source) results = problem.evaluate(x) results_list.append(results)
else:
sources, problem.targets, results_list), title=u'Waveform Check', section='checks', feather_icon='activity', description=u''' Plot to judge waveform time window settings and source model parameter ranges.
For each waveform target, observed and synthetic waveforms are shown. For the latter, models are randomly drawn from the configured parameter search space.
The top panel shows the observed waveform; filtered (faint gray), and filtered and tapered (black). The colored outline around the observed trace shows the taper position for each drawn model in a different color. The middle panel shows the filtered synthetic waveforms of the drawn models and the bottom plot shows the corresponding filtered and tapered synthetic waveforms. The colors of taper and synthetic traces are consistent for each random model. The given time is relative to the reference event origin time. ''')
range(len(targets)), targets, results_list):
# distances = [ # s.distance_to(target) for s in sources]
# distance_min = num.min(distances) # distance_max = num.max(distances)
num.max(num.abs( result.filtered_obs.get_ydata())))
else:
fig, nw=1, nh=1, w=1., h=5., units=fontsize)
t0 = result.tsyn_pick else:
t-t0, ydata*0.40 + 3.5, color='black', lw=1.0)
axes.axvline( result.tsyn_pick - t0, color=(0.7, 0.7, 0.7), zorder=2)
''' Plot showing all waveform fits for the ensemble of solutions'''
2, Float.T(), default=(9., 5.), help='width and length of the figure in cm') default=1, help='horizontal number of subplots on every page') default=1, help='vertical number of subplots on every page') optional=True, help='Plot fits for models up to this misfit value') default='misfit', help='Choice of value to color, options: dist and misfit') default=8, help='Font Size of all fonts, except title') default=10, help='Font size of title')
self, self.draw_figures(ds, history, optimiser), title=u'Waveform fits for the ensemble', section='fits', feather_icon='activity', description=u''' Plot showing waveform (attribute) fits for the ensemble of solutions.
Waveform fits for every nth model in the ensemble of bootstrap solutions. Depending on the target configuration different types of comparisons are possible: (i) time domain waveform differences, (ii) amplitude spectra, (iii) envelopes, (iv) cross correlation functions. Each waveform plot gives a number of details:
1) Target information (left side, from top to bottom) gives station name with component, distance to source, azimuth of station with respect to source, target weight, target misfit and starting time of the waveform relative to the origin time.
2) The background gray area shows the applied taper function.
3) The waveforms shown are: the restituted and filtered observed trace without tapering (light grey) and the same trace with tapering and processing (dark gray), the synthetic trace (light red) and the filtered, tapered and (if enabled) shifted and processed synthetic trace (colored). The colors of the synthetic traces indicate how well the corresponding models fit in the global weighting scheme (when all bootstrap weights are equal), from better fit (red) to worse fit (blue). The amplitudes of the traces are scaled according to the target weight (small weight, small amplitude) and normed relative to the maximum amplitude of the targets of the corresponding normalisation family.
4) The bottom panel shows, depending on the type of comparison, sample-wise residuals for time domain comparisons (red filled), spectra of observed and synthetic traces for amplitude spectrum comparisons, or cross correlation traces.''')
ibest = gms < misfit_cutoff gms = gms[ibest] models = models[ibest]
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 in problem.parameter_names: ind = problem.name_to_index(color_parameter) icolor = problem.extract(models, ind)
not isinstance(target, WaveformMisfitTarget) or \ not num.all(num.isfinite(w)):
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: result.filtered_obs, result.filtered_syn, result.processed_obs, result.processed_syn):
# result.filtered_syn.shift(result.tshift)
result.processed_syn, result.processed_obs, problem.norm_exponent)
normalisation_family=target.normalisation_family, path=target.path)
normalisation_family=target.normalisation_family, path=target.path)
logger.warn('No traces to show!') return
dtrace_ for dtrace_ in dtraces_all if dtrace_ is not None], skey)
problem.waveform_targets, lambda t: (t.path, t.codes[3]), filter=lambda t: t in target_to_results)
norm=colors.Normalize(vmin=num.min(icolor), vmax=num.max(icolor)), cmap=plt.get_cmap('coolwarm'))
source, targets, nxmax, nymax)
continue
name='fig_%s_%i_%i' % (title, ixx, iyy)) item, plt.figure(figsize=self.size_inch))
left=0.03, right=1.0 - 0.03, bottom=0.03, top=1.0 - 0.06, wspace=0.2, hspace=0.2)
target.normalisation_family, target.path]
axes.set_ylim(-10. * space_factor, 10.) else:
axes2, result.processed_obs.get_xdata(), result.taper, fc=tap_color_fill, ec=tap_color_edge, alpha=0.2)
axes2, dtrace, space, 0., 1., fc='none', ec=syn_color)
# plot_trace( # axes, result.filtered_syn, # color=syn_color_light, lw=1.0)
axes, result.filtered_obs, color=obs_color_light, lw=0.75)
axes, result.processed_syn, color=syn_color, lw=1.0, alpha=0.3)
axes, result.processed_obs, color=obs_color, lw=0.75, alpha=0.3)
result.processed_obs.tmin, result.processed_obs.tmax]
[tmark, tmark], [-0.9, 0.1], color=tap_color_annot)
(tmarks[0], '$\\,$ ' + meta.str_duration( tmarks[0] - source.time), 'left'), (tmarks[1], '$\\Delta$ ' + meta.str_duration( dur), 'right')]:
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)
tmarks[0] - dur*0.1, tmarks[1] + dur*0.1)
scale_string = 'Syn/obs scales differ!'
infos.append(scale_string)
else: infos.append('.'.join(x for x in target.codes if x)) '\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)
yield item, fig
''' Plot showing the waveform fits for the best model ''' 2, Float.T(), default=(9., 5.), help='width and length of the figure in cm') default=1, help='horizontal number of subplots on every page') default=1, help='vertical number of subplots on every page') default=8, help='Font Size of all fonts, except title') default=10, help='Font Size of title')
self, self.draw_figures(ds, history, optimiser), title=u'Waveform fits for best model', section='fits', feather_icon='activity', description=u''' Plot showing observed and synthetic waveform (attributes) for the best fitting model.
Best model's waveform fits for all targets. Depending on the target configurations different types of comparisons are possible: (i) time domain waveform differences, (ii) amplitude spectra, (iii) envelopes, (iv) cross correlation functions. Each waveform plot gives a number of details:
1) Target information (left side, from top to bottom) gives station name with component, distance to source, azimuth of station with respect to source, target weight, target misfit and starting time of the waveform relative to the origin time.
2) The background gray area shows the applied taper function.
3) The waveforms shown are: the restituted and filtered observed trace without tapering (light grey) and the same trace with tapering and processing (dark gray), the synthetic trace (light red) and the filtered, tapered and (if enabled) shifted and processed synthetic target trace (red). The traces are scaled according to the target weight (small weight, small amplitude) and normed relative to the maximum amplitude of the targets of the corresponding normalisation family.
4) The bottom panel shows, depending on the type of comparison, sample-wise residuals for time domain comparisons (red filled), spectra of observed and synthetic traces for amplitude spectrum comparisons, or cross correlation traces.
5) Colored boxes on the upper right show the relative weight of the target within the entire dataset of the optimisation (top box, orange) and the relative misfit contribution to the global misfit of the optimisation (bottom box, red). ''')
misfits[:1, :, :], extra_correlated_weights=optimiser.get_correlated_weights(problem), get_contributions=True)[0, :]
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: result.filtered_obs, result.filtered_syn, result.processed_obs, result.processed_syn):
result.spectrum_obs, result.spectrum_syn):
spec.ydata *= w
# result.filtered_syn.shift(result.tshift)
result.processed_syn, result.processed_obs, problem.norm_exponent)
normalisation_family=target.normalisation_family, path=target.path)
normalisation_family=target.normalisation_family, path=target.path)
result.spectrum_syn.meta = dict( normalisation_family=target.normalisation_family, path=target.path)
all_syn_specs.append(result.spectrum_syn)
logger.warn('No traces to show!') return
problem.waveform_targets, lambda t: (t.path, t.codes[3]), filter=lambda t: t in target_to_result)
source, targets, nxmax, nymax)
continue
name='fig_%s_%i_%i' % (title, ixx, iyy)) item, plt.figure(figsize=self.size_inch))
left=0.03, right=1.0 - 0.03, bottom=0.03, top=1.0 - 0.06, wspace=0.2, hspace=0.2)
target.normalisation_family, target.path]
axes.set_ylim(-10. * space_factor, 10.) else: -absmax * 1.33 * space_factor, absmax * 1.33)
axes2, result.processed_obs.get_xdata(), result.taper, fc=tap_color_fill, ec=tap_color_edge)
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)
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: axes2, dtrace, space, 0., 1., fc=light(misfit_color, 0.3), ec=misfit_color)
axes, result.filtered_syn, color=syn_color_light, lw=1.0)
axes, result.filtered_obs, color=obs_color_light, lw=0.75)
axes, result.processed_syn, color=syn_color, lw=1.0)
axes, result.processed_obs, color=obs_color, lw=0.75)
# xdata = result.filtered_obs.get_xdata()
result.processed_obs.tmin, result.processed_obs.tmax]
[tmark, tmark], [-0.9, 0.1], color=tap_color_annot)
(tmarks[0], '$\\,$ ' + meta.str_duration( tmarks[0] - source.time), 'left'), (tmarks[1], '$\\Delta$ ' + meta.str_duration(dur), 'right')]:
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)
(0, rel_w, light(weight_color, 0.5), weight_color), (1, rel_c, light(misfit_color, 0.5), misfit_color)]:
(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)
scale_string = 'Syn/obs scales differ!'
infos.append(scale_string)
else: infos.append('.'.join(x for x in target.codes if x))
'\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)
yield item, fig
''' Plot showing all waveform fits for the ensemble of solutions'''
except (NoRundirAvailable, ProblemDataNotAvailable): history = None
self, self.draw_figures(problem, dataset, history), title=u'Seismic station locations', section='checks', feather_icon='target', description=u''' Plot showing seismic station locations and attributes.
Station locations in dependence of distance and azimuth are shown. The center of the plot corresponds to the origin of the search space, not to the optimised location of the source. ''')
misfits[:1, :, :], get_contributions=True)[0, :]
problem.waveform_targets, lambda t: (t.path, t.codes[3]))
continue
for target in targets)
[target_index[target][0] for target in targets])
name='seismic_stations_weights_%s' % cg_str, title=u'Station weights (%s)' % cg_str, description=u'\n\nMarkers are scaled according to the ' u'weighting factor of the corresponding target\'s ' u'contribution in the misfit function.') azimuths, distances, ws[itargets], labels) 'Weight', prop=dict(size=self.font_size))
name='seismic_stations_contributions_%s' % cg_str, title=u'Station misfit contributions (%s)' % cg_str, description=u'\n\nMarkers are scaled according to their ' u'misfit contribution for the globally best ' u'source model.') azimuths, distances, gcms[itargets], labels) 'Contribution', prop=dict(size=self.font_size))
WaveformStationDistribution, CheckWaveformsPlot, FitsWaveformPlot, FitsWaveformEnsemblePlot ] |