def plot_currentmodels(self, nchains): """Return fig. Plots the first nchains chains, no matter of outlier status. """ fig, ax = plt.subplots(figsize=(4, 6.5)) base = cm.get_cmap(name='rainbow') color_list = base(np.linspace(0, 1, nchains)) for i, modfile in enumerate(self.modfiles[1][:nchains]): chainidx, _, _ = self._return_c_p_t(modfile) models = np.load(modfile) vpvs = np.load(modfile.replace('models', 'vpvs')).T currentvpvs = vpvs[-1] currentmodel = models[-1] color = color_list[i] vp, vs, h = Model.get_vp_vs_h(currentmodel, currentvpvs, self.mantle) cvp, cvs, cdepth = Model.get_stepmodel_from_h(h=h, vs=vs, vp=vp) label = 'c%d / %d' % (chainidx, vs.size-1) ax.plot(cvs, cdepth, color=color, ls='-', lw=0.8, alpha=0.7, label=label) ax.invert_yaxis() ax.set_xlabel('$V_S$ in km/s') ax.set_ylabel('Depth in km') # ax.set_xlim(self.priors['vs']) ax.set_ylim(self.priors['z'][::-1]) ax.set_title('Current models') ax.grid(color='gray', alpha=0.6, ls=':', lw=0.5) ax.legend(loc='center left', bbox_to_anchor=(1, 0.5)) return fig
def update_models(self, model, vpvs): logger.debug('### Found new chain model') vp, vs, dep = Model.get_stepmodel(model, vpvs=vpvs, mantle=self.mantle) self.vs_step = np.roll(self.vs_step, -1, axis=0) # rolling up models nantmp = np.ones(self.modellength) * np.nan nantmp[:vs.size] = vs self.vs_step[-1] = nantmp self.dep_step = np.roll(self.dep_step, -1, axis=0) # rolling up models nantmp = np.ones(self.modellength) * np.nan nantmp[:dep.size] = dep self.dep_step[-1] = nantmp vp, vs, h = Model.get_vp_vs_h(model, vpvs=vpvs, mantle=self.mantle) ymod = self.compute_synth(h, vs, vp) for i, tline in enumerate(self.targetlines): if tline is not None: tline.set_ydata(ymod[i]) # # create LineCollection segments = [ np.column_stack([x, y]) for x, y in zip(self.vs_step, self.dep_step) ] self.modelcollection.set_segments(segments) a = np.repeat(([0, 1], ), self.capacity, axis=0) b = np.array([[v] * 2 for v in self.vpvss]) segments = [np.column_stack([x, y]) for x, y in zip(b, a)] self.vpvscollection.set_segments(segments)
def plot_bestdatafits(self): """Plot best data fits from each chain and ever best, ignoring outliers.""" targets = Targets.JointTarget(targets=self.targets) fig, ax = targets.plot_obsdata(mod=False) thebestmodel = np.nan thebestmisfit = 1e15 thebestchain = np.nan modfiles = self.modfiles[1] for i, modfile in enumerate(modfiles): chainidx, _, _ = self._return_c_p_t(modfile) if chainidx in self.outliers: continue models = np.load(modfile) misfits = np.load(modfile.replace('models', 'misfits')).T[-1] bestmodel = models[np.argmin(misfits)] bestmisfit = misfits[np.argmin(misfits)] if bestmisfit < thebestmisfit: thebestmisfit = bestmisfit thebestmodel = bestmodel thebestchain = chainidx vp, vs, h = Model.get_vp_vs_h(bestmodel, self.priors['vpvs']) rho = vp * 0.32 + 0.77 for n, target in enumerate(targets.targets): xmod, ymod = target.moddata.plugin.run_model(h=h, vp=vp, vs=vs, rho=rho) if len(targets.targets) > 1: ax[n].plot(xmod, ymod, color='k', alpha=0.5, lw=0.7) else: ax.plot(xmod, ymod, color='k', alpha=0.5, lw=0.7) if len(targets.targets) > 1: ax[0].set_title('Best data fits from %d chains' % (len(modfiles) - self.outliers.size)) # idx = len(targets.targets) - 1 han, lab = ax[0].get_legend_handles_labels() handles, labels = self._unique_legend(han, lab) ax[0].legend().set_visible(False) else: ax.set_title('Best data fits from %d chains' % (len(modfiles) - self.outliers.size)) han, lab = ax.get_legend_handles_labels() handles, labels = self._unique_legend(han, lab) ax.legend().set_visible(False) fig.legend(handles, labels, loc='center left', bbox_to_anchor=(0.92, 0.5)) return fig
def plot_currentdatafits(self, nchains): """Plot the first nchains chains, no matter of outlier status. """ base = cm.get_cmap(name='rainbow') color_list = base(np.linspace(0, 1, nchains)) targets = Targets.JointTarget(targets=self.targets) fig, ax = targets.plot_obsdata(mod=False) for i, modfile in enumerate(self.modfiles[1][:nchains]): color = color_list[i] chainidx, _, _ = self._return_c_p_t(modfile) models = np.load(modfile) vpvs = np.load(modfile.replace('models', 'vpvs')).T currentvpvs = vpvs[-1] currentmodel = models[-1] vp, vs, h = Model.get_vp_vs_h(currentmodel, currentvpvs, self.mantle) rho = vp * 0.32 + 0.77 jmisfit = 0 for n, target in enumerate(targets.targets): xmod, ymod = target.moddata.plugin.run_model( h=h, vp=vp, vs=vs, rho=rho) yobs = target.obsdata.y misfit = target.valuation.get_rms(yobs, ymod) jmisfit += misfit label = '' if len(targets.targets) > 1: if ((len(targets.targets) - 1) - n) < 1e-2: label = 'c%d / %.3f' % (chainidx, jmisfit) ax[n].plot(xmod, ymod, color=color, alpha=0.7, lw=0.8, label=label) else: label = 'c%d / %.3f' % (chainidx, jmisfit) ax.plot(xmod, ymod, color=color, alpha=0.5, lw=0.7, label=label) if len(targets.targets) > 1: ax[0].set_title('Current data fits') idx = len(targets.targets) - 1 han, lab = ax[idx].get_legend_handles_labels() handles, labels = self._unique_legend(han, lab) ax[0].legend().set_visible(False) else: ax.set_title('Current data fits') han, lab = ax.get_legend_handles_labels() handles, labels = self._unique_legend(han, lab) ax.legend().set_visible(False) fig.legend(handles, labels, loc='center left', bbox_to_anchor=(0.92, 0.5)) return fig
def plot_bestmodels(self): """Return fig. Plot the best (fit) models ever discovered per each chain, ignoring outliers. """ fig, ax = plt.subplots(figsize=(4, 6.5)) thebestmodel = np.nan thebestmisfit = 1e15 thebestchain = np.nan modfiles = self.modfiles[1] for i, modfile in enumerate(modfiles): chainidx, _, _ = self._return_c_p_t(modfile) if chainidx in self.outliers: continue models = np.load(modfile) vpvs = np.load(modfile.replace('models', 'vpvs')).T misfits = np.load(modfile.replace('models', 'misfits')).T[-1] bestmodel = models[np.argmin(misfits)] bestvpvs = vpvs[np.argmin(misfits)] bestmisfit = misfits[np.argmin(misfits)] if bestmisfit < thebestmisfit: thebestmisfit = bestmisfit thebestmodel = bestmodel thebestvpvs = bestvpvs thebestchain = chainidx vp, vs, h = Model.get_vp_vs_h(bestmodel, bestvpvs, self.mantle) cvp, cvs, cdepth = Model.get_stepmodel_from_h(h=h, vs=vs, vp=vp) ax.plot(cvs, cdepth, color='k', ls='-', lw=0.8, alpha=0.5) # label = 'c%d' % thebestchain # vp, vs, h = Model.get_vp_vs_h(thebestmodel, thebestvpvs, self.mantle) # cvp, cvs, cdepth = Model.get_stepmodel_from_h(h=h, vs=vs, vp=vp) # ax.plot(cvs, cdepth, color='red', ls='-', lw=1, # alpha=0.8, label=label) ax.invert_yaxis() ax.set_xlabel('$V_S$ in km/s') ax.set_ylabel('Depth in km') # ax.set_xlim(self.priors['vs']) ax.set_ylim(self.priors['z'][::-1]) ax.set_title('Best fit models from %d chains' % (len(modfiles)-self.outliers.size)) ax.grid(color='gray', alpha=0.6, ls=':', lw=0.5) # ax.legend(loc=3) return fig
def _init_model_and_currentvalues(self): imodel = self.draw_initmodel() inoise, corrfix = self.draw_initnoiseparams() rcond = self.initparams['rcond'] self.set_target_covariance(corrfix[::2], inoise[::2], rcond) vp, vs, h = Model.get_vp_vs_h(imodel, self.vpvs) self.targets.evaluate(h=h, vp=vp, vs=vs, noise=inoise) self.currentmodel = imodel self.currentnoise = inoise self.currentmisfits = self.targets.proposalmisfits self.currentlikelihood = self.targets.proposallikelihood logger.debug((vs, h)) self.n = 0 # accepted models counter self.accept_as_currentmodel(imodel, inoise) self.append_currentmodel()
def plot_rfcorr(self, rf='prf'): from BayHunter import SynthObs p2models, p2noise, p2misfits, p2vpvs = self._get_posterior_data( ['models', 'noise', 'misfits', 'vpvs'], final=True) fig, axes = plt.subplots(2, sharex=True, sharey=True) ind = self.refs.index(rf) best = np.argmin(p2misfits.T[ind]) model = p2models[best] vpvs = p2vpvs[best] target = self.targets[ind] x, y = target.obsdata.x, target.obsdata.y vp, vs, h = Model.get_vp_vs_h(model, vpvs, self.mantle) rho = vp * 0.32 + 0.77 _, ymod = target.moddata.plugin.run_model( h=h, vp=vp, vs=vs, rho=rho) yobs = target.obsdata.y yresiduals = yobs - ymod # axes[0].set_title('Residuals [dobs-g(m)] obtained with best fitting model m') axes[0].plot(x, yresiduals, color='k', lw=0.7, label='residuals') corr, sigma = p2noise[best][2*ind:2*(ind+1)] yerr = SynthObs.compute_gaussnoise(y, corr=corr, sigma=sigma) # axes[1].set_title('One Realization of random noise from inferred CeRF') axes[1].plot(x, yerr, color='k', lw=0.7, label='noise realization') axes[1].set_xlabel('Time in s') axes[0].legend(loc=4) axes[1].legend(loc=4) axes[0].grid(color='gray', ls=':', lw=0.5) axes[1].grid(color='gray', ls=':', lw=0.5) axes[0].set_xlim([x[0], x[-1]]) return fig
def iterate(self): if self.iiter < (-self.iter_phase1 + (self.iterations * 0.01)): # only allow vs and z modifications the first 1 % of iterations modify = self.rstate.choice(['vsmod', 'zvmod'] + self.noisemods + self.vpvsmods) else: modify = self.rstate.choice(self.modifications) if modify in self.modelmods: proposalmodel = self._get_modelproposal(modify) proposalnoise = self.currentnoise proposalvpvs = self.currentvpvs if not self._validmodel(proposalmodel): proposalmodel = None elif modify in self.noisemods: proposalmodel = self.currentmodel proposalnoise = self._get_hyperparameter_proposal() proposalvpvs = self.currentvpvs if not self._validnoise(proposalnoise): proposalmodel = None elif modify == 'vpvs': proposalmodel = self.currentmodel proposalnoise = self.currentnoise proposalvpvs = self._get_vpvs_proposal() if not self._validvpvs(proposalvpvs): proposalmodel = None if proposalmodel is None: # If not a valid proposal model and noise params are found, # leave self.iterate and try with another modification # should not occur often. logger.debug('Not able to find a proposal for %s' % modify) self.iiter += 1 return # compute synthetic data and likelihood, misfit vp, vs, h = Model.get_vp_vs_h(proposalmodel, proposalvpvs, self.mantle) self.targets.evaluate(h=h, vp=vp, vs=vs, noise=proposalnoise) aidx = self.modifications.index(modify) self.proposed[aidx] += 1 # Replace self.currentmodel with proposalmodel with acceptance # probability alpha. Accept candidate sample (proposalmodel) # with probability alpha, or reject it with probability (1 - alpha). # these are log values ! alpha is log. u = np.log(self.rstate.uniform(0, 1)) alpha = self.get_acceptance_probability(modify) # #### _____________________________________________________________ if u < alpha: # always the case if self.jointlike > self.bestlike (alpha>1) self.accept_as_currentmodel(proposalmodel, proposalnoise, proposalvpvs) self.append_currentmodel() self.accepted[aidx] += 1 # print inversion status information if self.iiter % 5000 == 0: runtime = time.time() - self.tnull current_iterations = self.iiter + self.iter_phase1 if current_iterations > 0: acceptrate = float(self.n) / current_iterations * 100. logger.info('%6d %5d + hs %8.3f\t%9d |%6.1f s | %.1f ' % (self.lastmoditer, self.currentmodel.size / 2 - 1, self.currentmisfits[-1], self.currentlikelihood, runtime, acceptrate) + r'%') self.tnull = time.time() # stabilize model acceptance rate if self.iiter % 1000 == 0: if np.all(self.proposed) != 0: self.adjust_acceptrate() self.iiter += 1
def _validmodel(self, model): """ Check model before the forward modeling. - The model must contain all values > 0. - The layer thicknesses must be at least thickmin km. - if lvz: low velocity zones are allowed with the deeper layer velocity no smaller than (1-perc) * velocity of layer above. - ... and some other constraints. E.g. vs boundaries (prior) given. """ vp, vs, h = Model.get_vp_vs_h(model, self.currentvpvs, self.mantle) # check whether nlayers lies within the prior layermin = self.priors['layers'][0] layermax = self.priors['layers'][1] layermodel = (h.size - 1) if not (layermodel >= layermin and layermodel <= layermax): logger.debug("chain%d: model- nlayers not in prior" % self.chainidx) return False # check model for layers with thicknesses of smaller thickmin if np.any(h[:-1] < self.thickmin): logger.debug("chain%d: thicknesses are not larger than thickmin" % self.chainidx) return False # check whether vs lies within the prior vsmin = self.priors['vs'][0] vsmax = self.priors['vs'][1] if np.any(vs < vsmin) or np.any(vs > vsmax): logger.debug("chain%d: model- vs not in prior" % self.chainidx) return False # check whether interfaces lie within prior zmin = self.priors['z'][0] zmax = self.priors['z'][1] z = np.cumsum(h) if np.any(z < zmin) or np.any(z > zmax): logger.debug("chain%d: model- z not in prior" % self.chainidx) return False if self.lowvelperc is not None: # check model for low velocity zones. If larger than perc, then # compvels must be positive compvels = vs[1:] - (vs[:-1] * (1 - self.lowvelperc)) if not compvels.size == compvels[compvels > 0].size: logger.debug("chain%d: low velocity zone issues" % self.chainidx) return False if self.highvelperc is not None: # check model for high velocity zones. If larger than perc, then # compvels must be positive. compvels = (vs[:-1] * (1 + self.highvelperc)) - vs[1:] if not compvels.size == compvels[compvels > 0].size: logger.debug("chain%d: high velocity zone issues" % self.chainidx) return False return True
def plot_moho_crustvel_tradeoff(self, moho=None, mohovs=None, refmodel=None): models, vpvs = self._get_posterior_data(['models', 'vpvs'], final=True) if moho is None: moho = self.priors['z'] if mohovs is None: mohovs = 4.2 # km/s mohos = np.zeros(len(models)) * np.nan vscrust = np.zeros(len(models)) * np.nan vslastlayer = np.zeros(len(models)) * np.nan vsjumps = np.zeros(len(models)) * np.nan for i, model in enumerate(models): thisvpvs = vpvs[i] vp, vs, h = Model.get_vp_vs_h(model, thisvpvs, self.mantle) # cvp, cvs, cdepth = Model.get_stepmodel_from_h(h=h, vs=vs, vp=vp) # ifaces, vs = cdepth[1::2], cvs[::2] # interfaces, vs ifaces = np.cumsum(h) vsstep = np.diff(vs) # velocity change at interfaces mohoidxs = np.argwhere((ifaces > moho[0]) & (ifaces < moho[1])) if len(mohoidxs) == 0: continue # mohoidx = mohoidxs[np.argmax(vsstep[mohoidxs])][0] mohoidxs = mohoidxs.flatten() mohoidxs_vs = np.where((vs > mohovs))[0]-1 if len(mohoidxs_vs) == 0: continue mohoidx = np.intersect1d(mohoidxs, mohoidxs_vs) if len(mohoidx) == 0: continue mohoidx = mohoidx[0] # ------ thismoho = ifaces[mohoidx] crustmean = np.sum(vs[:(mohoidx+1)] * h[:(mohoidx+1)]) / ifaces[mohoidx] lastvs = vs[mohoidx] vsjump = vsstep[mohoidx] mohos[i] = thismoho vscrust[i] = crustmean vslastlayer[i] = lastvs vsjumps[i] = vsjump # exclude nan values mohos = mohos[~np.isnan(vsjumps)] vscrust = vscrust[~np.isnan(vsjumps)] vslastlayer = vslastlayer[~np.isnan(vsjumps)] vsjumps = vsjumps[~np.isnan(vsjumps)] fig, ax = plt.subplots(2, 4, figsize=(11, 6)) fig.subplots_adjust(hspace=0.05) fig.subplots_adjust(wspace=0.05) labels = ['$V_S$ last crustal layer', '$V_S$ crustal mean', '$V_S$ increase'] bins = 50 for n, xdata in enumerate([vslastlayer, vscrust, vsjumps]): try: histdata = ax[0][n].hist(xdata, bins=bins, color='darkblue', alpha=0.7, edgecolor='white', linewidth=0.4) median = np.median(xdata) ax[0][n].axvline(median, color='k', ls='--', lw=1.2, alpha=1) stats = 'median:\n%.2f km/s' % median ax[0][n].text(0.97, 0.97, stats, fontsize=9, color='k', horizontalalignment='right', verticalalignment='top', transform=ax[0][n].transAxes) except: pass for n, xdata in enumerate([vslastlayer, vscrust, vsjumps]): try: ax[1][n].set_xlabel(labels[n]) data = ax[1][n].hist2d(xdata, mohos, bins=bins) data2d, xedges, yedges, _ = np.array(data).T xi, yi = np.unravel_index(data2d.argmax(), data2d.shape) x_mode = ((xedges[:-1] + xedges[1:]) / 2.)[xi] y_mode = ((yedges[:-1] + yedges[1:]) / 2.)[yi] ax[1][n].axhline(y_mode, color='white', ls='--', lw=0.5, alpha=0.7) ax[1][n].axvline(x_mode, color='white', ls='--', lw=0.5, alpha=0.7) xmin, xmax = ax[1][n].get_xlim() ax[0][n].set_xlim([xmin, xmax]) except: pass ax[0][n].set_yticks([]) ax[0][n].set_yticklabels([], visible=False) ax[0][n].set_xticklabels([], visible=False) ax[1][1].set_yticklabels([], visible=False) ax[1][2].set_yticklabels([], visible=False) ax[1][3].set_yticklabels([], visible=False) ax[1][0].set_ylabel('Moho depth in km') # plot moho 1d histogram histdata = ax[1][3].hist(mohos, bins=bins, orientation='horizontal', color='darkblue', alpha=0.7, edgecolor='white', linewidth=0.4) median = np.median(mohos) std = np.std(mohos) print 'moho: %.4f +- %.4f km' % (median, std) ax[1][3].axhline(median, color='k', ls='--', lw=1.2, alpha=1) stats = 'median:\n%.2f km' % median ax[1][3].text(0.97, 0.97, stats, fontsize=9, color='k', horizontalalignment='right', verticalalignment='top', transform=ax[1][3].transAxes) ymin, ymax = ax[1][0].get_ylim() # ymin, ymax = median - 4*std, median + 4*std ax[1][0].set_ylim(ymin, ymax) ax[1][1].set_ylim(ymin, ymax) ax[1][2].set_ylim(ymin, ymax) ax[1][3].set_ylim(ymin, ymax) ax[1][3].set_xticklabels([], visible=False) ax[1][3].set_yticks([]) ax[1][3].set_yticklabels([], visible=False) ax[0][3].axis('off') if refmodel is not None: dep, vs = refmodel h = (dep[1:] - dep[:-1])[::2] ifaces, lvs = dep[1::2], vs[::2] vsstep = np.diff(lvs) # velocity change at interfaces mohoidxs = np.argwhere((ifaces > moho[0]) & (ifaces < moho[1])) mohoidx = mohoidxs[np.argmax(vsstep[mohoidxs])][0] truemoho = ifaces[mohoidx] truecrust = np.sum(lvs[:(mohoidx+1)] * h[:(mohoidx+1)]) / ifaces[mohoidx] truevslast = lvs[mohoidx] truevsjump = vsstep[mohoidx] for n, xdata in enumerate([truevslast, truecrust, truevsjump]): ax[1][n].axhline(truemoho, color='red', ls='--', lw=0.5, alpha=0.7) ax[1][n].axvline(xdata, color='red', ls='--', lw=0.5, alpha=0.7) return fig
def update_chain(self): print('New chain index:', self.chainidx) # if new chain is chosen self.modelmatrix, self.likes, self.noises, self.vpvss = self.chainarrays[ self.chainidx] nantmp = np.ones(self.modellength) * np.nan # reset vs and dep matrix to nan self.vs_step = np.ones((self.capacity, self.modellength)) * np.nan self.dep_step = np.ones((self.capacity, self.modellength)) * np.nan for i, model in enumerate(self.modelmatrix): # if nan model, the first element is also nan ! if ~np.isnan(model[0]): vp, vs, dep = Model.get_stepmodel(model, vpvs=self.vpvss[i], mantle=self.mantle) dep[-1] = self.priors['z'][-1] * 1.5 self.vs_step = np.roll(self.vs_step, -1, axis=0) # rolling up models vs = nantmp[:vs.size] = vs self.vs_step[-1][:vs.size] = vs self.dep_step = np.roll(self.dep_step, -1, axis=0) # rolling up models dep = nantmp[:dep.size] = dep self.dep_step[-1][:dep.size] = dep # update title self.axes[0].set_title('Chain %d' % self.chainidx) lastmodel = model lastvpvs = self.vpvss[-1] # immediately update data fit lines vp, vs, h = Model.get_vp_vs_h(lastmodel, vpvs=lastvpvs, mantle=self.mantle) ymod = self.compute_synth(h, vs, vp) for i, tline in enumerate(self.targetlines): if tline is not None: tline.set_ydata(ymod[i]) # # create LineCollection and update velocity models segments = [ np.column_stack([x, y]) for x, y in zip(self.vs_step, self.dep_step) ] self.modelcollection.set_segments(segments) self.likeline.set_ydata(self.likes) self.axes[3].set_ylim( [np.nanmin(self.likes) * 0.999, np.nanmax(self.likes) * 1.001]) # vpvs a = np.repeat(([0, 1], ), self.capacity, axis=0) b = np.array([[v] * 2 for v in self.vpvss]) segments = [np.column_stack([x, y]) for x, y in zip(b, a)] self.vpvscollection.set_segments(segments) for i, sline in enumerate(self.sigmalines): if sline is not None: ref = self.targetrefs[i] idx = self.targetrefs.index(ref) sline.set_ydata(self.noises.T[1::2][idx]) self.axes[4].set_ylim([ np.nanmin(self.noises.T[1::2]) * 0.98, np.nanmax(self.noises.T[1::2]) * 1.02 ]) self.fig.canvas.draw_idle()