예제 #1
0
def plot_subsurface_01():
    """
    Create a basic graben geology using recursive procedural API
    :return: nothing (but plot the result)
    """
    z0, L, NL = 0.0, 10000.0, 30
    h = L / NL
    print("z0, L, nL, h =", z0, L, NL, h)
    mesh = baseline_tensor_mesh(NL, h, centering='CCN')
    survey = survey_gridded_locations(L, L, 20, 20, z0)
    history = [Basement()]
    history.append(StratigraphicLayer(history[-1]))
    history.append(StratigraphicLayer(history[-1]))
    history.append(PlanarFault(history[-1]))
    history.append(PlanarFault(history[-1]))
    # Basic stratigraphy
    histpars = [3.0, 1900.0, 2.5, 2500.0, 2.0]
    # Fault #1
    histpars.extend([-4000.0, 0.0, 0.0, 0.940, 0.0, 0.342, -4200.0])
    # Fault #2
    histpars.extend([+4000.0, 0.0, 0.0, 0.940, 0.0, -0.342, 4200.0])
    fwdmodel = DiscreteGravity(mesh, survey, history[0])
    fwdmodel.gfunc = Basement()
    fwdmodel.edgemask = profile_timer(fwdmodel.calc_gravity, h, [1.0])
    for m, part_history in enumerate(history):
        fwdmodel.gfunc = part_history
        npars = np.sum([e.npars for e in history[:m + 1]])
        profile_timer(fwdmodel.calc_gravity, h, histpars[:npars])
        fwdmodel.fwd_data -= fwdmodel.edgemask * fwdmodel.voxmodel.mean()
        fig = plt.figure(figsize=(12, 4))
        ax1 = plt.subplot(121)
        fwdmodel.plot_model_slice(ax=ax1)
        ax2 = plt.subplot(122)
        fwdmodel.plot_gravity(ax=ax2)
        plt.show()
예제 #2
0
def run_mcmc(model, Nsamp=100000, Nburn=20000, Nthin=100, temper=False):
    """
    Runs the MCMC using riemann.
    :param model: GeoModel instance
    :return: chain
    """
    print("run_mcmc: running chain...")
    model.history.set_to_prior_draw()
    histpars = model.history.serialize()
    proposal = AMRW(0.1 * np.diag(model.stepsizes),
                    1000,
                    marginalize=False,
                    smooth_adapt=False)
    if temper:
        sampler = PTSampler(model,
                            proposal,
                            np.array(histpars),
                            betas=0.5**np.arange(10))
    else:
        sampler = Sampler(model, proposal, np.array(histpars))
    profile_timer(sampler.run, Nsamp)
    chain = np.array(sampler._chain_thetas)
    accept_frac = np.mean(chain[1:] - chain[:-1] != 0)
    print("run_mcmc: chain finished; acceptance fraction =", accept_frac)
    # Calculate autocorrelation time using emcee module
    # It's only used in this one place, so if user doesn't have it,
    # don't make them install it just to run the MCMC itself
    try:
        import emcee
        tau = emcee.autocorr.integrated_time(chain, quiet=True)
        print("run_mcmc:  autocorrelation time = ", tau)
    except:
        print("run_mcmc:  install emcee to use its autocorr submodule")
        pass
    return chain[Nburn:Nsamp:Nthin]
예제 #3
0
def main():
    """
    The main routine
    """
    parser = argparse.ArgumentParser(
        description="Running figures for Blockworlds paper.")
    parser.add_argument('--model_ids',
                        metavar='model_num',
                        type=int,
                        nargs='+',
                        help="run one or more models")
    parser.add_argument('--run_mcmc',
                        action='store_true',
                        default=False,
                        help="run MCMC for one or more models")
    parser.add_argument('--run_sliceplots',
                        action='store_true',
                        default=False,
                        help="run slice plots for one or more models")
    parser.add_argument('--results_table',
                        action='store_true',
                        default=False,
                        help="tabulate summary statistics for MCMC runs")
    parser.add_argument('--run_traceplots',
                        action='store_true',
                        default=False,
                        help="make trace plots for models from MCMC runs")
    args = parser.parse_args()

    # Parse list of model IDs and link to configurations
    if args.model_ids is not None:
        run_model_confs = [geo_model_confs[i] for i in args.model_ids]
    else:
        run_model_confs = []

    # Re-run MCMC experiments
    if args.run_mcmc:
        profile_timer(run_model_sampling, run_model_confs)

    # Re-run slice plots
    if args.run_sliceplots:
        for gconf in run_model_confs:
            slice_figures(gconf)

    if args.results_table:
        sampling_table(run_model_confs)

    if args.run_traceplots:
        for gconf in run_model_confs:
            traceplots(gconf)
