def fwd_grav_fatiando(): """ GravMag: 3D imaging using the migration method on synthetic gravity data (more complex model + noisy data) """ # Make some synthetic gravity data from a simple prism model za = 5000 zb = 7000 model = [mesher.Prism(-4000, 0, -4000, -2000, za, zb, {'density': 1200})] #, # mesher.Prism(-1000, 1000, -1000, 1000, 1000, 7000, {'density': -800}), # mesher.Prism(2000, 4000, 3000, 4000, 0, 2000, {'density': 600})] # Calculate on a scatter of points to show that migration doesn't need gridded # data # xp, yp, zp = gridder.scatter((-6000, 6000, -6000, 6000), 1000, z=0) shape = (25, 25) xp, yp, zp = gridder.regular((-5000, 5000, -5000, 5000), shape, z=0) #gz = utils.contaminate(prism.gz(xp, yp, zp, model), 0.1) gz = prism.gz(xp, yp, zp, model) # Plot the data shape = (50, 50) mpl.figure() mpl.axis('scaled') mpl.contourf(yp, xp, gz, shape, 30, interp=True) mpl.colorbar() mpl.plot(yp, xp, '.k') mpl.xlabel('East (km)') mpl.ylabel('North (km)') mpl.m2km() mpl.show() return xp, yp, zp, gz, shape, model
""" Seismic: Invert vertical seismic profile (VSP) traveltimes for the velocity of a layered model. """ import numpy from fatiando import utils from fatiando.seismic.profile import layered_straight_ray, LayeredStraight from fatiando.inversion.regularization import Damping from fatiando.vis import mpl # The limits in velocity and depths, respectively area = (0, 10000, 0, 100) vmin, vmax, zmin, zmax = area # Use the interactive functions of mpl to draw a layered model figure = mpl.figure() mpl.xlabel("Velocity (m/s)") mpl.ylabel("Depth (m)") thickness, velocity = mpl.draw_layers(area, figure.gca()) # Make some synthetic noise-corrupted travel-time data zp = numpy.arange(zmin + 0.5, zmax, 0.5) tts, error = utils.contaminate(layered_straight_ray(thickness, velocity, zp), 0.02, percent=True, return_stddev=True) # Make the solver and run the inversion using damping regularization # (assumes known thicknesses of the layers) solver = (LayeredStraight(tts, zp, thickness) + 0.1 * Damping(len(thickness))).fit() velocity_ = solver.estimate_ # Plot the results
""" GravMag: 2D forward modeling with polygons """ import numpy from fatiando import utils, mesher from fatiando.gravmag import talwani from fatiando.vis import mpl # Notice that the last two number are switched. # This way, the z axis in the plots points down. area = (-5000, 5000, 5000, 0) axes = mpl.figure().gca() mpl.xlabel("X") mpl.ylabel("Z") mpl.axis('scaled') polygons = [mesher.Polygon(mpl.draw_polygon(area, axes), {'density': 500})] xp = numpy.arange(-4500, 4500, 100) zp = numpy.zeros_like(xp) gz = talwani.gz(xp, zp, polygons) mpl.figure() mpl.axis('scaled') mpl.subplot(2, 1, 1) mpl.title(r"Gravity anomaly produced by the model") mpl.plot(xp, gz, '-k', linewidth=2) mpl.ylabel("mGal") mpl.xlim(-5000, 5000) mpl.subplot(2, 1, 2) mpl.polygon(polygons[0], 'o-k', linewidth=2, fill='k', alpha=0.5) mpl.xlabel("X")
from fatiando.geothermal.climsig import abrupt, SingleChange from fatiando.vis import mpl # Generating synthetic data using an ABRUPT model amp = 3 age = 54 # along a well at these depths zp = numpy.arange(0, 100, 1) temp, error = utils.contaminate(abrupt(amp, age, zp), 0.02, percent=True, return_stddev=True) # Preparing for the inversion data = SingleChange(temp, zp, mode='linear').config('levmarq', initial=[1, 1]) amp_, age_ = data.fit().estimate_ print "Trying to invert an abrupt change as linear" print " true: amp=%.3f age=%.3f" % (amp, age) print " estimated: amp=%.3f age=%.3f" % (amp_, age_) mpl.figure(figsize=(4, 5)) mpl.title("Residual well temperature") mpl.plot(temp, zp, 'ok', label='Observed') mpl.plot(data.predicted(), zp, '--r', linewidth=3, label='Predicted') mpl.legend(loc='lower right', numpoints=1) mpl.xlabel("Temperature (C)") mpl.ylabel("Z (m)") mpl.ylim(100, 0) mpl.show()
utils.contaminate(gravmag.prism.gz(x, y, z, model), noisegz), utils.contaminate(gravmag.prism.gxx(x, y, z, model), noise), utils.contaminate(gravmag.prism.gxy(x, y, z, model), noise), utils.contaminate(gravmag.prism.gxz(x, y, z, model), noise), utils.contaminate(gravmag.prism.gyy(x, y, z, model), noise), utils.contaminate(gravmag.prism.gyz(x, y, z, model), noise), utils.contaminate(gravmag.prism.gzz(x, y, z, model), noise)] with open('data.txt', 'w') as f: f.write(logger.header(comment='#')) f.write("# Noise corrupted gz and tensor components:\n") f.write("# noise = %g Eotvos\n" % (noise)) f.write("# noise = %g mGal\n" % (noisegz)) f.write("# coordinates are in meters\n") f.write("# gz in mGal and tensor in Eotvos\n") f.write("# x y z height gz gxx gxy gxz gyy gyz gzz\n") numpy.savetxt(f, numpy.transpose(data)) # Show it mpl.figure(figsize=(10, 9)) names = "z height gz gxx gxy gxz gyy gyz gzz".split() for i, comp in enumerate(data[2:]): mpl.subplot(3, 3, i + 1) mpl.axis('scaled') mpl.title(names[i]) levels = mpl.contourf(y*0.001, x*0.001, comp, shape, 8) mpl.contour(y*0.001, x*0.001, comp, shape, levels) if i == 3: mpl.ylabel('North = x (km)') if i == 7: mpl.xlabel('East = y (km)') mpl.show()
""" GravMag: Generate noise-corrupted gravity gradient tensor data """ from fatiando import mesher, gridder, gravmag, utils from fatiando.vis import mpl prisms = [mesher.Prism(-1000,1000,-1000,1000,0,2000,{'density':1000})] shape = (100,100) xp, yp, zp = gridder.regular((-5000, 5000, -5000, 5000), shape, z=-200) components = [gravmag.prism.gxx, gravmag.prism.gxy, gravmag.prism.gxz, gravmag.prism.gyy, gravmag.prism.gyz, gravmag.prism.gzz] print "Calculate the tensor components and contaminate with 5 Eotvos noise" ftg = [utils.contaminate(comp(xp, yp, zp, prisms), 5.0) for comp in components] print "Plotting..." mpl.figure(figsize=(14,6)) mpl.suptitle("Contaminated FTG data") names = ['gxx', 'gxy', 'gxz', 'gyy', 'gyz', 'gzz'] for i, data in enumerate(ftg): mpl.subplot(2,3,i+1) mpl.title(names[i]) mpl.axis('scaled') levels = mpl.contourf(xp*0.001, yp*0.001, data, (100,100), 12) mpl.colorbar() mpl.contour(xp*0.001, yp*0.001, data, shape, levels, clabel=False) mpl.show()
topo = np.loadtxt('etopo1-havai.gdf', skiprows=30, usecols=[-1], unpack=True) shape = (151, 151) area = (lon.min(), lon.max(), lat.min(), lat.max()) # First, lets calculate the gravity disturbance (e.g., the free-air anomaly) # We'll do this using the closed form of the normal gravity for the WGS84 # ellipsoid gamma = normal_gravity.gamma_closed_form(lat, height) disturbance = gravity - gamma # Now we can remove the effect of the Bouguer plate to obtain the Bouguer # anomaly. We'll use the standard densities of 2.67 g.cm^-3 for crust and 1.04 # g.cm^-3 for water. bouguer = disturbance - normal_gravity.bouguer_plate(topo) mpl.figure(figsize=(14, 3.5)) bm = mpl.basemap(area, projection='merc') mpl.subplot(131) mpl.title('Gravity (mGal)') mpl.contourf(lon, lat, gravity, shape, 60, cmap=mpl.cm.Reds, basemap=bm) mpl.colorbar(pad=0) mpl.subplot(132) mpl.title('Gravity disturbance (mGal)') amp = np.abs(disturbance).max() mpl.contourf(lon, lat, disturbance, shape, 60, cmap=mpl.cm.RdBu_r, basemap=bm, vmin=-amp, vmax=amp) mpl.colorbar(pad=0) mpl.subplot(133) mpl.title('Bouguer anomaly (mGal)') mpl.contourf(lon, lat, bouguer, shape, 60, cmap=mpl.cm.Reds, basemap=bm) mpl.colorbar(pad=0)
model = [ mesher.Prism(-4000, -3000, -4000, -3000, 0, 2000, {'magnetization': 2}), # a scalar magnetization means only induced mesher.Prism(-1000, 1000, -1000, 1000, 0, 2000, {'magnetization': 1}), # This prism will have magnetization in a different direction mesher.Prism(2000, 4000, 3000, 4000, 0, 2000, {'magnetization': utils.ang2vec(3, -10, 45)})] # induced + remanent # Create a regular grid at 100m height shape = (200, 200) area = bounds[:4] xp, yp, zp = gridder.regular(area, shape, z=-500) # Calculate the anomaly for a given regional field tf = prism.tf(xp, yp, zp, model, inc, dec) # Plot mpl.figure() mpl.title("Total-field anomaly (nT)") mpl.axis('scaled') mpl.contourf(yp, xp, tf, shape, 15) mpl.colorbar() mpl.xlabel('East y (km)') mpl.ylabel('North x (km)') mpl.m2km() mpl.show() # Show the prisms myv.figure() myv.prisms(model, 'magnetization') myv.axes(myv.outline(bounds), ranges=[i * 0.001 for i in bounds]) myv.wall_north(bounds) myv.wall_bottom(bounds) myv.show()
shape = (25, 25) x, y, z = gridder.regular([-5000, 5000, -5000, 5000], shape, z=0) tf = utils.contaminate(gravmag.prism.tf(x, y, z, model, inc, dec), 5) # Setup the layer grid = mesher.PointGrid([-7000, 7000, -7000, 7000], 1000, (50, 50)) # Estimate the magnetization intensity data = [gravmag.eqlayer.TotalField(x, y, z, tf, inc, dec)] # Need to apply enough damping so that won't try to fit the error as well intensity, predicted = gravmag.eqlayer.classic(data, grid, damping=0.02) grid.addprop('magnetization', intensity) residuals = tf - predicted[0] print "Residuals:" print "mean:", residuals.mean() print "stddev:", residuals.std() # Plot the layer and the fit mpl.figure(figsize=(14,4)) mpl.subplot(1, 3, 1) mpl.axis('scaled') mpl.title('Layer (A/m)') mpl.pcolor(grid.y, grid.x, grid.props['magnetization'], grid.shape) mpl.subplot(1, 3, 2) mpl.axis('scaled') mpl.title('Fit (nT)') levels = mpl.contour(y, x, tf, shape, 15, color='r') mpl.contour(y, x, predicted[0], shape, levels, color='k') mpl.subplot(1, 3, 3) mpl.title('Residuals (nT)') mpl.hist(residuals, bins=10) mpl.show() # Now I can forward model the layer at the south pole and check against the # true solution of the prism
maxit = int(duration / dt) stations = [[50000, 0]] # x, z coordinate of the seismometer snapshot = int(0.5 / dt) # Plot a snapshot of the simulation every 0.5 seconds simulation = wavefd.elastic_sh(mu, density, area, dt, maxit, sources, stations, snapshot, padding=50, taper=0.01) # This part makes an animation using matplotlibs animation API fig = mpl.figure(figsize=(14, 5)) ax = mpl.subplot(1, 2, 2) mpl.title('Wavefield') # Start with everything zero and grab the plot so that it can be updated later wavefield_plt = mpl.imshow(np.zeros(shape), extent=area, vmin=-10**(-5), vmax=10**(-5), cmap=mpl.cm.gray_r) mpl.points(stations, '^b') mpl.xlim(area[:2]) mpl.ylim(area[2:][::-1]) mpl.xlabel('x (km)') mpl.ylabel('z (km)') mpl.subplot(1, 2, 1) seismogram_plt, = mpl.plot([], [], '-k')
""" Vis: Plot a map using the Mercator map projection and pseudo-color """ from fatiando import gridder, utils from fatiando.vis import mpl # Generate some data to plot area = (-20, 40, 20, 80) shape = (100, 100) lon, lat = gridder.regular(area, shape) data = utils.gaussian2d(lon, lat, 10, 20, 10, 60, angle=45) # Now get a basemap to plot with some projection bm = mpl.basemap(area, 'merc') # And now plot everything passing the basemap to the plotting functions mpl.figure(figsize=(5, 8)) mpl.pcolor(lon, lat, data, shape, basemap=bm) mpl.colorbar() bm.drawcoastlines() bm.drawmapboundary() bm.drawcountries() mpl.draw_geolines(area, 10, 10, bm) mpl.show()
utils.contaminate(gravmag.prism.gxx(x, y, z, model), noise), utils.contaminate(gravmag.prism.gxy(x, y, z, model), noise), utils.contaminate(gravmag.prism.gxz(x, y, z, model), noise), utils.contaminate(gravmag.prism.gyy(x, y, z, model), noise), utils.contaminate(gravmag.prism.gyz(x, y, z, model), noise), utils.contaminate(gravmag.prism.gzz(x, y, z, model), noise) ] with open('data.txt', 'w') as f: f.write(logger.header(comment='#')) f.write("# Noise corrupted gz and tensor components:\n") f.write("# noise = %g Eotvos\n" % (noise)) f.write("# noise = %g mGal\n" % (noisegz)) f.write("# coordinates are in meters\n") f.write("# gz in mGal and tensor in Eotvos\n") f.write("# x y z height gz gxx gxy gxz gyy gyz gzz\n") numpy.savetxt(f, numpy.transpose(data)) # Show it mpl.figure(figsize=(10, 9)) names = "z height gz gxx gxy gxz gyy gyz gzz".split() for i, comp in enumerate(data[2:]): mpl.subplot(3, 3, i + 1) mpl.axis('scaled') mpl.title(names[i]) levels = mpl.contourf(y * 0.001, x * 0.001, comp, shape, 8) mpl.contour(y * 0.001, x * 0.001, comp, shape, levels) if i == 3: mpl.ylabel('North = x (km)') if i == 7: mpl.xlabel('East = y (km)') mpl.show()
dt = 0.004 # sample rate ds = 10. # depth increment f = 30. # approximated frequency ricker wavelet (scipy a=1/(2.f.dt)) disc = 10 # space discretization shp = (70, 560) nz, nx = shp # bellow load geologic model velociy model vmodel = utils.fromimage('pinchout.bmp', ranges=[2500., 3500.], shape=shp) twti = np.cumsum(ds/vmodel, axis=0)*2 # calculate irregular sampled twt times twt = np.arange(0, np.max(twti)+0.10, dt) # new twt times re-sampled to 4 ms dnx = int(nx/disc) twtvmodel = np.zeros((len(twt), dnx)) # velocity model in time and discretized for i in xrange(0, nx, disc): # set the time re-sample velocity model twtvmodel[:, int(i/disc)] = np.interp(twt, twti[:, i], vmodel[:, i]) zimp = np.ones(twtvmodel.shape)*1000.*twtvmodel # create impedance z = rho*v rc = (zimp[1:]-zimp[:-1])/(zimp[1:]+zimp[:-1]) # calculate reflection coefs fig = mpl.figure(figsize=(11, 7)) # plottings mpl.subplots_adjust(right=0.98, left=0.11, hspace=0.4, top=0.93, bottom=0.13) mpl.subplot2grid((3, 4), (0, 0), colspan=4) # plot rc model mpl.title("Zero-offset section reflection coefficients", fontsize=13, family='sans-serif', weight='bold') rcs = utils.matrix2stream(rc.transpose(), header={'delta': dt}) mpl.seismic_wiggle(rcs, normalize=True, scale=1.5, ranges=[0, nx]) # rc model wavelet = signal.ricker(255, 1/(2*f*dt)) # create wavelet samples = signal.filtfilt(wavelet, np.ones(len(wavelet)), rc, axis=0, padlen=len(twt)-2) # convolve rc*wavelet mpl.ylabel('twt (s)') mpl.subplot2grid((3, 4), (1, 0), colspan=4) # plot zero-offset traces traces = utils.matrix2stream(samples.transpose(), header={'delta': dt}) mpl.seismic_image(traces, cmap=mpl.pyplot.cm.jet, aspect='auto', ranges=[0, nx]) mpl.seismic_wiggle(traces, ranges=[0, nx], normalize=True) mpl.ylabel('twt (s)')
mesher.Prism(-1000,1000,-1000,1000,0,2000,{'density':-800}), mesher.Prism(1000,3000,2000,3000,0,1000,{'density':500})] area = (-5000, 5000, -5000, 5000) shape = (50, 50) z0 = -100 xp, yp, zp = gridder.regular(area, shape, z=z0) gz = utils.contaminate(gravmag.prism.gz(xp, yp, zp, prisms), 0.5) # Now do the upward continuation using the analytical formula height = 2000 dims = gridder.spacing(area, shape) gzcont = gravmag.transform.upcontinue(gz, height, xp, yp, dims) gztrue = gravmag.prism.gz(xp, yp, zp - height, prisms) mpl.figure(figsize=(14,6)) mpl.subplot(1, 2, 1) mpl.title("Original") mpl.axis('scaled') mpl.contourf(xp, yp, gz, shape, 15) mpl.contour(xp, yp, gz, shape, 15) mpl.subplot(1, 2, 2) mpl.title("Continued + true") mpl.axis('scaled') levels = mpl.contour(xp, yp, gzcont, shape, 12, color='b', label='Continued', style='dashed') mpl.contour(xp, yp, gztrue, shape, levels, color='r', label='True', style='solid') mpl.legend() mpl.show()
[wavefd.GaussSource(2000, 0, area, shape, 100.0, 25.)]] # z source or z compressional source # Get the iterator for the simulation dt = wavefd.maxdt(area, shape, np.max(pvel)) duration = 3.0 maxit = int(duration/dt) stations = [[2200+i*dx, 0] for i in range(220)] # x, z coordinate of the seismometers snapshot = int(0.004/dt) # Plot a snapshot of the simulation every 4 miliseconds print "dt for simulation is ", dt print "max iteration for simulation is ", maxit print "duration for simulation is ", duration simulation = wavefd.elastic_psv(lamb, mu, density, area, dt, maxit, sources, stations, snapshot, padding=50, taper=0.01) # This part makes an animation using matplotlibs animation API fig = mpl.figure(figsize=(12, 5)) # Start with everything zero and grab the plot so that it can be updated later mpl.imshow(pvel[::-1], extent=area, alpha=0.25) wavefield = mpl.imshow(np.zeros(shape), extent=area, vmin=-10**-7, vmax=10**-7, alpha=0.75, cmap=mpl.cm.gray_r) mpl.points(stations, '.k') mpl.ylim(area[2:][::-1]) mpl.xlabel('x (km)') mpl.ylabel('z (km)') mpl.m2km() times = np.linspace(0, maxit*dt, maxit) # the only way for getting the feedback response of the seimograms global seismograms # This function updates the plot every few timesteps def animate(i): # Simulation will yield panels corresponding to P and S waves because
x, y, z = gridder.scatter(area, 1000, z=-150, seed=0) tf = contaminate(sphere.tf(x, y, z, model, inc, dec), 5.0, seed=0) # Give the centers of the dipoles centers = [[3000, 3000, 1000], [7000, 7000, 1000]] # Estimate the magnetization vectors solver = DipoleMagDir(x, y, z, tf, inc, dec, centers).fit() # Print the estimated and true dipole monents, inclinations and declinations print 'Estimated magnetization (intensity, inclination, declination)' for e in solver.estimate_: print e # Plot the fit and the normalized histogram of the residuals mpl.figure(figsize=(14, 5)) mpl.subplot(1, 2, 1) mpl.title("Total Field Anomaly (nT)", fontsize=14) mpl.axis('scaled') nlevels = mpl.contour(y, x, tf, (50, 50), 15, interp=True, color='r', label='Observed', linewidth=2.0) mpl.contour(y, x, solver.predicted(), (50, 50), nlevels, interp=True, color='b', label='Predicted', style='dashed', linewidth=2.0) mpl.legend(loc='upper left', shadow=True, prop={'size': 13}) mpl.xlabel('East y (m)', fontsize=14) mpl.ylabel('North x (m)', fontsize=14) mpl.subplot(1, 2, 2) residuals_mean = numpy.mean(solver.residuals()) residuals_std = numpy.std(solver.residuals()) # Each residual is subtracted from the mean and the resulting # difference is divided by the standard deviation
area = (-5000, 5000, -5000, 5000) shape = (51, 51) z0 = -500 xp, yp, zp = gridder.regular(area, shape, z=z0) gz = utils.contaminate(prism.gz(xp, yp, zp, model), 0.001) # Need to convert gz to SI units so that the result can be converted to Eotvos gxz = utils.si2eotvos(transform.derivx(xp, yp, utils.mgal2si(gz), shape)) gyz = utils.si2eotvos(transform.derivy(xp, yp, utils.mgal2si(gz), shape)) gzz = utils.si2eotvos(transform.derivz(xp, yp, utils.mgal2si(gz), shape)) gxz_true = prism.gxz(xp, yp, zp, model) gyz_true = prism.gyz(xp, yp, zp, model) gzz_true = prism.gzz(xp, yp, zp, model) mpl.figure() mpl.title("Original gravity anomaly") mpl.axis('scaled') mpl.contourf(xp, yp, gz, shape, 15) mpl.colorbar(shrink=0.7) mpl.m2km() mpl.figure(figsize=(14, 10)) mpl.subplots_adjust(top=0.95, left=0.05, right=0.95) mpl.subplot(2, 3, 1) mpl.title("x deriv (contour) + true (color map)") mpl.axis('scaled') levels = mpl.contourf(yp, xp, gxz_true, shape, 12) mpl.colorbar(shrink=0.7) mpl.contour(yp, xp, gxz, shape, 12, color='k') mpl.m2km()
percent=True, return_stddev=True, seed=seed) # Make the mesh mesh = SquareMesh(area, shape) # and run the inversion misfit = srtomo.SRTomo(tts, srcs, recs, mesh) regularization = Smoothness2D(mesh.shape) # Will use the l-curve criterion to find the best regularization parameter tomo = LCurve(misfit, regularization, [10**i for i in np.arange(0, 10, 1)], jobs=8).fit() mesh.addprop('vp', tomo.estimate_) # Plot the L-curve annd print the regularization parameter estimated mpl.figure() mpl.title('L-curve: triangle marks the best solution') tomo.plot_lcurve() print "Estimated regularization parameter: %g" % (tomo.regul_param_) # Calculate and print the standard deviation of the residuals # Should be close to the data error if the inversion was able to fit the data residuals = tomo.residuals() print "Assumed error: %g" % (error) print "Standard deviation of residuals: %g" % (np.std(residuals)) mpl.figure(figsize=(14, 5)) mpl.subplot(1, 2, 1) mpl.axis('scaled') mpl.title('Vp model') mpl.squaremesh(model, prop='vp', cmap=mpl.cm.seismic)
""" Seismic: Invert vertical seismic profile (VSP) traveltimes for the velocity of a layered model. """ import numpy from fatiando import utils from fatiando.seismic.profile import layered_straight_ray, LayeredStraight from fatiando.inversion.regularization import Damping from fatiando.vis import mpl # The limits in velocity and depths, respectively area = (0, 10000, 0, 100) vmin, vmax, zmin, zmax = area # Use the interactive functions of mpl to draw a layered model figure = mpl.figure() mpl.xlabel("Velocity (m/s)") mpl.ylabel("Depth (m)") thickness, velocity = mpl.draw_layers(area, figure.gca()) # Make some synthetic noise-corrupted travel-time data zp = numpy.arange(zmin + 0.5, zmax, 0.5) tts, error = utils.contaminate( layered_straight_ray(thickness, velocity, zp), 0.02, percent=True, return_stddev=True) # Make the solver and run the inversion using damping regularization # (assumes known thicknesses of the layers) solver = (LayeredStraight(tts, zp, thickness) + 0.1 * Damping(len(thickness))).fit() velocity_ = solver.estimate_ # Plot the results mpl.figure(figsize=(12, 5))
simulation = wavefd.elastic_psv(lamb, mu, density, area, dt, maxit, sources, stations, snapshots, padding=70, taper=0.005, xz2ps=True) # This part makes an animation using matplotlibs animation API background = 10**-5 * ((density - density.min()) / density.max()) fig = mpl.figure(figsize=(10, 8)) mpl.subplots_adjust(right=0.98, left=0.11, hspace=0.3, top=0.93) mpl.subplot(3, 1, 1) mpl.title('x seismogram') xseismogram, = mpl.plot([], [], '-k') mpl.xlim(0, duration) mpl.ylim(-0.05, 0.05) mpl.ylabel('Amplitude') mpl.subplot(3, 1, 2) mpl.title('z seismogram') zseismogram, = mpl.plot([], [], '-k') mpl.xlim(0, duration) mpl.ylim(-0.05, 0.05) mpl.ylabel('Amplitude') ax = mpl.subplot(3, 1, 3) mpl.title('time: 0.0 s')
oTimeBeforePlotting = datetime.now() #-----Drawing----- #Plot the model myv.figure() myv.prisms(lModel, 'density', style='surface') axes = myv.axes(myv.outline()) myv.wall_bottom(axes.axes.bounds) myv.wall_north(axes.axes.bounds) myv.title("Geological Model") # Plot the forward modelled signal mpl.figure(figsize=(16,5)) mpl.subplot(121) mpl.title("Original signal") mpl.axis('scaled') mpl.contourf(aYGridCoords, aXGridCoords, aObservedSignal, tSignalSize, 50) #last arg is number of contours mpl.colorbar() mpl.xlabel('East (km)') mpl.ylabel('North (km)') mpl.m2km() mpl.subplot(122) mpl.title("Forward modelled signal") mpl.axis('scaled') mpl.contourf(aYGridCoords, aXGridCoords, aCalcSignal, tSignalSize, 50) #last arg is number of contours mpl.colorbar() mpl.xlabel('East (km)')
snapshot = int(0.5 / dt) # Plot a snapshot of the simulation every 0.5 seconds simulation = wavefd.elastic_psv(lamb, mu, density, area, dt, maxit, sources, stations, snapshot, padding=50, taper=0.01, xz2ps=True) # This part makes an animation using matplotlibs animation API fig = mpl.figure(figsize=(12, 5)) mpl.subplot(2, 2, 2) mpl.title('x component') xseismogram, = mpl.plot([], [], '-k') mpl.xlim(0, duration) mpl.ylim(-10**(-3), 10**(-3)) mpl.subplot(2, 2, 4) mpl.title('z component') zseismogram, = mpl.plot([], [], '-k') mpl.xlim(0, duration) mpl.ylim(-10**(-3), 10**(-3)) mpl.subplot(1, 2, 1) # Start with everything zero and grab the plot so that it can be updated later wavefield = mpl.imshow(np.zeros(shape), extent=area, vmin=-10**-6,
# Pad with the odd reflection and a cosine taper (default) g, _ = gridder.pad_array(gz, padtype='OddReflectionTaper') pads.append(g.flatten()) # Get coordinate vectors N = gridder.pad_coords(xy, gz.shape, nps) shapepad = g.shape # Generate new meshgrid and plot results yp = N[1] xp = N[0] titles = ['Original', 'Zero', 'Mean', 'Edge', 'Linear Taper', 'Reflection', 'Odd Reflection', 'Odd Reflection/Taper'] mpl.figure(figsize=(17, 9)) mpl.suptitle('Padding algorithms for a 2D array') for ii, p in enumerate(pads): mpl.subplot(2, 4, ii+2) mpl.axis('scaled') mpl.title(titles[ii+1]) levels = mpl.contourf(yp*0.001, xp*0.001, p, shapepad, 15) cb = mpl.colorbar() mpl.contour(yp*0.001, xp*0.001, p, shapepad, levels, clabel=False, linewidth=0.1) mpl.subplot(2, 4, 1) mpl.axis('scaled') mpl.title(titles[0]) levels = mpl.contourf(y*0.001, x*0.001, gz, shape, 15) cb = mpl.colorbar() mpl.contour(y*0.001, x*0.001, gz, shape, levels, clabel=False, linewidth=0.1)
""" GravMag: 2D forward modeling with polygons """ import numpy from fatiando import utils, mesher from fatiando.gravmag import talwani from fatiando.vis import mpl # Notice that the last two number are switched. # This way, the z axis in the plots points down. area = (-5000, 5000, 5000, 0) axes = mpl.figure().gca() mpl.xlabel("X") mpl.ylabel("Z") mpl.axis('scaled') polygons = [mesher.Polygon(mpl.draw_polygon(area, axes), {'density':500})] xp = numpy.arange(-4500, 4500, 100) zp = numpy.zeros_like(xp) gz = talwani.gz(xp, zp, polygons) mpl.figure() mpl.axis('scaled') mpl.subplot(2,1,1) mpl.title(r"Gravity anomaly produced by the model") mpl.plot(xp, gz, '-k', linewidth=2) mpl.ylabel("mGal") mpl.xlim(-5000, 5000) mpl.subplot(2,1,2) mpl.polygon(polygons[0], 'o-k', linewidth=2, fill='k', alpha=0.5) mpl.xlabel("X")
misfit = PELTotalField(x, y, z, tf, inc, dec, layer, windows, degree) regul = PELSmoothness(layer, windows, degree) # Use an L-curve analysis to find the best regularization parameter solver = LCurve(misfit, regul, [10 ** i for i in range(-20, -10)]).fit() layer.addprop('magnetization', solver.estimate_) residuals = solver.residuals() print "Residuals:" print "mean:", residuals.mean() print "stddev:", residuals.std() # Now I can forward model the layer at the south pole and 500 m above the # original data. Check against the true solution of the prism tfpole = prism.tf(x, y, z - 500, model, -90, 0) tfreduced = sphere.tf(x, y, z - 500, layer, -90, 0) mpl.figure() mpl.suptitle('L-curve') mpl.title("Estimated regularization parameter: %g" % (solver.regul_param_)) solver.plot_lcurve() mpl.grid() mpl.figure(figsize=(15, 4)) mpl.subplot(1, 3, 1) mpl.axis('scaled') mpl.title('Layer (A/m)') mpl.pcolor(layer.y, layer.x, layer.props['magnetization'], layer.shape) mpl.colorbar() mpl.m2km() mpl.subplot(1, 3, 2) mpl.axis('scaled') mpl.title('Fit (nT)')
area = (-150, 150, -300, 300) shape = (30, 15) x, y = gridder.regular(area, shape) height = (-80 * utils.gaussian2d(x, y, 100, 200, x0=-50, y0=-100, angle=-60) + 200 * utils.gaussian2d(x, y, 50, 100, x0=80, y0=170)) nodes = (x, y, -1 * height) relief = mesher.PrismRelief(0, gridder.spacing(area, shape), nodes) relief.addprop('density', (2670 for i in xrange(relief.size))) gridarea = (-80, 80, -220, 220) gridshape = (100, 100) xp, yp, zp = gridder.regular(gridarea, gridshape, z=-200) gz = prism.gz(xp, yp, zp, relief) mpl.figure(figsize=(10, 7)) mpl.subplot(1, 2, 1) mpl.title("Synthetic topography") mpl.axis('scaled') mpl.pcolor(x, y, height, shape) cb = mpl.colorbar() cb.set_label("meters") mpl.square(gridarea, label='Computation grid') mpl.legend() mpl.subplot(1, 2, 2) mpl.title("Topographic effect") mpl.axis('scaled') mpl.pcolor(xp, yp, gz, gridshape) cb = mpl.colorbar() cb.set_label("mGal") mpl.show()
disc = 10 # space discretization shp = (70, 560) nz, nx = shp # bellow load geologic model velociy model vmodel = utils.fromimage('pinchout.bmp', ranges=[2500., 3500.], shape=shp) twti = np.cumsum(ds / vmodel, axis=0) * 2 # calculate irregular sampled twt times twt = np.arange(0, np.max(twti) + 0.10, dt) # new twt times re-sampled to 4 ms dnx = int(nx / disc) twtvmodel = np.zeros((len(twt), dnx)) # velocity model in time and discretized for i in xrange(0, nx, disc): # set the time re-sample velocity model twtvmodel[:, int(i / disc)] = np.interp(twt, twti[:, i], vmodel[:, i]) zimp = np.ones( twtvmodel.shape) * 1000. * twtvmodel # create impedance z = rho*v rc = (zimp[1:] - zimp[:-1]) / (zimp[1:] + zimp[:-1] ) # calculate reflection coefs fig = mpl.figure(figsize=(11, 7)) # plottings mpl.subplots_adjust(right=0.98, left=0.11, hspace=0.4, top=0.93, bottom=0.13) mpl.subplot2grid((3, 4), (0, 0), colspan=4) # plot rc model mpl.title("Zero-offset section reflection coefficients", fontsize=13, family='sans-serif', weight='bold') rcs = utils.matrix2stream(rc.transpose(), header={'delta': dt}) mpl.seismic_wiggle(rcs, normalize=True, scale=1.5, ranges=[0, nx]) # rc model wavelet = signal.ricker(255, 1 / (2 * f * dt)) # create wavelet samples = signal.filtfilt(wavelet, np.ones(len(wavelet)), rc, axis=0, padlen=len(twt) - 2) # convolve rc*wavelet mpl.ylabel('twt (s)')
""" GravMag: 3D forward modeling of total-field magnetic anomaly using polygonal prisms """ from fatiando import mesher, gridder, utils from fatiando.vis import mpl, myv from fatiando.gravmag import polyprism # The regional field inc, dec = 30, -15 # Draw each polygonal prism (viewed from above) bounds = [-5000, 5000, -5000, 5000, 0, 5000] area = bounds[:4] axis = mpl.figure().gca() mpl.axis('scaled') model = [ mesher.PolygonalPrism( mpl.draw_polygon(area, axis, xy2ne=True), # Use only induced magnetization 0, 2000, {'magnetization': 2})] # Calculate the effect shape = (100, 100) xp, yp, zp = gridder.regular(area, shape, z=-500) tf = polyprism.tf(xp, yp, zp, model, inc, dec) # and plot it mpl.figure() mpl.axis('scaled') mpl.title("Total field anomalyproduced by prism model (nT)") mpl.contourf(yp, xp, tf, shape, 20) mpl.colorbar() for p in model:
[wavefd.MexHatSource(350000, 20000, area, shape, 100000, 0.5, delay=2)]] # Get the iterator. This part only generates an iterator object. The actual # computations take place at each iteration in the for loop below dt = wavefd.maxdt(area, shape, pvel.max()) duration = 100 maxit = int(duration/dt) stations = [[550000, 0]] snapshots = int(1./dt) simulation = wavefd.elastic_psv(lamb, mu, density, area, dt, maxit, sources, stations, snapshots, padding=70, taper=0.005, xz2ps=True) # This part makes an animation using matplotlibs animation API background = 10**-5*((pvel - pvel.min())/pvel.max()) fig = mpl.figure(figsize=(10, 8)) mpl.subplots_adjust(right=0.98, left=0.11, hspace=0.3, top=0.93) mpl.subplot(2, 1, 1) mpl.title('x seismogram') xseismogram, = mpl.plot([],[],'-k') mpl.xlim(0, duration) mpl.ylim(-0.05, 0.05) mpl.ylabel('Amplitude') ax = mpl.subplot(2, 1, 2) mpl.title('time: 0.0 s') wavefield = mpl.imshow(density, extent=area, cmap=mpl.cm.gray_r, vmin=-0.00001, vmax=0.00001) mpl.points(stations, '^b', size=8) #mpl.text(500000, 20000, 'Crust') #mpl.text(500000, 60000, 'Mantle') fig.text(0.8, 0.5, 'Seismometer')
area = [0, shape[0]*ds, 0, shape[1]*ds] # Set the parameters of the finite difference grid velocity = np.zeros(shape)+6000. velocity[100:,100:] = 0. fc = 15. sources = [wavefd.GaussSource(125*ds, 75*ds, area, shape, 1., fc)] dt = wavefd.scalar_maxdt(area, shape, np.max(velocity)) duration = 2.5 maxit = int(duration/dt) stations = [[75*ds, 125*ds]] # x, z coordinate of the seismometer snapshots = 3 # every 3 iterations plots one simulation = wavefd.scalar(velocity, area, dt, maxit, sources, stations, snapshots) # This part makes an animation using matplotlibs animation API background = (velocity-4000)*10**-1 fig = mpl.figure(figsize=(8, 6)) mpl.subplots_adjust(right=0.98, left=0.11, hspace=0.5, top=0.93) mpl.subplot2grid((4, 3), (0,0), colspan=3,rowspan=3) wavefield = mpl.imshow(np.zeros_like(velocity), extent=area, cmap=mpl.cm.gray_r, vmin=-1000, vmax=1000) mpl.points(stations, '^b', size=8) mpl.ylim(area[2:][::-1]) mpl.xlabel('x (km)') mpl.ylabel('z (km)') mpl.m2km() mpl.subplot2grid((4,3), (3,0), colspan=3) seismogram1, = mpl.plot([],[],'-k') mpl.xlim(0, duration) mpl.ylim(-200, 200) mpl.ylabel('Amplitude') times = np.linspace(0, dt*maxit, maxit)
fields = [ gravmag.prism.potential(xp, yp, zp, prisms), gravmag.prism.gx(xp, yp, zp, prisms), gravmag.prism.gy(xp, yp, zp, prisms), gravmag.prism.gz(xp, yp, zp, prisms), gravmag.prism.gxx(xp, yp, zp, prisms), gravmag.prism.gxy(xp, yp, zp, prisms), gravmag.prism.gxz(xp, yp, zp, prisms), gravmag.prism.gyy(xp, yp, zp, prisms), gravmag.prism.gyz(xp, yp, zp, prisms), gravmag.prism.gzz(xp, yp, zp, prisms) ] titles = [ 'potential', 'gx', 'gy', 'gz', 'gxx', 'gxy', 'gxz', 'gyy', 'gyz', 'gzz' ] mpl.figure(figsize=(8, 9)) mpl.subplots_adjust(left=0.03, right=0.95, bottom=0.05, top=0.92, hspace=0.3) mpl.suptitle("Potential fields produced by a 3 prism model") for i, field in enumerate(fields): mpl.subplot(4, 3, i + 3) mpl.axis('scaled') mpl.title(titles[i]) levels = mpl.contourf(yp * 0.001, xp * 0.001, field, shape, 15) cb = mpl.colorbar() mpl.contour(yp * 0.001, xp * 0.001, field, shape, levels, clabel=False, linewidth=0.1)
# Generate some synthetic data prisms = [mesher.Prism(-4000, 4000, -500, 500, 500, 1000, {'density': 1000})] shape = (100, 100) xp, yp, zp = gridder.regular((-5000, 5000, -5000, 5000), shape, z=-150) noise = 2 tensor = [ utils.contaminate(gravmag.prism.gxx(xp, yp, zp, prisms), noise), utils.contaminate(gravmag.prism.gxy(xp, yp, zp, prisms), noise), utils.contaminate(gravmag.prism.gxz(xp, yp, zp, prisms), noise), utils.contaminate(gravmag.prism.gyy(xp, yp, zp, prisms), noise), utils.contaminate(gravmag.prism.gyz(xp, yp, zp, prisms), noise), utils.contaminate(gravmag.prism.gzz(xp, yp, zp, prisms), noise) ] # Plot the data titles = ['gxx', 'gxy', 'gxz', 'gyy', 'gyz', 'gzz'] mpl.figure() for i, title in enumerate(titles): mpl.subplot(3, 2, i + 1) mpl.title(title) mpl.axis('scaled') levels = mpl.contourf(yp, xp, tensor[i], shape, 10) mpl.contour(yp, xp, tensor[i], shape, levels) mpl.m2km() mpl.show() # Get the eigenvectors from the tensor data eigenvals, eigenvecs = gravmag.tensor.eigen(tensor) # Use the first eigenvector to estimate the center of mass cm, sigma = gravmag.tensor.center_of_mass(xp, yp, zp, eigenvecs[0]) print "Sigma = %g" % (sigma) # Plot the prism and the estimated center of mass myv.figure()
# Set the parameters of the finite difference grid velocity = np.zeros(shape) + 6000. velocity[100:, 100:] = 0. fc = 15. sources = [wavefd.GaussSource(125 * ds, 75 * ds, area, shape, 1., fc)] dt = wavefd.scalar_maxdt(area, shape, np.max(velocity)) duration = 2.5 maxit = int(duration / dt) stations = [[75 * ds, 125 * ds]] # x, z coordinate of the seismometer snapshots = 3 # every 3 iterations plots one simulation = wavefd.scalar(velocity, area, dt, maxit, sources, stations, snapshots) # This part makes an animation using matplotlibs animation API background = (velocity - 4000) * 10**-1 fig = mpl.figure(figsize=(8, 6)) mpl.subplots_adjust(right=0.98, left=0.11, hspace=0.5, top=0.93) mpl.subplot2grid((4, 3), (0, 0), colspan=3, rowspan=3) wavefield = mpl.imshow(np.zeros_like(velocity), extent=area, cmap=mpl.cm.gray_r, vmin=-1000, vmax=1000) mpl.points(stations, '^b', size=8) mpl.ylim(area[2:][::-1]) mpl.xlabel('x (km)') mpl.ylabel('z (km)') mpl.m2km() mpl.subplot2grid((4, 3), (3, 0), colspan=3) seismogram1, = mpl.plot([], [], '-k') mpl.xlim(0, duration)
mesher.Prism(2000,4000,3000,4000,0,2000,{'density':1300})] shape = (100,100) xp, yp, zp = gridder.regular((-5000, 5000, -5000, 5000), shape, z=-150) fields = [prism.potential(xp, yp, zp, model), prism.gx(xp, yp, zp, model), prism.gy(xp, yp, zp, model), prism.gz(xp, yp, zp, model), prism.gxx(xp, yp, zp, model), prism.gxy(xp, yp, zp, model), prism.gxz(xp, yp, zp, model), prism.gyy(xp, yp, zp, model), prism.gyz(xp, yp, zp, model), prism.gzz(xp, yp, zp, model)] titles = ['potential', 'gx', 'gy', 'gz', 'gxx', 'gxy', 'gxz', 'gyy', 'gyz', 'gzz'] mpl.figure(figsize=(8, 9)) mpl.subplots_adjust(left=0.03, right=0.95, bottom=0.05, top=0.92, hspace=0.3) mpl.suptitle("Potential fields produced by a 3 prism model") for i, field in enumerate(fields): mpl.subplot(4, 3, i + 3) mpl.axis('scaled') mpl.title(titles[i]) levels = mpl.contourf(yp*0.001, xp*0.001, field, shape, 15) cb = mpl.colorbar() mpl.contour(yp*0.001, xp*0.001, field, shape, levels, clabel=False, linewidth=0.1) mpl.show() myv.figure() myv.prisms(model, prop='density') axes = myv.axes(myv.outline()) myv.wall_bottom(axes.axes.bounds, opacity=0.2)
area = (-150, 150, -300, 300) shape = (30, 15) x, y = gridder.regular(area, shape) height = (-80*utils.gaussian2d(x, y, 100, 200, x0=-50, y0=-100, angle=-60) + 200*utils.gaussian2d(x, y, 50, 100, x0=80, y0=170)) nodes = (x, y, -1*height) relief = mesher.PrismRelief(0, gridder.spacing(area,shape), nodes) relief.addprop('density', (2670 for i in xrange(relief.size))) gridarea = (-80, 80, -220, 220) gridshape = (100, 100) xp, yp, zp = gridder.regular(gridarea, gridshape, z=-200) gz = gravmag.prism.gz(xp, yp, zp, relief) mpl.figure(figsize=(10,7)) mpl.subplot(1, 2, 1) mpl.title("Synthetic topography") mpl.axis('scaled') mpl.pcolor(x, y, height, shape) cb = mpl.colorbar() cb.set_label("meters") mpl.square(gridarea, label='Computation grid') mpl.legend() mpl.subplot(1, 2, 2) mpl.title("Topographic effect") mpl.axis('scaled') mpl.pcolor(xp, yp, gz, gridshape) cb = mpl.colorbar() cb.set_label("mGal") mpl.show()
Seismic: 2D epicenter estimation assuming a homogeneous and flat Earth """ import sys import numpy from fatiando import gridder, utils from fatiando.mesher import Square from fatiando.vis import mpl from fatiando.seismic import ttime2d from fatiando.seismic.epic2d import Homogeneous # Make a velocity model to calculate traveltimes area = (0, 10, 0, 10) vp, vs = 2, 1 model = [Square(area, props={'vp':vp, 'vs':vs})] # Pick the locations of the receivers mpl.figure() mpl.axis('scaled') mpl.suptitle("Choose the location of the receivers") rec_points = mpl.pick_points(area, mpl.gca(), marker='^', color='r') # and the source mpl.figure() mpl.axis('scaled') mpl.suptitle("Choose the location of the source") mpl.points(rec_points, '^r') src = mpl.pick_points(area, mpl.gca(), marker='*', color='y') if len(src) > 1: print "Don't be greedy! Pick only one point as the source" sys.exit() # Calculate the P and S wave traveltimes srcs, recs = utils.connect_points(src, rec_points) ptime = ttime2d.straight(model, 'vp', srcs, recs)
oTimeEndIteration = datetime.now() print("~~~~~~~~~~Total Time:", oTimeEndTot - oTimeBeginTot) oTimeBeforePlotting = datetime.now() #-----Drawing----- #Plot the model myv.figure() myv.prisms(lModel, 'density', style='surface') axes = myv.axes(myv.outline()) myv.wall_bottom(axes.axes.bounds) myv.wall_north(axes.axes.bounds) myv.title("Geological Model") # Plot the forward modelled signal mpl.figure(figsize=(16, 5)) mpl.subplot(121) mpl.title("Original signal") mpl.axis('scaled') mpl.contourf(aYGridCoords, aXGridCoords, aObservedSignal, tSignalSize, 50) #last arg is number of contours mpl.colorbar() mpl.xlabel('East (km)') mpl.ylabel('North (km)') mpl.m2km() mpl.subplot(122) mpl.title("Forward modelled signal") mpl.axis('scaled') mpl.contourf(aYGridCoords, aXGridCoords, aCalcSignal, tSignalSize, 50) #last arg is number of contours
""" GravMag: 3D forward modeling of total-field magnetic anomaly using polygonal prisms """ from fatiando import mesher, gridder, utils from fatiando.vis import mpl, myv from fatiando.gravmag import polyprism # The regional field inc, dec = 30, -15 # Draw each polygonal prism (viewed from above) bounds = [-5000, 5000, -5000, 5000, 0, 5000] area = bounds[:4] axis = mpl.figure().gca() mpl.axis('scaled') model = [ mesher.PolygonalPrism( mpl.draw_polygon(area, axis, xy2ne=True), # Use only induced magnetization 0, 2000, {'magnetization':2})] # Calculate the effect shape = (100, 100) xp, yp, zp = gridder.regular(area, shape, z=-500) tf = polyprism.tf(xp, yp, zp, model, inc, dec) # and plot it mpl.figure() mpl.axis('scaled') mpl.title("Total field anomalyproduced by prism model (nT)") mpl.contourf(yp, xp, tf, shape, 20) mpl.colorbar() for p in model: