distributed data that are inside a given area. It doesn't matter whether or not the points are on a regular grid. """ from fatiando import gridder import matplotlib.pyplot as plt import numpy as np # Generate some synthetic data area = (-100, 100, -60, 60) x, y = gridder.scatter(area, 1000, seed=0) data = np.sin(0.1*x)*np.cos(0.1*y) # Select the data that fall inside "section" section = [-40, 40, -25, 25] # Tip: you pass more than one data array as input. Use this to cut multiple # data sources (e.g., gravity + height + topography). x_sub, y_sub, [data_sub] = gridder.cut(x, y, [data], section) # Plot the original data besides the cut section plt.figure(figsize=(8, 6)) plt.subplot(1, 2, 1) plt.axis('scaled') plt.title("Whole data") plt.tricontourf(y, x, data, 30, cmap='RdBu_r') plt.plot(y, x, 'xk') x1, x2, y1, y2 = section plt.plot([y1, y2, y2, y1, y1], [x1, x1, x2, x2, x1], '-k', linewidth=3) plt.xlim(area[2:]) plt.ylim(area[:2]) plt.subplot(1, 2, 2)
""" Gridding: Cut a section from a grid """ from fatiando import gridder, utils from fatiando.vis import mpl # Generate some synthetic data on a regular grid x, y = gridder.regular((-10, 10, -10, 10), (100,100)) # Using a 2D Gaussian z = utils.gaussian2d(x, y, 1, 1) subarea = [-2, 2, -3, 3] subx, suby, subscalar = gridder.cut(x, y, [z], subarea) mpl.figure(figsize=(12, 5)) mpl.subplot(1, 2, 1) mpl.title("Whole grid") mpl.axis('scaled') mpl.pcolor(x, y, z, (100,100)) mpl.square(subarea, 'k', linewidth=2, label='Cut this region') mpl.legend(loc='lower left') mpl.subplot(1, 2, 2) mpl.title("Cut grid") mpl.axis('scaled') mpl.pcolor(subx, suby, subscalar[0], (40,60), interp=True) mpl.show()
def center_of_mass(x, y, z, eigvec1, windows=1, wcenter=None, wmin=None, wmax=None): """ Estimates the center of mass of a source using the method of Beiki and Pedersen (2010). Uses an expanding window to get the best estimate and deal with multiple sources. Parameters: * x, y, z : arrays The x, y, and z coordinates of the observation points * eigvec1 : array (shape = (N, 3) where N is the number of observations) The first eigenvector of the gravity gradient tensor at each observation point * windows : int The number of expanding windows to use * wcenter : list = [x, y] The [x, y] coordinates of the center of the expanding windows. Will default to the middle of the data area if None * wmin, wmax : float Minimum and maximum size of the expanding windows. Will default to 10% data area and 100% data area, respectively, if None Returns: * [xo, yo, zo], sigma : float xo, yo, zo are the coordinates of the estimated center of mass. sigma is the estimated standard deviation of the distances between the estimated center of mass and the lines passing through the observation point in the direction of the eigenvector Example:: >>> import fatiando as ft >>> # Generate synthetic data using a prism >>> prism = ft.mesher.Prism(-200,0,-100,100,0,200,{'density':1000}) >>> x, y, z = ft.gridder.regular((-500,500,-500,500), (20,20), z=-100) >>> tensor = [ft.gravmag.prism.gxx(x, y, z, [prism]), ... ft.gravmag.prism.gxy(x, y, z, [prism]), ... ft.gravmag.prism.gxz(x, y, z, [prism]), ... ft.gravmag.prism.gyy(x, y, z, [prism]), ... ft.gravmag.prism.gyz(x, y, z, [prism]), ... ft.gravmag.prism.gzz(x, y, z, [prism])] >>> # Get the eigenvector >>> eigenvals, eigenvecs = ft.gravmag.tensor.eigen(tensor) >>> # Now estimate the center of mass >>> cm, sigma = ft.gravmag.tensor.center_of_mass(x, y, z, eigenvecs[0]) >>> xo, yo, zo = cm >>> print "%.2lf, %.2lf, %.2lf" % (xo, yo, zo) -100.05, 0.00, 99.86 """ if wmin is None: wmin = 0.1 * numpy.mean([x.max() - x.min(), y.max() - y.min()]) if wmax is None: wmax = numpy.mean([x.max() - x.min(), y.max() - y.min()]) # To ensure that if there is only one window, it will use the largest # possible if windows == 1: wmin = wmax if wcenter is None: wcenter = [0.5 * (x.min() + x.max()), 0.5 * (y.min() + y.max())] xc, yc = wcenter best = None for size in numpy.linspace(wmin, wmax, windows): area = [ xc - 0.5 * size, xc + 0.5 * size, yc - 0.5 * size, yc + 0.5 * size ] wx, wy, scalars = gridder.cut(x, y, [z, eigvec1], area) wz, weigvec1 = scalars # Estimate the center of mass for the data in this window vx, vy, vz = numpy.transpose(weigvec1) m11 = numpy.sum(1 - vx**2) m12 = numpy.sum(-vx * vy) m13 = numpy.sum(-vx * vz) m22 = numpy.sum(1 - vy**2) m23 = numpy.sum(-vy * vz) m33 = numpy.sum(1 - vz**2) matrix = numpy.array([[m11, m12, m13], [m12, m22, m23], [m13, m23, m33]]) vector = numpy.array([ numpy.sum((1 - vx**2) * wx - vx * vy * wy - vx * vz * wz), numpy.sum(-vx * vy * wx + (1 - vy**2) * wy - vy * vz * wz), numpy.sum(-vx * vz * wx - vy * vz * wy + (1 - vz**2) * wz) ]) cm = numpy.linalg.solve(matrix, vector) xo, yo, zo = cm dists = ((xo - wx)**2 + (yo - wy)**2 + (zo - wz)**2 - ((xo - wx) * vx + (yo - wy) * vy + (zo - wz) * vz)**2) sigma = numpy.sqrt(numpy.sum(dists) / len(wx)) if best is None or sigma < best[1]: best = [cm, sigma] return best
import numpy from matplotlib import pyplot from fatiando import vis, gridder, logger log = logger.tofile(logger.get(), 'fetchdata.log') log.info(logger.header()) data = numpy.loadtxt('/home/leo/dat/boa6/ftg/rawdata/BOA6_FTG.XYZ', unpack=True) # Remove the coordinates from the raw data data[0] -= data[0].min() data[1] -= data[1].min() area1 = [7970, 12877, 10650, 17270] y, x, scalars = gridder.cut(data[0], data[1], data[2:], area1) # The x and y components are switched because the coordinates are mixed up # (my x is their y) height, z, gyy, gxy, gyz, gxx, gxz, gzz = scalars # Remove the coordinates from the cut data x -= x.min() y -= y.min() # Convert altitude into z coordinates z *= -1 # Save things to a file fields = ['x', 'y', 'height', 'alt', 'gxx', 'gxy', 'gxz', 'gyy', 'gyz', 'gzz'] data = [x, y, height, z, gxx, gxy, gxz, gyy, gyz, gzz] with open('data.xyz', 'w') as f: f.write(logger.header(comment='#')) f.write("\n# Column structure\n# ") f.write(' '.join(fields)) f.write('\n') numpy.savetxt(f, numpy.transpose(data), fmt="%.4f") # Plot
def center_of_mass(x, y, z, eigvec1, windows=1, wcenter=None, wmin=None, wmax=None): """ Estimates the center of mass of a source using the method of Beiki and Pedersen (2010). Uses an expanding window to get the best estimate and deal with multiple sources. Parameters: * x, y, z : arrays The x, y, and z coordinates of the observation points * eigvec1 : array (shape = (N, 3) where N is the number of observations) The first eigenvector of the gravity gradient tensor at each observation point * windows : int The number of expanding windows to use * wcenter : list = [x, y] The [x, y] coordinates of the center of the expanding windows. Will default to the middle of the data area if None * wmin, wmax : float Minimum and maximum size of the expanding windows. Will default to 10% data area and 100% data area, respectively, if None Returns: * [xo, yo, zo], sigma : float xo, yo, zo are the coordinates of the estimated center of mass. sigma is the estimated standard deviation of the distances between the estimated center of mass and the lines passing through the observation point in the direction of the eigenvector Example:: >>> import fatiando as ft >>> # Generate synthetic data using a prism >>> prism = ft.mesher.Prism(-200,0,-100,100,0,200,{'density':1000}) >>> x, y, z = ft.gridder.regular((-500,500,-500,500), (20,20), z=-100) >>> tensor = [ft.gravmag.prism.gxx(x, y, z, [prism]), ... ft.gravmag.prism.gxy(x, y, z, [prism]), ... ft.gravmag.prism.gxz(x, y, z, [prism]), ... ft.gravmag.prism.gyy(x, y, z, [prism]), ... ft.gravmag.prism.gyz(x, y, z, [prism]), ... ft.gravmag.prism.gzz(x, y, z, [prism])] >>> # Get the eigenvector >>> eigenvals, eigenvecs = ft.gravmag.tensor.eigen(tensor) >>> # Now estimate the center of mass >>> cm, sigma = ft.gravmag.tensor.center_of_mass(x, y, z, eigenvecs[0]) >>> xo, yo, zo = cm >>> print "%.2lf, %.2lf, %.2lf" % (xo, yo, zo) -100.05, 0.00, 99.86 """ if wmin is None: wmin = 0.1*numpy.mean([x.max() - x.min(), y.max() - y.min()]) if wmax is None: wmax = numpy.mean([x.max() - x.min(), y.max() - y.min()]) # To ensure that if there is only one window, it will use the largest # possible if windows == 1: wmin = wmax if wcenter is None: wcenter = [0.5*(x.min() + x.max()), 0.5*(y.min() + y.max())] xc, yc = wcenter best = None for size in numpy.linspace(wmin, wmax, windows): area = [xc - 0.5*size, xc + 0.5*size, yc - 0.5*size, yc + 0.5*size] wx, wy, scalars = gridder.cut(x, y, [z, eigvec1], area) wz, weigvec1 = scalars # Estimate the center of mass for the data in this window vx, vy, vz = numpy.transpose(weigvec1) m11 = numpy.sum(1 - vx**2) m12 = numpy.sum(-vx*vy) m13 = numpy.sum(-vx*vz) m22 = numpy.sum(1 - vy**2) m23 = numpy.sum(-vy*vz) m33 = numpy.sum(1 - vz**2) matrix = numpy.array( [[m11, m12, m13], [m12, m22, m23], [m13, m23, m33]]) vector = numpy.array([ numpy.sum((1 - vx**2)*wx - vx*vy*wy - vx*vz*wz), numpy.sum(-vx*vy*wx + (1 - vy**2)*wy - vy*vz*wz), numpy.sum(-vx*vz*wx - vy*vz*wy + (1 - vz**2)*wz)]) cm = numpy.linalg.solve(matrix, vector) xo, yo, zo = cm dists = ((xo - wx)**2 + (yo - wy)**2 + (zo - wz)**2 - ((xo - wx)*vx + (yo - wy)*vy + (zo - wz)*vz)**2) sigma = numpy.sqrt(numpy.sum(dists)/len(wx)) if best is None or sigma < best[1]: best = [cm, sigma] return best
""" Gridding: Cut a section from a grid """ from fatiando import gridder, utils from fatiando.vis import mpl # Generate some synthetic data on a regular grid x, y = gridder.regular((-10, 10, -10, 10), (100, 100)) # Using a 2D Gaussian z = utils.gaussian2d(x, y, 1, 1) subarea = [-2, 2, -3, 3] subx, suby, subscalar = gridder.cut(x, y, [z], subarea) mpl.figure(figsize=(12, 5)) mpl.subplot(1, 2, 1) mpl.title("Whole grid") mpl.axis('scaled') mpl.pcolor(x, y, z, (100, 100)) mpl.square(subarea, 'k', linewidth=2, label='Cut this region') mpl.legend(loc='lower left') mpl.subplot(1, 2, 2) mpl.title("Cut grid") mpl.axis('scaled') mpl.pcolor(subx, suby, subscalar[0], (40, 60), interp=True) mpl.show()