In [1]:
%pylab inline
from line_profiler import LineProfiler
from fatiando import gravmag, gridder, utils, mesher
from fatiando.vis import mpl


Welcome to pylab, a matplotlib-based Python environment [backend: module://IPython.zmq.pylab.backend_inline].
For more information, type 'help(pylab)'.

In [2]:
# Make synthetic data
inc, dec = -60, 23
props = {'magnetization':10}
model = [mesher.Prism(-500, 500, -1000, 1000, 1000, 4000, props)]
shape = (50, 50)
x, y, z = gridder.regular([-5000, 5000, -5000, 5000], shape, z=-150)
tf = utils.contaminate(gravmag.prism.tf(x, y, z, model, inc, dec), 5)
# Estimate the magnetization intensity
data = [gravmag.eqlayer.TotalField(x, y, z, tf, inc, dec)]
# Setup the layer
grid = mesher.PointGrid([-5000, 5000, -5000, 5000], 200, (100, 100))

Test the layers

Run the PEL once to see if the results are OK


In [3]:
damping, smoothness = 0*10.**-15, 10.**-3
windows, degree = (10, 10), 1
intensity, matrices = gravmag.eqlayer.pel(data, grid, windows, degree, damping, smoothness)
grid.addprop('magnetization', intensity)
predicted = gravmag.sphere.tf(x, y, z, grid, inc, dec)
residuals = tf - predicted
print "Residuals:"
print "mean:", residuals.mean()
print "stddev:", residuals.std()


Residuals:
mean: 1.52098406255
stddev: 7.18138872773

In [4]:
# Plot the layer and the fit
mpl.figure(figsize=(14,3))
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.colorbar()
mpl.m2km()
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, shape, levels, color='k')
mpl.m2km()
mpl.subplot(1, 3, 3)
mpl.title('Residuals (nT)')
mpl.hist(residuals, bins=10)


Out[4]:
(array([   4,    5,   16,   68,  634, 1253,  431,   61,   20,    8]),
 array([-41.96712938, -33.93165344, -25.89617749, -17.86070154,
        -9.82522559,  -1.78974964,   6.2457263 ,  14.28120225,
        22.3166782 ,  30.35215415,  38.38763009]),
 <a list of 10 Patch objects>)

Run a classic layer to see


In [5]:
classic_damping = 0.02
intensity, predicted = gravmag.eqlayer.classic(data, grid, classic_damping)
grid.addprop('magnetization', intensity)
residuals = tf - predicted[0]
print "Residuals:"
print "mean:", residuals.mean()
print "stddev:", residuals.std()


Residuals:
mean: 2.09208298987
stddev: 2.3472550405

In [6]:
# Plot the layer and the fit
mpl.figure(figsize=(14,3))
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.colorbar()
mpl.m2km()
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.m2km()
mpl.subplot(1, 3, 3)
mpl.title('Residuals (nT)')
mpl.hist(residuals, bins=10)


Out[6]:
(array([ 14,  88, 301, 661, 608, 404, 235, 137,  46,   6]),
 array([ -4.58424174,  -3.08928293,  -1.59432413,  -0.09936532,
         1.39559349,   2.8905523 ,   4.3855111 ,   5.88046991,
         7.37542872,   8.87038753,  10.36534633]),
 <a list of 10 Patch objects>)

Benchmark them


In [7]:
%timeit gravmag.eqlayer.classic(data, grid, classic_damping)


1 loops, best of 3: 17.7 s per loop

In [8]:
%timeit gravmag.eqlayer.pel(data, grid, windows, degree, damping, smoothness)


1 loops, best of 3: 5.07 s per loop

Profiling Classic


