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()
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]
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)
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()
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()
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
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()
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()))
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()))
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()
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)