Пример #1
0
def multiplymatrices_incl_errors(inmatrix1,
                                 inmatrix2,
                                 inmatrix1_err=None,
                                 inmatrix2_err=None):

    if inmatrix1 is None or inmatrix2 is None:
        raise MTex.MTpyError_inputarguments(
            'ERROR - two 2x2 arrays needed as input')

    if inmatrix1.shape != inmatrix2.shape:
        raise MTex.MTpyError_inputarguments(
            'ERROR - two 2x2 arrays with same dimensions needed as input')

    prod = np.array(np.dot(np.matrix(inmatrix1), np.matrix(inmatrix2)))

    if (inmatrix1_err is None) or (inmatrix1_err is None):
        return prod, None

    var = np.zeros((2, 2))
    var[0,0] = (inmatrix1_err[0,0] * inmatrix2[0,0])**2 + (inmatrix1_err[0,1] * inmatrix2[1,0])**2+\
                (inmatrix2_err[0,0] * inmatrix1[0,0])**2 + (inmatrix2_err[1,0] * inmatrix1[0,1])**2
    var[0,1] = (inmatrix1_err[0,0] * inmatrix2[0,1])**2 + (inmatrix1_err[0,1] * inmatrix2[1,1])**2+\
                (inmatrix2_err[0,1] * inmatrix1[0,0])**2 + (inmatrix2_err[1,1] * inmatrix1[0,1])**2
    var[1,0] = (inmatrix1_err[1,0] * inmatrix2[0,0])**2 + (inmatrix1_err[1,1] * inmatrix2[1,0])**2+\
                (inmatrix2_err[0,0] * inmatrix1[1,0])**2 + (inmatrix2_err[1,0] * inmatrix1[1,1])**2
    var[1,1] = (inmatrix1_err[1,0] * inmatrix2[0,1])**2 + (inmatrix1_err[1,1] * inmatrix2[1,1])**2+\
                (inmatrix2_err[0,1] * inmatrix1[1,0])**2 + (inmatrix2_err[1,1] * inmatrix1[1,1])**2

    return prod, np.sqrt(var)
Пример #2
0
def rotatematrix_incl_errors(inmatrix, angle, inmatrix_err=None):

    if inmatrix is None:
        raise MTex.MTpyError_inputarguments(
            'Matrix AND eror matrix must be defined')

    if (inmatrix_err is not None) and (inmatrix.shape != inmatrix_err.shape):
        raise MTex.MTpyError_inputarguments(
            'Matrix and err-matrix shapes do not match: %s - %s' %
            (str(inmatrix.shape), str(inmatrix_err.shape)))

    try:
        degreeangle = angle % 360
    except:
        raise MTex.MTpyError_inputarguments(
            '"Angle" must be a valid number (in degrees)')

    phi = math.radians(degreeangle)

    cphi = np.cos(phi)
    sphi = np.sin(phi)

    # JP: Changed the rotation matrix to be formulated to rotate
    # counter clockwise, I cannot find a good reason for this except that
    # when you plot the strike and phase tensors the look correct with this
    # formulation.
    rotmat = np.array([[cphi, sphi], [-sphi, cphi]])
    # rotmat = np.array([[ cphi, -sphi], [sphi, cphi]])
    rotated_matrix = np.dot(np.dot(rotmat, inmatrix), np.linalg.inv(rotmat))

    errmat = None
    if (inmatrix_err is not None):
        err_orig = np.real(inmatrix_err)
        errmat = np.zeros_like(inmatrix_err)

        # standard propagation of errors:
        errmat[0,0] = np.sqrt( (cphi**2 * err_orig[0,0])**2 + \
                              (cphi * sphi * err_orig[0,1])**2 + \
                                  (cphi * sphi * err_orig[1,0])**2 + \
                                      (sphi**2 * err_orig[1,1])**2 )
        errmat[0,1] = np.sqrt( (cphi**2 * err_orig[0,1])**2 + \
                              (cphi * sphi * err_orig[1,1])**2 + \
                                  (cphi * sphi * err_orig[0,0])**2 + \
                                      (sphi**2 * err_orig[1,0])**2 )
        errmat[1,0] = np.sqrt( (cphi**2 * err_orig[1,0])**2 + \
                              (cphi * sphi * err_orig[1,1])**2 +\
                                  (cphi * sphi * err_orig[0,0])**2 + \
                                      (sphi**2 * err_orig[0,1])**2 )
        errmat[1,1] = np.sqrt( (cphi**2 * err_orig[1,1])**2 + \
                              (cphi * sphi * err_orig[0,1])**2 + \
                                  (cphi * sphi * err_orig[1,0])**2 + \
                                      (sphi**2 * err_orig[0,0])**2 )

    return rotated_matrix, errmat
Пример #3
0
def rhophi2z(rho, phi, freq):
    """
        Convert impedance-style information given in Rho/Phi format into complex valued Z.

        Input:
        rho - 2x2 array (real) - in Ohm m
        phi - 2x2 array (real) - in degrees
        freq - scalar - frequency in Hz

        Output:
        Z - 2x2 array (complex)
    """

    try:
        if rho.shape != (2, 2) or phi.shape != (2, 2):
            raise
        if not (rho.dtype in ['float', 'int']
                and phi.dtype in ['float', 'int']):
            raise

    except:
        raise MTex.MTpyError_inputarguments(
            'ERROR - arguments must be two 2x2 arrays (real)')

    z = np.zeros((2, 2), 'complex')
    for i in range(2):
        for j in range(2):
            abs_z = np.sqrt(5 * freq * rho[i, j])
            z[i, j] = cmath.rect(abs_z, math.radians(phi[i, j]))

    return z