In [9]:
%prun -T gravmag_eqlayer.classic.profile gravmag.eqlayer.classic(data, grid, classic_damping)
!cat gravmag_eqlayer.classic.profile


 
*** Profile printout saved to text file u'gravmag_eqlayer.classic.profile'. 
         201703 function calls in 18.053 seconds

   Ordered by: internal time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
       98   12.750    0.130   12.750    0.130 {numpy.core._dotblas.dot}
    10000    4.065    0.000    4.537    0.000 sphere.py:57(tf)
        1    0.523    0.523    5.180    5.180 eqlayer.py:57(sensitivity)
    20389    0.146    0.000    0.146    0.000 {numpy.core.multiarray.array}
    10001    0.142    0.000    0.142    0.000 utils.py:237(dircos)
        1    0.098    0.098   18.041   18.041 eqlayer.py:66(classic)
    10000    0.077    0.000    0.196    0.000 linalg.py:1840(norm)
    10000    0.056    0.000    0.101    0.000 mesher.py:683(__getitem__)
    10000    0.027    0.000    0.027    0.000 {numpy.core.multiarray.empty_like}
    10000    0.024    0.000    0.024    0.000 {method 'fill' of 'numpy.ndarray' objects}
    10000    0.024    0.000    0.033    0.000 mesher.py:559(__init__)
    10000    0.020    0.000    0.020    0.000 {method 'reduce' of 'numpy.ufunc' objects}
    10001    0.018    0.000    0.119    0.000 mesher.py:698(next)
    10000    0.013    0.000    0.064    0.000 numeric.py:65(zeros_like)
    20000    0.013    0.000    0.013    0.000 mesher.py:689(<genexpr>)
        1    0.011    0.011   18.053   18.053 <string>:1(<module>)
    10000    0.009    0.000    0.009    0.000 mesher.py:49(__init__)
        1    0.009    0.009    0.467    0.467 iterative.py:192(cg)
    20201    0.008    0.000    0.008    0.000 {isinstance}
    10197    0.007    0.000    0.091    0.000 numeric.py:167(asarray)
    10001    0.007    0.000    0.007    0.000 {method 'ravel' of 'numpy.ndarray' objects}
    10000    0.002    0.000    0.002    0.000 {method 'conj' of 'numpy.ndarray' objects}
      190    0.002    0.000    0.459    0.002 interface.py:92(matvec)
      191    0.001    0.000    0.001    0.000 {method 'reshape' of 'numpy.ndarray' objects}
       95    0.000    0.000    0.454    0.005 interface.py:232(matvec)
      192    0.000    0.000    0.000    0.000 numeric.py:237(asanyarray)
        1    0.000    0.000    0.000    0.000 {method 'trace' of 'numpy.ndarray' objects}
        3    0.000    0.000    0.000    0.000 {numpy.core.multiarray.empty}
        1    0.000    0.000    0.000    0.000 {range}
       95    0.000    0.000    0.000    0.000 utils.py:25(id)
        1    0.000    0.000    0.000    0.000 fromnumeric.py:986(trace)
        1    0.000    0.000    0.000    0.000 utils.py:28(make_system)
        1    0.000    0.000    0.000    0.000 interface.py:203(aslinearoperator)
        4    0.000    0.000    0.000    0.000 fromnumeric.py:2116(rank)
        2    0.000    0.000    0.000    0.000 {numpy.core.multiarray.zeros}
        1    0.000    0.000    0.000    0.000 shape_base.py:58(atleast_2d)
        2    0.000    0.000    0.000    0.000 interface.py:59(__init__)
        2    0.000    0.000    0.000    0.000 sputils.py:96(isshape)
        4    0.000    0.000    0.000    0.000 sputils.py:81(isintlike)
        6    0.000    0.000    0.000    0.000 {len}
        4    0.000    0.000    0.000    0.000 sputils.py:111(issequence)
        1    0.000    0.000    0.000    0.000 {sum}
        1    0.000    0.000    0.000    0.000 utils.py:18(coerce)
        1    0.000    0.000    0.000    0.000 utils.py:77(postprocess)
        3    0.000    0.000    0.000    0.000 {hasattr}
        2    0.000    0.000    0.000    0.000 {method 'append' of 'list' objects}
        2    0.000    0.000    0.000    0.000 eqlayer.py:70(<genexpr>)
        2    0.000    0.000    0.000    0.000 {getattr}
        1    0.000    0.000    0.000    0.000 mesher.py:680(__len__)
        1    0.000    0.000    0.000    0.000 mesher.py:694(__iter__)
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

