'''
Function:     get_submatrix_invs_dets_mp

Arguments:    conn - The child connection through which to send the output of the function.
              mat - A four-dimensional, size (N,M,P,P) array.
              inds - A list of unique (integer) indices lying in the interval in [0,P).
           
Output:       mat_out - A four-dimensional, size (N,M,L,L) array, where L = len(inds). The matrix mat_out[i,j,:,:] is
                        the inverse of the submatrix of mat[i,j,:,:] acquired by extracting the rows and columns
                        corresponding to the indices inds. For example, inds = [0,1] would yield the inverses of the
                        upper left 2x2 submatrices.
              mat_dets - A two-dimensional, size (N,M) array, where the entry mat_dets[i,j] contains the determinant of
                         the submatrix of mat[i,j,:,:] acquired by extracting the rows and columns corresponding to the 
                         indices inds. For example, inds = [0,1] would yield the determinants of the upper left 2x2
                         submatrices.
           
Description:  Computes submatrix inverses and determinants. Meant to be called within a new Process generated by the
              Python multiprocessing module, to ensure that the matrix copies created when extracting the submatrix are
              garbage collected.

Authors:     James Trousdale - jamest212@gmail.com
'''

import numpy as np

def get_submatrix_invs_dets_mp(conn,mat,inds):
    mat_out = np.zeros((np.size(mat,0),np.size(mat,1),len(inds),len(inds)))
    mat_dets = np.zeros((np.size(mat,0),np.size(mat,1)))
    
    for i in xrange(np.size(mat,0)):
        for j in xrange(np.size(mat,1)):
            temp = np.squeeze(mat[i,j,:,:])[np.ix_(inds,inds)]
            mat_out[i,j,:,:] = np.linalg.inv(temp)
            mat_dets[i,j] = np.linalg.det(temp)
            
    conn.send((mat_out,mat_dets))
    conn.close()