예제 #4
0
def plot_subsurface_02():
    """
    Create a basic graben geology using object-oriented API
    :return: nothing (but plot the result)
    """
    # Initialize basic grid parameters
    z0, L, NL = 0.0, 10000.0, 30
    h = L / NL
    print("z0, L, nL, h =", z0, L, NL, h)
    mesh = baseline_tensor_mesh(NL, h, centering='CCN')
    survey = survey_gridded_locations(L, L, 20, 20, z0)
    # Create the history
    history = gen_two_fault_model_demo([
        3.0, 1900.0, 2.5, 2500.0, 2.0, -4000.0, 0.0, +20.0, 0.0, -4200.0,
        +4000.0, 0.0, -20.0, 0.0, +4200.0
    ])
    # Add a final Fold event just for laughs
    history.add_event(
        FoldEvent([('nth', 'nph', vMFDist(th0=+0.0, ph0=0.0, kappa=100)),
                   ('pitch', UniGaussianDist(mean=0.0, std=30.0)),
                   ('phase', UniformDist(mean=0.0, width=360.0)),
                   ('wavelength', UniGaussianDist(mean=3000.0, std=300.0)),
                   ('amplitude', UniGaussianDist(mean=300.0, std=50.0))]))
    print("history.pars =", history.serialize())
    # Can also set parameters all at once -- good for running MCMC
    history.set_to_prior_draw()
    history.deserialize([
        3.0, 1900.0, 2.5, 2500.0, 2.0, -4000.0, 0.0, +20.0, 0.0, -4200.0,
        +4000.0, 0.0, -20.0, 0.0, +4200.0, -0.0, 0.0, 0.0, 0.0, 3000.0, 300.0
    ])
    print("history.pars =", history.serialize())
    print("history.prior =", history.logprior())
    # Plot a cross-section
    fwdmodel = DiscreteGravity(mesh, survey, history.event_list[0])
    fwdmodel.gfunc = history.event_list[0].rockprops
    fwdmodel.edgemask = profile_timer(fwdmodel.calc_gravity, h)
    for m, event in enumerate(history.event_list):
        print("current event:", event)
        fwdmodel.gfunc = lambda r, h: np.array(event.rockprops(r, h))
        profile_timer(fwdmodel.calc_gravity, h)
        fwdmodel.fwd_data -= fwdmodel.edgemask * fwdmodel.voxmodel.mean()
        fig = plt.figure(figsize=(12, 4))
        ax1 = plt.subplot(121)
        fwdmodel.plot_model_slice(ax=ax1)
        ax2 = plt.subplot(122)
        fwdmodel.plot_gravity(ax=ax2)
        plt.show()