Пример #4
0
def rotatevector_incl_errors(invector, angle, invector_err=None):
    #check for row or column vector

    if invector is None:
        raise MTex.MTpyError_inputarguments(
            'Vector AND error-vector must be defined')

    if (invector_err is not None) and (invector.shape != invector_err.shape):
        raise MTex.MTpyError_inputarguments(
            'Vector and errror-vector shapes do not match: %s - %s' %
            (str(invector.shape), str(invector_err.shape)))

    try:
        degreeangle = angle % 360
    except:
        raise MTex.MTpyError_inputarguments(
            '"Angle" must be a valid number (in degrees)')

    phi = math.radians(degreeangle)

    cphi = np.cos(phi)
    sphi = np.sin(phi)

    # JP: Changed the rotation matrix to be formulated to rotate
    # counter clockwise, I cannot find a good reason for this except that
    # when you plot the strike and phase tensors the look correct with this
    # formulation.
    rotmat = np.array([[cphi, sphi], [-sphi, cphi]])
    # rotmat = np.array([[ cphi, -sphi],[sphi, cphi]])

    if invector.shape == (1, 2):
        rotated_vector = np.dot(invector, np.linalg.inv(rotmat))
    else:
        rotated_vector = np.dot(rotmat, invector)

    errvec = None
    if (invector_err is not None):
        errvec = np.zeros_like(invector_err)

        if invector_err.shape == (1, 2):
            errvec = np.dot(invector_err, np.abs(np.linalg.inv(rotmat)))
        else:
            errvec = np.dot(np.abs(rotmat), invector_err)

    return rotated_vector, errvec
Пример #5
0
def invertmatrix_incl_errors(inmatrix, inmatrix_err=None):

    if inmatrix is None:
        raise MTex.MTpyError_inputarguments('Matrix must be defined')

    if (inmatrix_err is not None) and (inmatrix.shape != inmatrix_err.shape):
        raise MTex.MTpyError_inputarguments(
            'Matrix and err-matrix shapes do not match: %s - %s' %
            (str(inmatrix.shape), str(inmatrix_err.shape)))

    if (inmatrix.shape[-2] != inmatrix.shape[-1]):
        raise MTex.MTpyError_inputarguments('Matrices must be square!')

    if (inmatrix_err is not None) and (inmatrix_err.shape[-2] !=
                                       inmatrix_err.shape[-1]):
        raise MTex.MTpyError_inputarguments('Matrices must be square!')

    dim = inmatrix.shape[-1]

    det = np.linalg.det(inmatrix)

    if det == 0:
        raise MTex.MTpyError_inputarguments(
            'Matrix is singular - I cannot invert that!')

    inv_matrix = np.zeros_like(inmatrix)

    if dim != 2:
        raise MTex.MTpyError_inputarguments('Only 2D matrices supported yet')

    inv_matrix = np.linalg.inv(inmatrix)

    inv_matrix_err = None

    if (inmatrix_err is not None):
        inmatrix_err = np.real(inmatrix_err)
        inv_matrix_err = np.zeros_like(inmatrix_err)

        for i in range(2):
            for j in range(2):
                #looping over the entries of the error matrix
                err = 0.
                for k in range(2):
                    for l in range(2):
                        #each entry has 4 summands

                        err += np.abs(-inv_matrix[i, k] * inv_matrix[l, j] *
                                      inmatrix_err[k, l])

                inv_matrix_err[i, j] = err

    return inv_matrix, inv_matrix_err
Пример #6
0
def reorient_data2D(x_values, y_values, x_sensor_angle=0, y_sensor_angle=90):
    """
        Re-orient time series data of a sensor pair, which has not been in default (x=0, y=90) orientation.

        Input:
        - x-values - Numpy array
        - y-values - Numpy array
        Note: same length for both! - If not, the shorter length is taken 

        Optional:
        - Angle of the x-sensor - measured in degrees, clockwise from North (0) 
        - Angle of the y-sensor - measured in degrees, clockwise from North (0) 

        Output:
        - corrected x-values (North)
        - corrected y-values (East)
    """

    x_values = np.array(x_values)
    y_values = np.array(y_values)

    try:
        if x_values.dtype not in ['complex', 'float', 'int']:
            raise
        if len(x_values) != len(y_values):
            raise
    except:
        raise MTex.MTpyError_inputarguments(
            'ERROR - both input arrays must be of same length')

    if len(x_values) != len(y_values):
        l = min(len(x_values), len(y_values))
        x_values = x_values[:l]
        y_values = y_values[:l]

    in_array = np.zeros((len(x_values), 2), x_values.dtype)

    in_array[:, 0] = x_values
    in_array[:, 1] = y_values

    try:
        x_angle = math.radians(x_sensor_angle)
        y_angle = math.radians(y_sensor_angle)
    except:
        raise MTex.MTpyError_inputarguments(
            'ERROR - both angles must be of type int or float')

    T = np.matrix(
        [[np.real(cmath.rect(1, x_angle)),
          np.imag(cmath.rect(1, x_angle))],
         [np.real(cmath.rect(1, y_angle)),
          np.imag(cmath.rect(1, y_angle))]])

    try:
        new_array = np.dot(in_array, T.I)
    except:
        raise MTex.MTpyError_inputarguments(
            'ERROR - angles must define independent axes to span 2D')

    #print new_array.shape

    return new_array[:, 0], new_array[:, 1]