In [10]:
lp = LineProfiler(gravmag.eqlayer.classic)
lp.runcall(gravmag.eqlayer.classic, data, grid, classic_damping)
lp.print_stats()


Timer unit: 1e-06 s

File: /home/leo/src/fatiando/fatiando/gravmag/eqlayer.py
Function: classic at line 66
Total time: 18.3068 s

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
    66                                           def classic(data, grid, damping=0.):
    67                                               """
    68                                               The classic equivalent layer with damping regularization.
    69                                               """
    70         1            7      7.0      0.0      ndata = sum(d.size for d in data)
    71         1           24     24.0      0.0      sensitivity = numpy.empty((ndata, grid.size), dtype=float)
    72         1            6      6.0      0.0      datavec = numpy.empty(ndata, dtype=float)
    73         1            1      1.0      0.0      bottom = 0
    74         2            2      1.0      0.0      for d in data:
    75         1      5600880 5600880.0     30.6          sensitivity[bottom:bottom + d.size, :] = d.sensitivity(grid)
    76         1           21     21.0      0.0          datavec[bottom:bottom + d.size] = d.data
    77         1            2      2.0      0.0          bottom += d.size
    78         1     12193283 12193283.0     66.6      system = numpy.dot(sensitivity, sensitivity.T)
    79         1            4      4.0      0.0      if damping != 0.:
    80         1            3      3.0      0.0          order = len(system)
    81         1          147    147.0      0.0          scale = float(numpy.trace(system))/order
    82         1           31     31.0      0.0          diag = range(order)
    83         1         1268   1268.0      0.0          system[diag, diag] += damping*scale
    84         1       466618 466618.0      2.5      tmp = linalg.cg(system, datavec)[0]
    85         1        24418  24418.0      0.1      estimate = numpy.dot(sensitivity.T, tmp)
    86         1        20053  20053.0      0.1      pred = numpy.dot(sensitivity, estimate)
    87         1            3      3.0      0.0      predicted = []
    88         1            1      1.0      0.0      start = 0
    89         2            4      2.0      0.0      for d in data:
    90         1            9      9.0      0.0          predicted.append(pred[start:start + d.size])
    91         1            2      2.0      0.0          start += d.size
    92         1            2      2.0      0.0      return estimate, predicted

Profiling PEL