예제 #5
0
def plot_subsurface_02():
    """
    Create a basic graben geology using object-oriented API
    :return: nothing (but plot the result)
    """
    # Initialize basic grid parameters
    z0, L, NL = 0.0, 10000.0, 30
    h = L / NL
    print("z0, L, nL, h =", z0, L, NL, h)
    mesh = baseline_tensor_mesh(NL, h, centering='CCN')
    survey = survey_gridded_locations(L, L, 20, 20, z0)
    # Create the history
    history = GeoHistory()
    history.add_event(BasementEvent(3.0))
    history.add_event(StratLayerEvent(1900.0, 2.5))
    history.add_event(StratLayerEvent(2500.0, 2.0))
    history.add_event(PlanarFaultEvent(-4000.0, 0.0, +20.0, 0.0, -4200.0))
    history.add_event(PlanarFaultEvent(+4000.0, 0.0, -20.0, 0.0, +4200.0))
    print("history.pars =", history.serialize())
    # Can also set parameters all at once -- good for running MCMC
    history = GeoHistory()
    history.add_event(BasementEvent())
    history.add_event(StratLayerEvent())
    history.add_event(StratLayerEvent())
    history.add_event(PlanarFaultEvent())
    history.add_event(PlanarFaultEvent())
    history.deserialize([
        3.0, 1900.0, 2.5, 2500.0, 2.0, -4000.0, 0.0, +20.0, 0.0, -4200.0,
        +4000.0, 0.0, -20.0, 0.0, +4200.0
    ])
    print("history.pars =", history.serialize())
    # Plot a cross-section
    fwdmodel = DiscreteGravity(mesh, survey, history.event_list[0])
    fwdmodel.gfunc = BasementEvent(1.0).rockprops
    fwdmodel.edgemask = profile_timer(fwdmodel.calc_gravity, h)
    for m, event in enumerate(history.event_list):
        print("current event:", event)
        fwdmodel.gfunc = lambda r, h: np.array(event.rockprops(r, h))
        profile_timer(fwdmodel.calc_gravity, h)
        fwdmodel.fwd_data -= fwdmodel.edgemask * fwdmodel.voxmodel.mean()
        fig = plt.figure(figsize=(12, 4))
        ax1 = plt.subplot(121)
        fwdmodel.plot_model_slice(ax=ax1)
        ax2 = plt.subplot(122)
        fwdmodel.plot_gravity(ax=ax2)
        plt.show()
예제 #6
0
def vet_slice(my_model, z1_idx, z2_idx, zdelt1, zdelt2, Nz, showtitle=False):
    histpars = np.array(my_model.history.serialize())
    z1_0, z2_0 = histpars[z1_idx], histpars[z2_idx]
    z1_vals = np.linspace(z1_0 - 0.5 * zdelt1, z1_0 + 0.5 * zdelt1, Nz)
    z2_vals = np.linspace(z2_0 - 0.5 * zdelt2, z2_0 + 0.5 * zdelt2, Nz)
    xg, yg, Lg = profile_timer(run_grid, my_model, z1_vals, z2_vals, z1_idx,
                               z2_idx)
    show_contours(xg,
                  yg,
                  Lg,
                  z1_vals,
                  z2_vals,
                  z1_0,
                  z2_0,
                  showtitle=showtitle)
    return xg, yg, Lg
