def xderiv(x, y, data, n = 1): ''' Return the horizontal derivative in x direction for n order in Fourier domain. Inputs: x - numpy 2D array - grid values in x direction y - numpy 2D array - grid values in y direction data - numpy 2D array - potential data n - float - order of the derivative Output: xder - numpy 2D array - derivative in x direction ''' # Stablishing some conditions if x.shape != y.shape != data.shape: raise ValueError("All inputs must have same shape!") # Condition for the order of the derivative if n <= 0.: raise ValueError("Order of the derivative must be positive and nonzero!") if n == 0.: res = data else: # Calculate the wavenuber in x direction _, kx = auxiliars.wavenumber(y, x) # Apply the Fourier transform xder = numpy.fft.fft2(data)*((kx*1j)**(n)) # Calculating the inverse transform res = numpy.real(numpy.fft.ifft2(xder)) # Return the final output return res
def continuation(x, y, data, H): ''' This function compute the upward or downward continuation for a potential field data, which can be gravity or magnetic signal. The value for H represents the level which the data will be continuated. If H is positive, the continuation is upward, because Dz is greater than 0 and the exponential is negative; otherwise, if H is negative, the continuation is downward. Input: x - numpy 2D array - observation points on the grid in X direction y - numpy 2D array - observation points on the grid in Y direction data - 2D array - gravity or magnetic data H - float - value for the new observation level ''' # Conditions for all inputs if x.shape != y.shape != data.shape: raise ValueError("All inputs must have the same shape!") if H == 0.: # No continuation will be applied res = data else: # Calculate the wavenumbers ky, kx = auxiliars.wavenumber(y, x) kcont = numpy.exp((-H) * numpy.sqrt(kx**2 + ky**2)) result = kcont * numpy.fft.fft2(data) res = numpy.real(numpy.fft.ifft2(result)) # Return the final output return res
def reduction(x, y, data, inc, dec, incs=None, decs=None, newinc=None, newdec=None, newincs=None, newdecs=None): ''' Return the reduced potential data giving the new directions for the geomagnetic field and source magnetization. Its based on Blakely (1996). Inputs: x - numpy 2D array - coordinate at X y - numpy 2D array - coordinate at Y data - numpy 2D array - magnetic data set (usually total field anomaly) oldf - numpy 1D array - vector with old field directions olds - numpy 1D array - vector with old source directions newf - numpy 1D array - vector with new field directions news - numpy 1D array - vector with new source directions - The last four vector are discplaced as : v = [inc, dec] Output: res - numpy 2D array - result by using reduction filter Ps. This filter is very useful for values of incination greater than +/- 15 deg. ''' # Conditions for all inputs if x.shape != y.shape != data.shape: raise ValueError("All inputs must have the same shape!") # Induced magnetization if incs == None: incs = inc if decs == None: decs = dec # Reduction to Pole if newinc == None: newinc = 90. if newdec == None: newdec = 0. if newincs == None: newincs = 90. if newdecs == None: newdecs = 0. # Step 1 - Calculate the wavenumbers # It will return the wavenumbers in x and y directions, in order to calculate the # values for magnetization directions in Fourier domains: ky, kx = auxiliars.wavenumber(y, x) # Step 2 - Calcuate the magnetization direction # It will return the magnetization directions in Fourier domain for all vector that # contain inclination and declination. All values are complex. f0 = auxiliars.theta(inc, dec, kx, ky) m0 = auxiliars.theta(incs, decs, kx, ky) f1 = auxiliars.theta(newinc, newdec, kx, ky) m1 = auxiliars.theta(newincs, newdecs, kx, ky) # Step 3 - Calculate the filter # It will return the result for the reduction filter. However, it is necessary use a # condition while the division is been calculated, once there is no zero division. with numpy.errstate(divide='ignore', invalid='ignore'): operator = (f1 * m1) / (f0 * m0) operator[0, 0] = 0. # Calculate the result by multiplying the filter and the data on Fourier domain res = operator * numpy.fft.fft2(data) # Return the final output return numpy.real(numpy.fft.ifft2(res))
def pseudograv(x, y, data, inc, dec, incs, decs, rho=1000., mag=1.): ''' This function calculates the pseudogravity anomaly transformation due to a total field anomaly grid. It recquires the X and Y coordinates (respectively North and East directions), the magnetic data as a 2D array grid, the values for inclination and declination for the magnetic field and the magnetization of the source. Inputs: x - numpy 2D array - coordinates in X direction y - numpy 2D array - coordinates in y direction data - numpy 2D array - magnetic data (usually total field anomaly) field - numpy 1D array - inclination and declination for the magnetic field field[0] -> inclination field[1] -> declination source - numpy 1D array - inclination and declination for the magnetic source source[0] -> inclination source[1] -> declination Output: pgrav - numpy array - pseudo gravity anomaly ''' # Conditions (1): if x.shape != y.shape != data.shape: raise ValueError("All inputs must have the same shape!") # Conditions (2): assert rho != 0., 'Density must not be zero!' assert mag != 0., 'Magnetization must not be zero!' # Conversion for gravity and magnetic data G = 6.673e-11 si2mGal = 100000.0 t2nt = 1000000000.0 cm = 0.0000001 # Compute the constant value C = G * rho * si2mGal / (cm * mag * t2nt) # Calculate the wavenumber ky, kx = auxiliars.wavenumber(y, x) k = (kx**2 + ky**2)**(0.5) # Computing theta values for the source thetaf = auxiliars.theta(inc, dec, kx, ky) thetas = auxiliars.theta(incs, decs, kx, ky) # Calculate the product # Here we use the numpy error statement in order to evaluate the zero division with numpy.errstate(divide='ignore', invalid='ignore'): prod = 1. / (thetaf * thetas * k) prod[0, 0] = 0. # Calculate the pseudo gravity anomaly res = numpy.fft.fft2(data) * prod # Converting to mGal as a product by C: res *= C # Return the final output return numpy.real(numpy.fft.ifft2(res))