In [11]:
%prun -T gravmag_eqlayer.pel.profile gravmag.eqlayer.pel(data, grid, windows, degree, damping, smoothness)
!cat gravmag_eqlayer.pel.profile


 
*** Profile printout saved to text file u'gravmag_eqlayer.pel.profile'. 
         287089 function calls (287087 primitive calls) in 5.271 seconds

   Ordered by: internal time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    10000    4.136    0.000    4.609    0.000 sphere.py:57(tf)
      302    0.201    0.001    0.201    0.001 {numpy.core._dotblas.dot}
      100    0.179    0.002    4.910    0.049 eqlayer.py:57(sensitivity)
    22626    0.163    0.000    0.163    0.000 {numpy.core.multiarray.array}
    10100    0.145    0.000    0.145    0.000 utils.py:237(dircos)
    10000    0.078    0.000    0.200    0.000 linalg.py:1840(norm)
    10000    0.057    0.000    0.102    0.000 mesher.py:683(__getitem__)
    10000    0.025    0.000    0.025    0.000 {method 'fill' of 'numpy.ndarray' objects}
    10000    0.024    0.000    0.033    0.000 mesher.py:559(__init__)
      100    0.023    0.000    4.933    0.049 eqlayer.py:142(_gkmatrix)
    10000    0.020    0.000    0.020    0.000 {numpy.core.multiarray.empty_like}
        1    0.019    0.019    5.244    5.244 eqlayer.py:201(_pel_matrices)
    10000    0.019    0.000    0.019    0.000 {method 'reduce' of 'numpy.ufunc' objects}
    10100    0.018    0.000    0.120    0.000 mesher.py:698(next)
    10000    0.013    0.000    0.057    0.000 numeric.py:65(zeros_like)
    20000    0.013    0.000    0.013    0.000 mesher.py:689(<genexpr>)
     3600    0.013    0.000    0.017    0.000 lil.py:226(_insertat2)
    36711    0.012    0.000    0.012    0.000 {isinstance}
    10000    0.009    0.000    0.009    0.000 mesher.py:49(__init__)
    10502    0.008    0.000    0.008    0.000 {method 'ravel' of 'numpy.ndarray' objects}
      200    0.008    0.000    0.020    0.000 eqlayer.py:113(_bkmatrix)
    11418    0.008    0.000    0.105    0.000 numeric.py:167(asarray)
      303    0.008    0.000    0.016    0.000 compressed.py:101(check_format)
    14500    0.006    0.000    0.009    0.000 numeric.py:1574(isscalar)
     3600    0.005    0.000    0.029    0.000 lil.py:289(__setitem__)
        1    0.005    0.005    0.005    0.005 {numpy.linalg.lapack_lite.dgesv}
      303    0.005    0.000    0.006    0.000 compressed.py:622(prune)
        1    0.003    0.003    0.037    0.037 eqlayer.py:174(_pel_rmatrix)
  303/301    0.003    0.000    0.028    0.000 compressed.py:20(__init__)
    10000    0.003    0.000    0.003    0.000 {method 'conj' of 'numpy.ndarray' objects}
      202    0.002    0.000    0.003    0.000 function_base.py:6(linspace)
      100    0.002    0.000    0.006    0.000 eqlayer.py:165(_rightside)
      504    0.002    0.000    0.003    0.000 sputils.py:116(_isinstance)
      302    0.002    0.000    0.002    0.000 sputils.py:81(isintlike)
      100    0.002    0.000    0.034    0.000 csc.py:116(__getitem__)
      100    0.001    0.000    0.012    0.000 csc.py:84(transpose)
        1    0.001    0.001    0.014    0.014 eqlayer.py:253(_coefs2prop)
      200    0.001    0.000    0.012    0.000 fromnumeric.py:445(transpose)
      100    0.001    0.000    0.001    0.000 {_csr.get_csr_submatrix}
      201    0.001    0.000    0.001    0.000 {numpy.core.multiarray.zeros}
      101    0.001    0.000    0.003    0.000 sputils.py:18(upcast)
     8738    0.001    0.000    0.001    0.000 {len}
      100    0.001    0.000    0.005    0.000 mesher.py:663(__init__)
        1    0.001    0.001    0.003    0.003 lil.py:423(tocsr)
      304    0.001    0.000    0.001    0.000 base.py:59(set_shape)
      100    0.001    0.000    0.006    0.000 compressed.py:263(_mul_multivector)
     3600    0.001    0.000    0.001    0.000 {_bisect.bisect_left}
      200    0.001    0.000    0.011    0.000 fromnumeric.py:32(_wrapit)
     4813    0.001    0.000    0.001    0.000 base.py:81(get_shape)
      100    0.001    0.000    0.010    0.000 csr.py:320(_get_submatrix)
        1    0.001    0.001    0.006    0.006 mesher.py:721(split)
      100    0.001    0.000    0.009    0.000 base.py:229(__mul__)
     7302    0.001    0.000    0.001    0.000 {method 'append' of 'list' objects}
      100    0.001    0.000    0.008    0.000 csr.py:84(transpose)
      100    0.001    0.000    0.012    0.000 csr.py:163(__getitem__)
        1    0.001    0.001    0.001    0.001 lil.py:59(__init__)
      303    0.001    0.000    0.001    0.000 sputils.py:96(isshape)
      100    0.001    0.000    0.001    0.000 {_csc.csc_matvecs}
     1008    0.001    0.000    0.001    0.000 {method 'split' of 'str' objects}
      304    0.001    0.000    0.001    0.000 base.py:51(__init__)
      209    0.001    0.000    0.001    0.000 {numpy.core.multiarray.empty}
      400    0.001    0.000    0.001    0.000 {method 'reshape' of 'numpy.ndarray' objects}
     1214    0.001    0.000    0.001    0.000 compressed.py:85(getnnz)
        1    0.000    0.000    5.271    5.271 eqlayer.py:276(pel)
     1010    0.000    0.000    0.000    0.000 {numpy.core.multiarray.can_cast}
      303    0.000    0.000    0.001    0.000 sputils.py:50(to_native)
      200    0.000    0.000    0.020    0.000 base.py:370(__getattr__)
      200    0.000    0.000    0.000    0.000 {method 'repeat' of 'numpy.ndarray' objects}
     3600    0.000    0.000    0.000    0.000 {method 'extend' of 'list' objects}
      404    0.000    0.000    0.003    0.000 base.py:548(isspmatrix)
      303    0.000    0.000    0.001    0.000 data.py:17(__init__)
      400    0.000    0.000    0.000    0.000 {zip}
      302    0.000    0.000    0.001    0.000 sputils.py:111(issequence)
      202    0.000    0.000    0.000    0.000 {numpy.core.multiarray.arange}
      100    0.000    0.000    0.001    0.000 function_base.py:3208(meshgrid)
      911    0.000    0.000    0.000    0.000 fromnumeric.py:2116(rank)
      303    0.000    0.000    0.000    0.000 {method 'newbyteorder' of 'numpy.dtype' objects}
      303    0.000    0.000    0.000    0.000 sputils.py:54(getdtype)
      100    0.000    0.000    0.001    0.000 sputils.py:77(isscalarlike)
      200    0.000    0.000    0.000    0.000 csr.py:325(process_slice)
        1    0.000    0.000    5.271    5.271 <string>:1(<module>)
      603    0.000    0.000    0.000    0.000 csr.py:157(_swap)
      303    0.000    0.000    0.000    0.000 {getattr}
      100    0.000    0.000    0.001    0.000 csr.py:586(get_csr_submatrix)
      200    0.000    0.000    0.000    0.000 {method 'transpose' of 'numpy.ndarray' objects}
      100    0.000    0.000    0.001    0.000 csc.py:216(csc_matvecs)
      200    0.000    0.000    0.000    0.000 csr.py:349(check_bounds)
        2    0.000    0.000    0.000    0.000 {numpy.core.multiarray._fastCopyAndTranspose}
      100    0.000    0.000    0.000    0.000 numeric.py:237(asanyarray)
      100    0.000    0.000    0.001    0.000 sputils.py:124(isdense)
      100    0.000    0.000    0.000    0.000 fromnumeric.py:107(reshape)
      306    0.000    0.000    0.000    0.000 csc.py:149(_swap)
      100    0.000    0.000    0.000    0.000 mesher.py:694(__iter__)
      101    0.000    0.000    0.000    0.000 data.py:20(_get_dtype)
        1    0.000    0.000    0.000    0.000 {_csr.csr_tocsc}
        1    0.000    0.000    0.006    0.006 linalg.py:244(solve)
        2    0.000    0.000    0.000    0.000 {method 'trace' of 'numpy.ndarray' objects}
        1    0.000    0.000    0.000    0.000 {method 'cumsum' of 'numpy.ndarray' objects}
        3    0.000    0.000    0.000    0.000 {range}
      100    0.000    0.000    0.000    0.000 mesher.py:680(__len__)
        1    0.000    0.000    0.000    0.000 csr.py:112(tocsc)
        2    0.000    0.000    0.000    0.000 fromnumeric.py:986(trace)
        3    0.000    0.000    0.000    0.000 eqlayer.py:96(_ncoefficients)
        1    0.000    0.000    0.000    0.000 {method 'astype' of 'numpy.ndarray' objects}
        1    0.000    0.000    0.003    0.003 lil.py:445(tocsc)
        1    0.000    0.000    0.000    0.000 linalg.py:99(_commonType)
        1    0.000    0.000    0.000    0.000 {numpy.core.multiarray.concatenate}
        1    0.000    0.000    0.000    0.000 linalg.py:139(_fastCopyAndTranspose)
        1    0.000    0.000    0.000    0.000 csr.py:177(csr_tocsc)
        1    0.000    0.000    0.000    0.000 fromnumeric.py:1643(cumsum)
        1    0.000    0.000    0.003    0.003 base.py:178(asformat)
        4    0.000    0.000    0.000    0.000 {sum}
        1    0.000    0.000    0.000    0.000 linalg.py:157(_assertSquareness)
        1    0.000    0.000    0.000    0.000 compressed.py:90(_set_self)
        1    0.000    0.000    0.000    0.000 linalg.py:127(_to_native_byte_order)
        2    0.000    0.000    0.000    0.000 linalg.py:84(_realType)
        1    0.000    0.000    0.000    0.000 linalg.py:151(_assertRank2)
        5    0.000    0.000    0.000    0.000 {issubclass}
        3    0.000    0.000    0.000    0.000 linalg.py:71(isComplexType)
        2    0.000    0.000    0.000    0.000 eqlayer.py:231(<genexpr>)
        2    0.000    0.000    0.000    0.000 linalg.py:66(_makearray)
        1    0.000    0.000    0.000    0.000 compressed.py:597(__set_sorted)
        1    0.000    0.000    0.000    0.000 {max}
        2    0.000    0.000    0.000    0.000 {method 'get' of 'dict' objects}
        1    0.000    0.000    0.000    0.000 {min}
        1    0.000    0.000    0.000    0.000 {method '__array_prepare__' of 'numpy.ndarray' objects}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