예제 #7
0
def compare_antialiasing(N_features_gp=3):
    """
    Demo different functional forms for antialiasing
    :param N_features_gp: number of GP features to use (1, 2, or 3)
    :return: nothing (yet)
    """
    from scipy.special import erf

    def parpV1(x):  # piecewise linear interpolation
        r = 1.0 * x + 0.5
        r[r < 0.0] = 0.0
        r[r > 1.0] = 1.0
        return r

    def parpV2(x):  # error function (cdf of a Gaussian)
        r = 1.0 * (x < 0)
        idx = (np.abs(r) < 100)
        r[idx] = 0.5 * (1 + erf(2.15 * x[idx]))
        return r

    def parpV3(x, gp):  # GP interpolation (w/one feature, for display)
        # Grab the underlying GP and evaluate it using a single feature
        # This is only for plots; residuals calculated using all features
        r = gp.predict_1d(x)
        return r

    # Generate some data and go
    Xtrain, Ytrain = generate_random_data(1000, uniform_omega=True)
    gp = GaussianProcessAntialiasing(N_features=N_features_gp)
    profile_timer(gp.fit, Xtrain, Ytrain)

    # Show some typical curves
    pars, pV = generate_random_data(200)
    r0, n = pars[:, :3], pars[:, 3:]
    fig = plt.figure(figsize=(10, 4))
    plt.subplot(121)
    resids1, resids2, resids3 = [], [], []
    for ni in n:
        x = np.dot(r0, ni)
        X = np.array([np.concatenate([r0i, ni]) for r0i in r0])
        y = np.array([partial_volume(mesh_eval, r0i, ni) for r0i in r0])
        resids1.extend(y - parpV1(x))
        resids2.extend(y - parpV2(x))
        resids3.extend(y - gp.predict(X))
        idx = np.argsort(x)
        plt.plot(x[idx], y[idx], c='gray', lw=0.5)
    x = np.linspace(-1.0, 1.0, 41)
    plt.plot(x, parpV1(x), c='r', lw=2, ls='--', label="piecewise")
    plt.plot(x, parpV2(x), c='b', lw=2, ls='--', label="softmax")
    plt.plot(x,
             parpV3(x, gp),
             c='g',
             lw=2,
             ls='--',
             label="GP ($N_\mathrm{{pars}} = {}$)".format(N_features_gp))
    plt.xlabel("Coverage Parameter $(\mathbf{r_0 \cdot n})/h$")
    plt.ylabel("Cumulative Partial Volume / $h^3$")
    plt.legend()
    plt.subplot(122)
    plt.hist(resids1, bins=50, range=(-0.1, 0.1), alpha=0.5, label='piecewise')
    plt.hist(resids2, bins=50, range=(-0.1, 0.1), alpha=0.5, label='softmax')
    plt.hist(resids3,
             bins=50,
             range=(-0.1, 0.1),
             alpha=0.5,
             label="GP ($N_\mathrm{{pars}} = {}$)".format(N_features_gp))
    print("resids(piecewise) mean, std = {:.3g}, {:.3g}".format(
        np.mean(resids1), np.std(resids1)))
    print("resids(softmax)   mean, std = {:.3g}, {:.3g}".format(
        np.mean(resids2), np.std(resids2)))
    print("resids(GP)        mean, std = {:.3g}, {:.3g}".format(
        np.mean(resids3), np.std(resids3)))
    plt.xlabel("Residuals in Partial Volume / $h^3$")
    plt.legend()
    plt.subplots_adjust(bottom=0.15)
    plt.show()
