Source code for geodat.math

import numpy
from . import keepdims

[docs]def integrate(data, axes=None, iax=None, **kwargs): ''' Integrate data along a selected set of axes Dimension is maintained using keepdims.sum data - numpy.ndarray axes - a list of axes iax - a list of integers that select which axes are integrated along ''' if axes is None: axes = [numpy.arange(idim) for idim in data.shape] if iax is None: iax = range(data.ndim) if type(iax) is not list: iax = [iax] inc = numpy.ones(data.shape, dtype=data.dtype) for ax in iax: ax_data = numpy.array(axes[ax], dtype=data.dtype) dx = numpy.gradient(ax_data)[(numpy.newaxis,)*ax + \ (slice(None),) + \ (numpy.newaxis,)*(data.ndim-ax-1)] inc *= numpy.abs(dx) # Perform integration return keepdims.sum(data*inc, axis=iax, **kwargs)
[docs]def gradient(f, dx=1., axis=0, mask_boundary=False): '''Compute central difference for a pariticular axis Input: f - numpy ndarray dx - spacing ''' if f.shape[axis] <= 1: raise ValueError("Length of axis {} must be >1".format(axis)) result = numpy.ma.zeros(f.shape, dtype=f.dtype) axis = axis % f.ndim sl_right = (slice(None),)*axis \ + (slice(2, None),) + (slice(None),)*(f.ndim-axis-1) sl_left = (slice(None),)*axis \ + (slice(0, -2),) + (slice(None),)*(f.ndim-axis-1) sl_center = (slice(None),)*axis \ + (slice(1, -1),) + (slice(None),)*(f.ndim-axis-1) # Make sure all dimension of dx have len>1 dx = dx.squeeze() # Broadcasting dx sl_dx_center = (numpy.newaxis,)*axis + (slice(1, -1),) \ + (numpy.newaxis,)*(f.ndim-axis-1) if numpy.isscalar(dx): result[sl_center] = (f[sl_right] - f[sl_left])/2./dx elif result.ndim == dx.ndim: result[sl_center] = (f[sl_right] - f[sl_left])/2./dx[sl_center] else: result[sl_center] = (f[sl_right] - f[sl_left])/2./dx[sl_dx_center] # Boundary values b1 = (slice(None),)*axis \ + (slice(0, 1),) + (slice(None),)*(f.ndim-axis-1) b2 = (slice(None),)*axis \ + (slice(-1, None),) + (slice(None),)*(f.ndim-axis-1) if mask_boundary: result[b1] = numpy.ma.masked result[b2] = numpy.ma.masked else: b1_p1 = (slice(None),)*axis \ + (slice(1, 2),) + (slice(None),)*(f.ndim-axis-1) b2_m1 = (slice(None),)*axis \ + (slice(-2, -1),) + (slice(None),)*(f.ndim-axis-1) sl_dx_0 = (numpy.newaxis,)*axis + (slice(0, 1),) \ + (numpy.newaxis,)*(f.ndim-axis-1) sl_dx_end = (numpy.newaxis,)*axis + (slice(-1, None),) \ + (numpy.newaxis,)*(f.ndim-axis-1) if numpy.isscalar(dx): result[b1] = (f[b1_p1] - f[b1])/dx result[b2] = (f[b2] - f[b2_m1])/dx elif result.ndim == dx.ndim: result[b1] = (f[b1_p1] - f[b1])/dx[b1] result[b2] = (f[b2] - f[b2_m1])/dx[b2] else: result[b1] = (f[b1_p1] - f[b1])/dx[sl_dx_0] result[b2] = (f[b2] - f[b2_m1])/dx[sl_dx_end] return result
[docs]def div(ux, uy, dx, dy, xaxis=-1, yaxis=-2): ''' Compute the divergence of a vector field ux,uy dx, dy are either 1-d array or a scalar xaxis - integer indicating the location of x axis (default = -1) yaxis - integer indicating the location of y axis (default = -2) ''' result = gradient(ux, dx, axis=xaxis, mask_boundary=True) + \ gradient(uy, dy, axis=yaxis, mask_boundary=True) return result
def _div(ux, uy, dx, dy): ''' Backup - Compute the divergence of a vector field ux,uy dx, dy are either 1-d array or a scalar xaxis - integer indicating the location of x axis (default = -1) yaxis - integer indicating the location of y axis (default = -2) ''' ny, nx = ux.shape[-2:] if numpy.isscalar(dx) or dx.ndim <= 1: dx = numpy.resize(dx, (nx, ny)).T if numpy.isscalar(dy) or dy.ndim <= 1: dy = numpy.resize(dy, (ny, nx)) result = numpy.ma.zeros(ux.shape) result[..., 1:-1, 1:-1] = \ (ux[..., 1:-1, 2:]-ux[..., 1:-1, 0:-2])/2./dx[1:-1, 1:-1] \ + (uy[..., 2:, 1:-1]-uy[..., 0:-2, 1:-1])/2./dy[1:-1, 1:-1] result[..., 0, :] = numpy.ma.masked result[..., -1, :] = numpy.ma.masked result[..., :, 0] = numpy.ma.masked result[..., :, -1] = numpy.ma.masked return result
Fork me on GitHub