In [12]:
lp = LineProfiler(gravmag.eqlayer.pel)
lp.runcall(gravmag.eqlayer.pel, data, grid, windows, degree, damping, smoothness)
lp.print_stats()


Timer unit: 1e-06 s

File: /home/leo/src/fatiando/fatiando/gravmag/eqlayer.py
Function: pel at line 276
Total time: 5.58372 s

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
   276                                           def pel(data, grid, windows, degree=1, damping=0., smoothness=0.,
   277                                                   matrices=None):
   278                                               """
   279                                               The Polynomial Equivalent Layers
   280                                               """
   281         1            2      2.0      0.0      ny, nx = windows
   282         1        10664  10664.0      0.2      grids = grid.split(nx, ny)
   283         1            3      3.0      0.0      if grid.shape[1]%nx != 0 or grid.shape[0]%ny != 0:
   284                                                   raise ValueError(
   285                                                       'PEL requires windows to be divisable by the grid shape')
   286         1            2      2.0      0.0      ngrids = len(grids)
   287         1            4      4.0      0.0      pergrid = _ncoefficients(degree)
   288         1            1      1.0      0.0      ncoefs = ngrids*pergrid
   289         1            1      1.0      0.0      modelmatrix, smoothmatrix, rightside = _pel_matrices(data, windows, grid,
   290         1      5544631 5544631.0     99.3          grids, degree)
   291         1          102    102.0      0.0      fg = numpy.trace(modelmatrix)
   292         1           33     33.0      0.0      fr = numpy.trace(smoothmatrix)
   293         1          511    511.0      0.0      leftside = modelmatrix + (float(smoothness*fg)/fr)*smoothmatrix
   294         1          481    481.0      0.0      leftside[range(ncoefs),range(ncoefs)] += float(damping*fg)/ncoefs
   295         1         7493   7493.0      0.1      coefs = numpy.linalg.solve(leftside, rightside)
   296         1        19784  19784.0      0.4      estimate = _coefs2prop(coefs, grid, grids, windows, degree)
   297         1            4      4.0      0.0      return estimate, [modelmatrix, smoothmatrix, rightside]