예제 #8
0
def gradtest():
    """
    Testing ground for adding automatic gradients to GeoFuncs
    :return: nothing (yet)
    """
    # All the same setup as before
    z0, L, NL = 0.0, 10000.0, 15
    h = L / NL
    print("z0, L, nL, h =", z0, L, NL, h)
    mesh = baseline_tensor_mesh(NL, h, centering='CCN')
    survey = survey_gridded_locations(L, L, 20, 20, z0)
    history = [Basement()]
    history.append(StratigraphicLayer(history[-1]))
    history.append(StratigraphicLayer(history[-1]))
    history.append(PlanarFault(history[-1]))
    history.append(PlanarFault(history[-1]))
    # Basic stratigraphy
    histpars = [3.0, 1900.0, 2.5, 2500.0, 2.0]
    # Fault #1
    histpars.extend([-4000.0, 0.0, 0.0, 0.940, 0.0, 0.342, -4200.0])
    # Fault #2
    histpars.extend([+4000.0, 0.0, 0.0, 0.940, 0.0, -0.342, 4200.0])
    # Forward model stuff
    fwdmodel = DiscreteGravity(mesh, survey, history[0])
    fwdmodel.gfunc = Basement()
    fwdmodel.edgemask = profile_timer(fwdmodel.calc_gravity, h, [1.0])

    # Test gradient of anti-aliasing function
    x = np.linspace(-1, 1, 4001)
    t0 = time.time()
    g = [soft_if_then_piecewise_ifthen(xi, 0.0, 1.0, 1.0) for xi in x]
    t1 = time.time()
    g = soft_if_then_piecewise(x, np.zeros(x.shape), np.ones(x.shape), 1.0)
    t2 = time.time()
    g = soft_if_then_logjit(x, np.zeros(x.shape), np.ones(x.shape), 1.0)
    t3 = time.time()
    print("looped:    {:.2e} sec".format(t1 - t0))
    print("vector:    {:.2e} sec".format(t2 - t1))
    print("logistic:  {:.2e} sec".format(t3 - t2))
    # a vectorized way to take the 1-D derivative
    logistic_jac = jacobian(soft_if_then_logjit)
    dg = np.sum(logistic_jac(x, 0.0, 1.0, 1.0), axis=0)
    fig = plt.figure()
    plt.plot(x, g)
    plt.plot(x, dg, ls='--')
    plt.show()

    # Go through the history event by event
    for m, part_history in enumerate(history):
        fwdmodel.gfunc = part_history
        npars = np.sum([e.npars for e in history[:m + 1]])
        profile_timer(fwdmodel.calc_gravity, h, histpars[:npars])
        fwdmodel.fwd_data -= fwdmodel.edgemask * fwdmodel.voxmodel.mean()
        fig = plt.figure(figsize=(12, 4))
        ax1 = plt.subplot(121)
        fwdmodel.plot_model_slice(ax=ax1)
        ax2 = plt.subplot(122)
        fwdmodel.plot_gravity(ax=ax2)
        plt.show()

    # Finite differences, hrngh
    t0 = time.time()
    dgfd = []
    for i in range(len(histpars)):
        hp1, hp2 = np.array(histpars), np.array(histpars)
        dth = 1e-7 * max(1, histpars[i])
        hp1[i] -= dth
        vox1 = history[-1](fwdmodel.mesh.gridCC, h, hp1)
        hp2[i] += dth
        vox2 = history[-1](fwdmodel.mesh.gridCC, h, hp2)
        dgfd.append((vox2 - vox1) / (2 * dth))
    dgfd = np.array(dgfd).T
    t1 = time.time()
    print("dgfd ran in {:.3f} seconds".format(t1 - t0))

    # Demonstrate an end-to-end derivative w/rt parameters
    gfuncjac = profile_timer(jacobian, history[-1], 2)
    gfuncjac = jit(gfuncjac)
    jhistpars = jnp.array(histpars)
    dg = profile_timer(gfuncjac, fwdmodel.mesh.gridCC, h, jhistpars)
    print("dg.shape =", dg.shape)
    for i in range(3):
        dg = profile_timer(gfuncjac, fwdmodel.mesh.gridCC, h, jhistpars)
    for dgi in dg.T:
        fwdmodel.voxmodel = np.array(dgi)
        print("voxmodel.mean, voxmodel.std =", fwdmodel.voxmodel.mean(),
              fwdmodel.voxmodel.std())
        print("voxmodel.isnan.sum() =", np.sum(np.isnan(fwdmodel.voxmodel)))
        # fwdmodel.plot_model_slice()
        # plt.show()

    idx = (np.abs(dgfd) > 1e-9)
    resids = 0.5 * (dgfd[idx] - dg[idx]) / (np.abs(dg[idx] + dgfd[idx]))
    print("mean fractional derivative error: {:.3g} +/- {:.3g}".format(
        resids.mean(), resids.std()))
