The fatiando package has been deprecated. Please check out the new tools in the Fatiando a Terra website: www.fatiando.org

Source code for fatiando.gravmag.magdir

"""
Estimation of the total magnetization vector of homogeneous bodies.

It estimates parameters related to the magnetization vector of homogeneous
bodies.

**Algorithms**

* :class:`~fatiando.gravmag.magdir.DipoleMagDir`: This class estimates
  the Cartesian components of the magnetization vector of homogeneous
  dipolar bodies with known center. The estimated magnetization vector
  is converted to dipole moment, inclination (positive down) and declination
  (with respect to x, North).

----

"""

from __future__ import division
from future.builtins import super
import numpy as np
from ..inversion import Misfit
from .. import mesher
from ..utils import ang2vec, vec2ang, safe_dot
from . import sphere
from ..constants import G, CM, T2NT, SI2EOTVOS
from .._our_duecredit import due, Doi, BibTeX


@due.dcite(Doi("10.5194/npg-22-215-2015"),
           description='Estimates total mag. dir. of approx. spherical bodies')
[docs]class DipoleMagDir(Misfit): """ Estimate the magnetization vector of a set of dipoles from magnetic total field anomaly using the method of Oliveira Jr. et al. (2015). By using the well-known first-order approximation of the total field anomaly (Blakely, 1996, p. 179) produced by a set of dipoles, the estimation of the Cartesian components of the magnetization vectors is formulated as linear inverse problem. After estimating the magnetization vectors, they are converted to dipole moment, inclination (positive down) and declination (with respect to x, North). After solving, use the ``estimate_`` attribute to get the estimated magnetization vectors in dipole moment, inclination and declination. The estimated magnetization vectors in Cartesian coordinates can be accessed through the ``p_`` attribute. .. note:: Assumes x = North, y = East, z = Down. Parameters: * x, y, z : 1d-arrays The x, y, z coordinates of each data point. * data : 1d-array The total field magnetic anomaly data at each point. * inc, dec : floats The inclination and declination of the inducing field * points : list of points [x, y, z] Each point [x, y, z] is the center of a dipole. Will invert for the Cartesian components of the magnetization vector of each dipole. Subsequently, the estimated magnetization vectors are converted to dipole moment, inclination and declination. .. note:: Inclination is positive down and declination is measured with respect to x (North). References: Blakely, R. (1996), Potential theory in gravity and magnetic applications: CUP Oliveira Jr., V. C., D. P. Sales, V. C. F. Barbosa, and L. Uieda (2015), Estimation of the total magnetization direction of approximately spherical bodies, Nonlin. Processes Geophys., 22(2), 215-232, doi:10.5194/npg-22-215-2015. Examples: Estimation of the total magnetization vector of dipoles with known centers >>> import numpy as np >>> from fatiando import gridder, utils >>> from fatiando.gravmag import sphere >>> from fatiando.mesher import Sphere, Prism >>> # Produce some synthetic data >>> area = (0, 10000, 0, 10000) >>> x, y, z = gridder.scatter(area, 500, z=-150, seed=0) >>> model = [Sphere(3000, 3000, 1000, 1000, ... {'magnetization': utils.ang2vec(6.0, -20.0, -10.0)}), ... Sphere(7000, 7000, 1000, 1000, ... {'magnetization': utils.ang2vec(6.0, 30.0, -40.0)})] >>> inc, dec = -9.5, -13 >>> tf = sphere.tf(x, y, z, model, inc, dec) >>> # Give the coordinates of the dipoles >>> points = [[3000.0, 3000.0, 1000.0], [7000.0, 7000.0, 1000.0]] >>> p_true = np.hstack((ang2vec(CM*(4.*np.pi/3.)*6.0*1000**3, ... -20.0, -10.0), ... ang2vec(CM*(4.*np.pi/3.)*6.0*1000**3, ... 30.0, -40.0))) >>> estimate_true = [utils.vec2ang(p_true[3*i : 3*i + 3]) for i ... in range(len(points))] >>> # Make a solver and fit it to the data >>> solver = DipoleMagDir(x, y, z, tf, inc, dec, points).fit() >>> # Check the fit >>> np.allclose(tf, solver.predicted(), rtol=0.001, atol=0.001) True >>> # solver.p_ returns the Cartesian components of the >>> # estimated magnetization vectors >>> for p in solver.p_: print "%.10f" % p 2325.8255393651 -410.1057950109 -859.5903757213 1667.3411086852 -1399.0653093445 1256.6370614359 >>> # Check the estimated parameter vector >>> np.allclose(p_true, solver.p_, rtol=0.001, atol=0.001) True >>> # The parameter vector is not that useful so use solver.estimate_ >>> # to convert the estimated magnetization vectors in dipole moment, >>> # inclination and declination. >>> for e in solver.estimate_: ... print "%.10f %.10f %.10f" % (e[0], e[1], e[2]) 2513.2741228718 -20.0000000000 -10.0000000000 2513.2741228718 30.0000000000 -40.0000000000 >>> # Check the converted estimate >>> np.allclose(estimate_true, solver.estimate_, rtol=0.001, ... atol=0.001) True """ def __init__(self, x, y, z, data, inc, dec, points): super().__init__(data=data, nparams=3*len(points), islinear=True) self.x, self.y, self.z = x, y, z self.inc, self.dec = inc, dec self.points = points # Constants self.ndipoles = len(points) self.cte = 1/((4*np.pi/3)*G*SI2EOTVOS) # Geomagnetic Field versor self.F_versor = ang2vec(1.0, inc, dec) def predicted(self, p): return safe_dot(self.jacobian(p), p) def jacobian(self, p): x = self.x y = self.y z = self.z dipoles = [mesher.Sphere(xp, yp, zp, 1.) for xp, yp, zp in self.points] jac = np.empty((self.ndata, self.nparams), dtype=np.float) for i, dipole in enumerate(dipoles): k = 3*i derivative_gxx = sphere.gxx(x, y, z, [dipole], dens=self.cte) derivative_gxy = sphere.gxy(x, y, z, [dipole], dens=self.cte) derivative_gxz = sphere.gxz(x, y, z, [dipole], dens=self.cte) derivative_gyy = sphere.gyy(x, y, z, [dipole], dens=self.cte) derivative_gyz = sphere.gyz(x, y, z, [dipole], dens=self.cte) derivative_gzz = sphere.gzz(x, y, z, [dipole], dens=self.cte) jac[:, k] = T2NT * ((self.F_versor[0] * derivative_gxx) + (self.F_versor[1] * derivative_gxy) + (self.F_versor[2] * derivative_gxz)) jac[:, k + 1] = T2NT * ((self.F_versor[0] * derivative_gxy) + (self.F_versor[1] * derivative_gyy) + (self.F_versor[2] * derivative_gyz)) jac[:, k + 2] = T2NT * ((self.F_versor[0] * derivative_gxz) + (self.F_versor[1] * derivative_gyz) + (self.F_versor[2] * derivative_gzz)) return jac
[docs] def fmt_estimate(self, p): """ Convert the estimate parameters from Cartesian to inclination, declication, and intensity. """ angles = [vec2ang(p[3*i: 3*i + 3]) for i in range(len(self.points))] return angles