In [13]:
lp = LineProfiler(gravmag.eqlayer._pel_matrices)
lp.runcall(gravmag.eqlayer.pel, data, grid, windows, degree, damping, smoothness)
lp.print_stats()


Timer unit: 1e-06 s

File: /home/leo/src/fatiando/fatiando/gravmag/eqlayer.py
Function: _pel_matrices at line 201
Total time: 5.68674 s

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
   201                                           def _pel_matrices(data, windows, grid, grids, degree):
   202                                               """
   203                                               Compute the matrices needed by the PEL.
   204                                           
   205                                               1. The Hessian of the model (B^TG^TGB)
   206                                               2. The Hessian of smoothness (B^TR^TRB)
   207                                               3. The right-side vector (B^TG^Td)
   208                                           
   209                                               >>> from fatiando.mesher import PointGrid
   210                                               >>> x, y, z, g = numpy.zeros((4, 500))
   211                                               >>> data = [Gz(x, y, z, g)]
   212                                               >>> grid = PointGrid((0, 10, 0, 10), 10, (10, 10))
   213                                               >>> grid.size
   214                                               100
   215                                               >>> grids = grid.split(2, 2)
   216                                               >>> print [g.size for g in grids]
   217                                               [25, 25, 25, 25]
   218                                               >>> model, smooth, right = _pel_matrices(data, (2, 2), grid, grids, 2)
   219                                               >>> coefs = _ncoefficients(2)*len(grids)
   220                                               >>> coefs
   221                                               24
   222                                               >>> model.shape
   223                                               (24, 24)
   224                                               >>> right.shape
   225                                               (24,)
   226                                           
   227                                               """
   228         1            3      3.0      0.0      ngrids = len(grids)
   229         1            2      2.0      0.0      pergrid = _ncoefficients(degree)
   230         1            1      1.0      0.0      ncoefs = ngrids*pergrid
   231         1            6      6.0      0.0      ndata = sum(d.size for d in data)
   232                                               # make the finite differences matrix for the window borders
   233         1        84628  84628.0      1.5      rmatrix, nderivs = _pel_rmatrix(windows, grid, grids)
   234         1           92     92.0      0.0      rightside = numpy.empty(ncoefs, dtype=float)
   235         1            4      4.0      0.0      gb = numpy.empty((ndata, ncoefs), dtype=float)
   236         1            3      3.0      0.0      rb = numpy.empty((nderivs, ncoefs), dtype=float)
   237         1            2      2.0      0.0      st = 0
   238       101          186      1.8      0.0      for i, grid in enumerate(grids):
   239       100         8988     89.9      0.2          bk = _bkmatrix(grid, degree)
   240       100      5322453  53224.5     93.6          gk = _gkmatrix(data, ndata, grid)
   241       100        77786    777.9      1.4          gkbk = numpy.dot(gk, bk)
   242       100        10558    105.6      0.2          gb[:,i*pergrid:(i + 1)*pergrid] = gkbk
   243                                                   # Make a part of the right-side vector
   244       100         6779     67.8      0.1          rightside[i*pergrid:(i + 1)*pergrid] = _rightside(gkbk, data, pergrid)
   245                                                   # Make the RB matrix
   246       100          190      1.9      0.0          en = st + grid.size
   247       100        57541    575.4      1.0          rb[:,i*pergrid:(i + 1)*pergrid] = rmatrix[:,st:en]*bk
   248       100          191      1.9      0.0          st = en
   249         1        69002  69002.0      1.2      modelmatrix = numpy.dot(gb.T, gb)
   250         1        48314  48314.0      0.8      smoothmatrix = numpy.dot(rb.T, rb)
   251         1            9      9.0      0.0      return modelmatrix, smoothmatrix, rightside


