Example #1
0
    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
Example #2
0
    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)
Example #3
0
    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
Example #4
0
    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
Example #5
0
    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
Example #6
0
    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()
Example #7
0
    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
Example #8
0
    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
Example #9
0
    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
Example #10
0
    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
Example #11
0
    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()