def get_wavefunctions(self, kx_array, verbose=False):
        """This method solves the matrix in coeff_matrix to give the four coefficients A, B, C and D
        It returns a list of functions representing the eigenfunctions of this waveguide
        """
        n = self.waveguide.cladding_index(self.wavelength)
        k = self.waveguide.wavevector_length_core(self.wavelength)
        d = self.waveguide.slab_gap
        gamma = lambda kx: np.sqrt(k**2 - kx**2 - n**2 * k**2
                                   )  #not n.real this time

        wavefunctions = []
        for kx in kx_array:
            mat = self.coeff_matrix(kx)
            null_space = util.null_vector(mat)
            A = null_space[0]
            B = null_space[1]
            C = null_space[2]
            D = null_space[3]

            m = self.coeff_matrix(kx)
            ns = util.null_vector(m)
            #B = ns[0]
            #C = ns[1]
            #A = B
            #D = (kx*np.sin(kx*d)*B+kx*np.cos(kx*d)*C)/gamma(kx)

            kz = np.sqrt(k**2 - kx**2)

            def get_wavef_x(A, B, C, D, kx):
                def wavef_x(x):
                    if x > 0:
                        return A * np.exp(-gamma(kx) * x)
                    elif x < 0 and -d < x:
                        return B * np.cos(kx * x) + C * np.sin(kx * x)
                    else:
                        return D * np.exp(gamma(kx) * (x + d))

                return wavef_x

            #Normalise the area under the wavef
            wavef_x = get_wavef_x(A, B, C, D, kx)
            intensity = lambda x: np.abs(wavef_x(x))**2
            if verbose:
                print 'Integrating wavefunction kx = %s...' % kx
            ires = integrate.quad(intensity,
                                  -self.waveguide.slab_gap * 10,
                                  self.waveguide.slab_gap * 10,
                                  epsabs=1e-10,
                                  epsrel=1e-10,
                                  limit=400)
            area = ires[0]

            def get_wavef(wfx, ar, kz):
                return lambda x, z: wfx(x) * np.exp(1j * kz * z) / np.sqrt(ar)

            wavefunctions.append(
                get_wavef(get_wavef_x(A, B, C, D, kx), area, kz))

        return wavefunctions
    def get_wavefunctions(self, kx_array, verbose=False):
        """This method solves the matrix in coeff_matrix to give the four coefficients A, B, C and D
        It returns a list of functions representing the eigenfunctions of this waveguide
        """
        n = self.waveguide.cladding_index(self.wavelength)
        k = self.waveguide.wavevector_length_core(self.wavelength)
        d = self.waveguide.slab_gap
        gamma = lambda kx: np.sqrt(k ** 2 - kx ** 2 - n ** 2 * k ** 2) #not n.real this time


        wavefunctions = []
        for kx in kx_array:
            mat = self.coeff_matrix(kx)
            null_space = util.null_vector(mat)
            A = null_space[0]
            B = null_space[1]
            C = null_space[2]
            D = null_space[3]

            m = self.coeff_matrix(kx)
            ns = util.null_vector(m)
            #B = ns[0]
            #C = ns[1]
            #A = B
            #D = (kx*np.sin(kx*d)*B+kx*np.cos(kx*d)*C)/gamma(kx)

            kz = np.sqrt(k**2 - kx**2)

            def get_wavef_x(A, B, C, D, kx):
                def wavef_x(x):
                    if x > 0:
                        return A*np.exp(-gamma(kx)*x)
                    elif x < 0 and -d < x:
                        return B*np.cos(kx*x)+C*np.sin(kx*x)
                    else:
                        return D*np.exp(gamma(kx)*(x+d))
                return wavef_x

            #Normalise the area under the wavef
            wavef_x = get_wavef_x(A, B, C, D, kx)
            intensity = lambda x: np.abs(wavef_x(x))**2
            if verbose:
                print 'Integrating wavefunction kx = %s...' % kx
            ires = integrate.quad(intensity, -self.waveguide.slab_gap*10, self.waveguide.slab_gap*10,
                epsabs=1e-10, epsrel=1e-10, limit=400)
            area = ires[0]

            def get_wavef(wfx, ar, kz):
                return lambda x,z: wfx(x) * np.exp(1j*kz*z) / np.sqrt(ar)

            wavefunctions.append(get_wavef(get_wavef_x(A, B, C, D, kx), area, kz))

        return wavefunctions
    def get_wavefunctions(self, kx_array, verbose=False):
        """This method solves the matrix in coeff_matrix to give the four coefficients A, B, C and D
        It returns a list of functions representing the eigenfunctions of this waveguide
        """
        n = self.waveguide.cladding_index(self.wavelength)
        k = self.waveguide.wavevector_length_core(self.wavelength)
        d = self.waveguide.slab_gap
        gamma = lambda kx: np.sqrt(k ** 2 - kx ** 2 - n ** 2 * k ** 2) #not n.real this time

        nmode = 0
        wavefunctions = []
        mats = dict()
        for kx in kx_array:
            nmode += 1
            mat = self.coeff_matrix(kx)
            mats['m'+str(nmode)] = mat
            nullv = util.null_vector(mat)
            A = nullv[0]
            B = nullv[1]
            C = nullv[2]
            D = nullv[3]

            if verbose:
                solnerrormat = np.matrix(self.coeff_matrix(kx))*np.matrix([[A],[B],[C],[D]])
                print 'n = %i Solution Error: %f' % (nmode, nplinalg.norm(solnerrormat))
                print 'Components: %s' % np.abs(solnerrormat)

            kz = np.sqrt(k**2 - kx**2)
            def wavef(x, z, A, B, C, D, kx, kz, g, mult):
                if x > d/2:
                    xpart = A*np.exp(-g*(x-d/2))
                elif x >= -d/2:
                    xpart = B*np.exp(1j*kx*x) + C*np.exp(-1j*kx*x)
                else:
                    xpart = D*np.exp(g*(x+d/2))
                return xpart*np.exp(1j*kz*z)*mult

            wavef_captured = functools.partial(wavef, A=A, B=B, C=C, D=D, kx=kx, kz=kz, g=gamma(kx), mult=1)
            wavef_x = functools.partial(wavef_captured, z=0)
            intensity = lambda x: np.abs(wavef_x(x))**2
            ires = integrate.quad(intensity, -self.waveguide.slab_gap * 10, self.waveguide.slab_gap * 10,
                epsabs=1e-10, epsrel=1e-10, limit=400)
            area = ires[0]
            wavef_norm = functools.partial(wavef, A=A, B=B, C=C, D=D, kx=kx, kz=kz, g=gamma(kx), mult=1/np.sqrt(area))
            wavefunctions.append(wavef_norm)
        return wavefunctions
    def get_wavefunctions(self, kx_array, verbose=False):
        """This method solves the matrix in coeff_matrix to give the four coefficients A, B, C and D
        It returns a list of functions representing the eigenfunctions of this waveguide
        """
        n = self.waveguide.cladding_index(self.wavelength)
        k = self.waveguide.wavevector_length_core(self.wavelength)
        d = self.waveguide.slab_gap
        gamma = lambda kx: np.sqrt(k**2 - kx**2 - n**2 * k**2
                                   )  #not n.real this time

        nmode = 0
        wavefunctions = []
        mats = dict()
        for kx in kx_array:
            nmode += 1
            mat = self.coeff_matrix(kx)
            mats['m' + str(nmode)] = mat
            nullv = util.null_vector(mat)
            A = nullv[0]
            B = nullv[1]
            C = nullv[2]
            D = nullv[3]

            if verbose:
                solnerrormat = np.matrix(self.coeff_matrix(kx)) * np.matrix(
                    [[A], [B], [C], [D]])
                print 'n = %i Solution Error: %f' % (
                    nmode, nplinalg.norm(solnerrormat))
                print 'Components: %s' % np.abs(solnerrormat)

            kz = np.sqrt(k**2 - kx**2)

            def wavef(x, z, A, B, C, D, kx, kz, g, mult):
                if x > d / 2:
                    xpart = A * np.exp(-g * (x - d / 2))
                elif x >= -d / 2:
                    xpart = B * np.exp(1j * kx * x) + C * np.exp(-1j * kx * x)
                else:
                    xpart = D * np.exp(g * (x + d / 2))
                return xpart * np.exp(1j * kz * z) * mult

            wavef_captured = functools.partial(wavef,
                                               A=A,
                                               B=B,
                                               C=C,
                                               D=D,
                                               kx=kx,
                                               kz=kz,
                                               g=gamma(kx),
                                               mult=1)
            wavef_x = functools.partial(wavef_captured, z=0)
            intensity = lambda x: np.abs(wavef_x(x))**2
            ires = integrate.quad(intensity,
                                  -self.waveguide.slab_gap * 10,
                                  self.waveguide.slab_gap * 10,
                                  epsabs=1e-10,
                                  epsrel=1e-10,
                                  limit=400)
            area = ires[0]
            wavef_norm = functools.partial(wavef,
                                           A=A,
                                           B=B,
                                           C=C,
                                           D=D,
                                           kx=kx,
                                           kz=kz,
                                           g=gamma(kx),
                                           mult=1 / np.sqrt(area))
            wavefunctions.append(wavef_norm)
        return wavefunctions