예제 #9
0
def fit_antialiasing():
    """
    Look for alternative models that can deliver GP-like accuracy, quickly
    :return: nothing (yet)
    """

    # Generate some random data
    np.random.seed(42)
    Xtrain, Ytrain = generate_random_data(1000, uniform_omega=True)
    # Transform Xtrain to the set of features useful in GP regression
    gp = GaussianProcessAntialiasing(N_features=3)
    Xtrain = gp._preprocess(Xtrain)

    # Recursive experimental design to avoid double-counting cross-terms
    def indices(N, order, terms=[]):
        termslist = [ ]
        # Termination case
        if len(terms) == order:
            return terms
        # Starting case
        elif len(terms) == 0:
            ilo = 0
        # Recursion
        else:
            ilo = terms[-1]
        for i in range(ilo, N):
            termslist.append(indices(N, order, terms=(terms + [i])))
        termslist = np.concatenate(termslist).reshape(-1, order)
        return termslist

    # Unique cross-terms
    def generate_cross_terms(X, order=1):
        Xlist = np.ones(shape=(len(X), 1))
        for k in range(1, order+1):
            for idx in indices(X.shape[1], k):
                cols = np.array([X[:,i] for i in idx])
                newcol = np.prod(cols, axis=0).reshape(-1, 1)
                Xlist = np.hstack([Xlist, newcol])
        return np.array(Xlist)

    # Hand-picked features up to order 3 based on symmetries of the cube
    def selected_features(X):
        rdotn, tanth, tanph = X.T
        # Odd terms in rdot; even terms in tanth and tanph
        Xp = np.hstack([rdotn.reshape(-1,1),
                        (rdotn**3).reshape(-1,1)])
        return Xp

    Xtrain = selected_features(Xtrain)
    # Xtrain = generate_cross_terms(Xtrain, order=3)
    print("Xtrain.shape =", Xtrain.shape)

    # Define a predictor and/or an objective function
    def linmodel(X, *p):
        Xp = np.dot(X, p)
        Ypred = np.zeros(Xp.shape)
        idx_ok = (Xp < 100.0)
        Ypred[idx_ok] = 0.5*(1 + np.tanh(Xp[idx_ok]))
        # experiment:  can a polynomial do just as well?
        # Ypred[idx_ok] = 0.5*(1 + Xp[idx_ok])
        return Ypred

    def logpost(p, *args):
        # print("args =", args)
        X, Y, Lreg = args
        Ypred = linmodel(X, *p)
        resids = Ypred - Y
        # maximizing log probability = minimizing -log probability
        return np.sum((Ypred-Y)**2) + Lreg*np.sum(np.abs(p))

    # Let's get out our curve-fitting apparatus
    from scipy.optimize import curve_fit
    p0 = np.zeros(Xtrain.shape[1])
    popt, pcov = profile_timer(curve_fit, linmodel, Xtrain, Ytrain, p0)
    resids = (linmodel(Xtrain, *popt)-Ytrain)
    print("linear model fit:  popt =", popt)
    print("resids:  mean = {}, std = {}".format(resids.mean(), resids.std()))

    # Let's add the lasso penalty now
    # Find the regularization strength by cross-validation
    from scipy.optimize import minimize
    popts = [ ]
    objfevals = [ ]
    Lregvals = 10**np.arange(-3.0, 5.5, 0.5)
    for Lreg in Lregvals:
        results = profile_timer(minimize, logpost, p0, (Xtrain, Ytrain, Lreg),
                                method='Nelder-Mead', options={'maxiter': 10000})
        popt = np.array(results.x)
        objfunc = logpost(popt, Xtrain, Ytrain, Lreg)
        print("Lreg = {}:  objfunc = {}".format(Lreg, objfunc))
        popts.append(popt)
        objfevals.append(objfunc)
    # Select threshold value of parameters favoring shrinkage
    objfevals = np.array(objfevals)
    idx = np.arange(len(Lregvals))
    iopt = len(idx[objfevals < 2.0*np.min(objfevals)])
    print("selected Lreg = {}, popt = {}".format(Lregvals[iopt], popts[iopt]))
    resids = (linmodel(Xtrain, *popts[iopt]) - Ytrain)
    print("resids:  mean = {}, std = {}".format(resids.mean(), resids.std()))