In [14]:
lp = LineProfiler(gravmag.eqlayer._gkmatrix)
lp.runcall(gravmag.eqlayer.pel, data, grid, windows, degree, damping, smoothness)
lp.print_stats()


Timer unit: 1e-06 s

File: /home/leo/src/fatiando/fatiando/gravmag/eqlayer.py
Function: _gkmatrix at line 142
Total time: 5.20938 s

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
   142                                           def _gkmatrix(data, ndata, grid):
   143                                               """
   144                                               Make the sensitivity matrix of a subgrid.
   145                                           
   146                                               >>> from fatiando.mesher import PointGrid
   147                                               >>> x, y, z, g = numpy.zeros((4, 500))
   148                                               >>> data = [Gz(x, y, z, g)]
   149                                               >>> grid = PointGrid((0, 10, 0, 10), 10, (10, 10))
   150                                               >>> grid.size
   151                                               100
   152                                               >>> gk = _gkmatrix(data, 500, grid)
   153                                               >>> gk.shape
   154                                               (500, 100)
   155                                           
   156                                               """
   157       100          517      5.2      0.0      sensitivity = numpy.empty((ndata, grid.size), dtype=float)
   158       100           94      0.9      0.0      start = 0
   159       200          178      0.9      0.0      for d in data:
   160       100           90      0.9      0.0          end = start + d.size
   161       100      5208221  52082.2    100.0          sensitivity[start:end,:] = d.sensitivity(grid)
   162       100          206      2.1      0.0          start = end
   163       100           72      0.7      0.0      return sensitivity