예제 #10
0
def compare_antialiasing(N_features_gp=3, vertical=False, histlogy=False):
    """
    Demo different functional forms for antialiasing
    :param N_features_gp: number of GP features to use (1, 2, or 3)
    :param vertical: stack plots vertically (True) or side by side (False)?
    :param histlogy: use logarithmic y-axis for histogram? (default False)
    :return: nothing (yet)
    """

    def parpV1(x):          # piecewise linear interpolation
        r = 1.0*x + 0.5
        r[r < 0.0] = 0.0
        r[r > 1.0] = 1.0
        return r

    def parpV2(x):          # error function (cdf of a Gaussian)
        r = 1.0 * (x < 0)
        idx = (np.abs(r) < 100)
        r[idx] = 0.5*(1 + np.tanh(2.2*x[idx] + 3.2*(x[idx])**3))
        return r

    def parpV3(x, gp):      # GP interpolation (w/one feature, for display)
        # Grab the underlying GP and evaluate it using a single feature
        # This is only for plots; residuals calculated using all features
        r = gp.predict_1d(x)
        return r

    # Generate some data and go
    Xtrain, Ytrain = generate_random_data(1000, uniform_omega=True)
    gp = GaussianProcessAntialiasing(N_features=N_features_gp)
    profile_timer(gp.fit, Xtrain, Ytrain)

    # Show some typical curves
    pars, pV = generate_random_data(200)
    r0, n = pars[:,:3], pars[:,3:]
    if vertical:
        figsize=(4.8, 6)
    else:
        figsize=(10, 6)
    fig = plt.figure(figsize=figsize)
    plt.subplot(211)
    resids1, resids2, resids3 = [ ], [ ], [ ]
    for ni in n:
        x = np.dot(r0, ni)
        X = np.array([np.concatenate([r0i, ni]) for r0i in r0])
        y = np.array([partial_volume(mesh_eval, r0i, ni) for r0i in r0])
        resids1.extend(y - parpV1(x))
        resids2.extend(y - parpV2(x))
        resids3.extend(y - gp.predict(X))
        idx = np.argsort(x)
        plt.plot(x[idx], y[idx], c='gray', lw=0.5)
    x = np.linspace(-1.0, 1.0, 41)
    plt.plot(x, parpV1(x), c='r', lw=2, ls='--', label="piecewise")
    plt.plot(x, parpV2(x), c='b', lw=2, ls='--', label="linear model")
    plt.plot(x, parpV3(x,gp), c='g', lw=2, ls='--',
             label="GP ($N_\mathrm{{pars}} = {}$)".format(N_features_gp))
    plt.xlabel("Coverage Parameter $(\mathbf{r_0 \cdot n})/h$")
    plt.ylabel("Cumulative Partial Volume / $h^3$")
    plt.legend()

    # Histograms
    Nhistbins = 50
    histrange = (-0.1, 0.1)
    plt.subplot(212)
    plt.hist(resids1, bins=Nhistbins, range=histrange, log=histlogy,
             color='r', alpha=0.5, label='piecewise')
    plt.hist(resids2, bins=Nhistbins, range=histrange, log=histlogy,
             color='b', alpha=0.5, label='linear model')
    plt.hist(resids3, bins=Nhistbins, range=histrange, log=histlogy,
             color='g', alpha=0.5,
             label="GP ($N_\mathrm{{pars}} = {}$)".format(N_features_gp))
    print("resids(piecewise)    mean, std, mad, max "
          "= {:.3g}, {:.3g}, {:.3g}, {:.3g}"
          .format(np.mean(resids1), np.std(resids1),
                  np.mean(np.abs(resids1)), np.max(np.abs(resids1))))
    print("resids(linear model) mean, std, mad, max "
          "= {:.3g}, {:.3g}, {:.3g}, {:.3g}"
          .format(np.mean(resids2), np.std(resids2),
                  np.mean(np.abs(resids2)), np.max(np.abs(resids2))))
    print("resids(GP)           mean, std, mad, max "
          "= {:.3g}, {:.3g}, {:.3g}, {:.3g}"
          .format(np.mean(resids3), np.std(resids3),
                  np.mean(np.abs(resids3)), np.max(np.abs(resids3))))
    plt.xlabel("Residuals in Partial Volume / $h^3$")
    plt.legend()
    if vertical:
        # for vertical format
        plt.subplots_adjust(bottom=0.08, top=0.92,
                            left=0.12, right=0.88, hspace=0.35)
        # save as figure for paper
        plt.savefig("compare_antialiasing.eps")
    else:
        # for horizontal format
        plt.subplots_adjust(bottom=0.15, top=0.88,
                            left=0.08, right=0.92, wspace=0.25)
    plt.show()
예제 #11
0
def slice_figures(gconf):

    # Don't make us re-do any of these scans if we don't have to
    model_idx = gconf.model_index
    pklfn = "sliceplots/implicit_{}_slices.pkl".format(model_idx)
    pklfn = "implicit_{}_slices.pkl".format(model_idx)

    # Initialize two GeoModels at different resolutions but same parameters
    L, NL, Nz = gconf.L, gconf.NL, 30
    model = initialize_geomodel(gconf)
    gconf.NL = 75
    model_hires = initialize_geomodel(gconf)
    gconf.NL = NL
    # Extract the forward models from these and make the data agree
    model.dsynth = model_hires.dsynth

    # Set up the three-column plots
    fwdmodels = [
        model.fwdmodel, model_hires.fwdmodel, model.fwdmodel,
        model_hires.fwdmodel
    ]
    akasettings = [False, False, True, True]

    # Actual parameters passed to plotting routine
    # See GeoConf definitions at top of file for actual slices plotted
    sliceparlist = [[model] + row + [Nz] for row in gconf.sliceplotlist]
    rowlabels = "abcdefghijklmnopqrstuvwxyz"
    collabels = [
        "Coarse Aliased", "Fine Aliased", "Coarse Anti-Aliased",
        "Fine Anti-Aliased"
    ]

    # First row should be slices
    fig = plt.figure(figsize=(14, 3))
    for i in range(len(fwdmodels)):
        fm, aka = fwdmodels[i], akasettings[i]
        model.set_fwdmodel(fm)
        model.set_antialiasing(aka)
        profile_timer(fm.calc_gravity, model.h)
        # Plot the cross-section
        ax1 = plt.subplot(1, len(fwdmodels), i + 1)
        fm.plot_model_slice(ax=ax1,
                            axlabels=(i == len(fwdmodels) - 1),
                            grid=(i % 2 == 0))
        ax1.set_title(collabels[i])
        ax1.set_xlabel("x (m)")
        if i == 0:
            plt.ylabel("z (m)")
        else:
            plt.ylabel("")

    # On last plot, add labels to stratigraphic layers; a bit of a hack,
    # but all the models have 3 layers so it should be roughly fine
    if model_idx < 5:
        plt.text(-450, -950, 'Basement', ha='left', color='b', size=12)
        plt.text(-450, -500, 'Layer 1', ha='left', color='k', size=12)
        plt.text(-450, -150, 'Layer 2', ha='left', color='white', size=12)
    else:
        plt.text(450, -950, 'Basement', ha='right', color='b', size=12)
        plt.text(450, -450, 'Layer 1', ha='right', color='k', size=12)
        plt.text(450, -100, 'Layer 2', ha='right', color='white', size=12)

    # plt.subplots_adjust(top=0.85, bottom=0.15, hspace=0.35, wspace=0.35)
    plt.subplots_adjust(bottom=0.2, left=0.08, right=0.92, wspace=0.35)
    figfn = "sliceplots/implicit_{}_slices.eps".format(model_idx)
    plt.savefig(figfn)

    # Now scan through all the posteriors
    xg, yg, Lg, args = [], [], [], []
    for j, slicepars in enumerate(sliceparlist):
        fig = plt.figure(figsize=(14, 3))
        for i in range(len(fwdmodels)):
            fm, aka = fwdmodels[i], akasettings[i]
            model.set_fwdmodel(fm)
            model.set_antialiasing(aka)
            ax = plt.subplot(1, len(fwdmodels), i + 1)
            xgji, ygji, Lgji = vet_slice(*slicepars, showtitle=False)
            plt.xlabel(gconf.parnames[slicepars[1]])
            if i == 0:
                plt.ylabel(gconf.parnames[slicepars[2]])
            # Mark true values
            truepars = model.history.serialize()
            x0 = truepars[slicepars[1]]
            y0 = truepars[slicepars[2]]
            plt.plot(x0, y0, marker='+', ms=15, mew=3, color='red')
            # Save to final list
            args.append(slicepars[1:])
            xg.append(xgji)
            yg.append(ygji)
            Lg.append(Lgji)
        # plt.subplots_adjust(top=0.85, bottom=0.15, hspace=0.35, wspace=0.35)
        plt.subplots_adjust(bottom=0.2, left=0.08, right=0.92, wspace=0.35)
        figfn = "sliceplots/implicit_{}{}_slices.eps".format(
            model_idx, rowlabels[j])
        plt.savefig(figfn)

    pklfn = "sliceplots/implicit_{}_slices.pkl".format(model_idx)
    with open(pklfn, 'wb') as pklfile:
        pickle.dump([xg, yg, Lg, args], pklfile)