In [15]:
lp = LineProfiler(gravmag.eqlayer.TotalField.sensitivity)
lp.runcall(gravmag.eqlayer.pel, data, grid, windows, degree, damping, smoothness)
lp.print_stats()


Timer unit: 1e-06 s

File: /home/leo/src/fatiando/fatiando/gravmag/eqlayer.py
Function: sensitivity at line 57
Total time: 5.36218 s

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
    57                                               def sensitivity(self, grid):
    58       100          241      2.4      0.0          x, y, z = self.x, self.y, self.z
    59       100          154      1.5      0.0          inc, dec = self.inc, self.dec
    60       100         2405     24.1      0.0          mag = utils.dircos(self.sinc, self.sdec)
    61       100          648      6.5      0.0          sens = numpy.empty((self.size, len(grid)), dtype=float)
    62     10100       214977     21.3      4.0          for i, s in enumerate(grid):
    63     10000      5143668    514.4     95.9              sens[:,i] = kernel.tf(x, y, z, [s], inc, dec, pmag=mag)
    64       100           85      0.8      0.0          return sens

Looking for a better way to build the sensitivity than using transpose:


In [16]:
%timeit transpose([arange(100) for i in xrange(100)])


1000 loops, best of 3: 880 us per loop

In [17]:
def matrix():
    a = zeros((100,100))
    for i in xrange(100):
        a[:,i] = arange(100)
    return a
%timeit matrix()
a = matrix()
print a


1000 loops, best of 3: 281 us per loop
[[  0.   0.   0. ...,   0.   0.   0.]
 [  1.   1.   1. ...,   1.   1.   1.]
 [  2.   2.   2. ...,   2.   2.   2.]
 ..., 
 [ 97.  97.  97. ...,  97.  97.  97.]
 [ 98.  98.  98. ...,  98.  98.  98.]
 [ 99.  99.  99. ...,  99.  99.  99.]]