Ejemplo n.º 1
0
def gen_hkl(bound, mt_tensor):

    m = 1.0 * bound

    h = math.ceil(math.sqrt(m / mt_tensor[0][0]))
    k = math.ceil(math.sqrt(m / mt_tensor[1][1]))
    l = math.ceil(math.sqrt(m / mt_tensor[2][2]))

    print h, k, l, "\n"

    x_csl = np.arange(-h, h + 1, 1.0)
    y_csl = np.arange(-k, k + 1, 1.0)
    z_csl = np.arange(-l, l + 1, 1.0)

    num_mi = np.size(x_csl) * np.size(y_csl) * np.size(z_csl)
    xx_csl, yy_csl, zz_csl = np.meshgrid(x_csl, y_csl, z_csl, indexing="xy")
    xx_csl, yy_csl, zz_csl = xx_csl.reshape(1, num_mi)[0], yy_csl.reshape(1, num_mi)[0], zz_csl.reshape(1, num_mi)[0]
    mil_ind = np.column_stack([xx_csl, yy_csl, zz_csl])

    ind = np.where((mil_ind[:, 0] == 0) & (mil_ind[:, 1] == 0) & (mil_ind[:, 2] == 0))[0][0]
    ### deleting (0 0 0)
    mil_ind = np.delete(mil_ind, ind, 0)
    ### finding the unique miller indices
    mil_ind = GBim.int_finder(mil_ind, tol=1e-06, order="rows")
    mil_ind_csl = GBt.unique_rows_tol(mil_ind, tol=1e-06)

    ### Antipodal symmetry (h k l) ~ (-h -k -l)
    return mil_ind_csl
Ejemplo n.º 2
0
def csl_area_sort(bpn, l_rcsl_go, mt_cslr_go, return_hkl=False):

    mil_sphr = np.dot(np.linalg.inv(l_rcsl_go), bpn.transpose()).transpose()
    mil_sphr = GBim.int_finder(mil_sphr, tol=1e-06, order="rows")
    # mil_sphr = GBt.unique_rows_tol(mil_sphr, tol=1e-06)
    d_inv_sqr = np.diag(np.dot(np.dot(mil_sphr, mt_cslr_go), mil_sphr.transpose()))
    d_inv = np.sqrt(d_inv_sqr)
    ind_d_inv_sort = np.argsort(d_inv)
    # bpn = GBt.unique_rows_tol(bpn[ind_d_inv_sort], tol=1e-04)
    bpn_sort = bpn[ind_d_inv_sort]
    mil_sort = mil_sphr[ind_d_inv_sort]
    if return_hkl == True:
        return bpn_sort, mil_sort
    else:
        return bpn_sort
Ejemplo n.º 3
0
def test_int_finder():
    """
    Test cases for the int_finder function in integer_manipulations
    """
    Mat = np.zeros(3, dtype=[('Matrix', '(3,3)float64'),
                             ('row', '(1,3)float64'), ('col', '(3,1)float64')])
    Mat['Matrix'][0] = np.array(([1.5, 2, 3.0e-7],
                                 [-4, 5, 6], [7, 2.0e-5, 1.0e-5]))
    Mat['Matrix'][1] = np.array(([1.5, 2, 3e-6],
                                 [-4, 0, 6], [3.5, -2e-6, 1e-6]))
    Mat['Matrix'][2] = np.array(([1.5, 2, 3e-7],
                                 [-4, 5, 6], [3.5, -2e-6, 1e-6]))
    Mat['row'][0] = np.array(([1.5e-7, 0, 3e-6]))
    Mat['row'][1] = np.array(([1.5e-7, 1, 3e-6]))
    Mat['row'][2] = np.array(([1.5, 4, 3e-7]))
    Mat['col'][0] = np.array(([1.5e-7], [0], [3e-6]))
    Mat['col'][1] = np.array(([1.5e-7], [1], [3e-6]))
    Mat['col'][2] = np.array(([1.5], [4], [3e-7]))
    order = np.zeros(2, 'a4')
    order = ['rows', 'col']
    
    cnt = 0
    for j in Mat.dtype.names:
        for i in range(Mat.shape[0]):
            for k in range(len(order)):
                cnt += 1
                print('case:', cnt, '\n')
                print(Mat[j][i], '\n\n', 'order:', order[k], '\nanswer:\n')

                # a = int_man.int_finder(Mat[j][i], tolerance, order[k])
                a = int_man.int_finder(Mat[j][i])
                print(a, '\n', '--')
                a = int_man.int_finder(Mat[j][i], 1.0e-5, 'rows', 1.0e-5) # supposed to fail for cnt == 7?
                print(a, '\n', '--')
                a = int_man.int_finder(Mat[j][i], 1e-5, 'rows')
                print(a, '\n', '--')
                a = int_man.int_finder(Mat[j][i], 1e-5, 'col')
                print(a, '\n', '--')
                a = int_man.int_finder(Mat[j][i], 1e-5, 'columns')
                print(a, '\n', '--')
                a = int_man.int_finder(Mat[j][i], 1e-5, order[k], 1e-5)
                print(a, '\n', '--')

                print('\n', '-----------------------------------------')

    print(cnt, ' test cases have been tried.')
    if __name__ == '__main__':
        test_int_finder
Ejemplo n.º 4
0
def gen_miller_ind(mesh_size):
    """
    Returns an array of unique miller indices

    Parameters
    ----------
    mesh_size: size of the mesh grid to create the indices array
    * positive integer

    Returns
    -------
    mil_ind: array of unique miller indices stored row wise
    * numpy array of size (m x 3)
    * m is the number of unique indices created for a given mesh_size

    See Also
    --------
    * GBpy.integer_manipulations.int_finder
    * GBpy.tools.unique_rows_tol
    """

    ### Creating an array of boundary plane miller indices
    r = mesh_size
    x_csl = np.arange(-r, r+1, 1.0)
    y_csl = np.arange(-r, r+1, 1.0)
    z_csl = np.arange(-r, r+1, 1.0)
    num_mi = np.size(x_csl)*np.size(y_csl)*np.size(z_csl)
    xx_csl, yy_csl, zz_csl = np.meshgrid(x_csl, y_csl, z_csl, indexing='xy')
    xx_csl, yy_csl, zz_csl = xx_csl.reshape(1, num_mi)[0], yy_csl.reshape(1, num_mi)[0], zz_csl.reshape(1, num_mi)[0]
    mil_ind = np.column_stack([xx_csl, yy_csl, zz_csl])
    ind = np.where((mil_ind[:, 0] == 0) & (mil_ind[:, 1] == 0) & (mil_ind[:, 2] == 0))[0][0]
    ### deleting (0 0 0)
    mil_ind = np.delete(mil_ind, ind, 0)
    ### finding the unique miller indices
    mil_ind = GBim.int_finder(mil_ind, tol=1e-06, order='rows')
    mil_ind = GBt.unique_rows_tol(mil_ind)
    # Try to remove (-h -k -l) for all (h k l) !!!
    return mil_ind
Ejemplo n.º 5
0
def pick_ctr(bp, l_rcsl_go, mt_cslr_go, grid_ctr, tol=1e-06):
    bpn = np.copy(bp)
    if len(bpn) == 1:
        return bpn, np.array([])
    bpn_sphr = mf.cube2sphr_2d(bpn)
    mil_sphr = np.dot(np.linalg.inv(l_rcsl_go), bpn_sphr.transpose()).transpose()
    mil_sphr = GBim.int_finder(mil_sphr, tol=1e-06, order="rows")
    d_inv_sqr = np.diag(np.dot(np.dot(mil_sphr, mt_cslr_go), mil_sphr.transpose()))

    d_inv_sqr_min = np.min(d_inv_sqr)
    cond = np.abs(d_inv_sqr - d_inv_sqr_min) <= tol
    # ind1 = np.where(cond)
    bpn_min = bpn[cond]
    num_bpn_min = len(bpn_min)
    d_ctr = np.zeros(num_bpn_min)
    for ct1 in range(num_bpn_min):
        pt = bpn_min[ct1]
        d_ctr[ct1] = np.sqrt((grid_ctr[0] - pt[0]) ** 2 + (grid_ctr[1] - pt[1]) ** 2)
    ind = np.argsort(d_ctr)
    bpn_pick = bpn_min[ind][0]

    ind_r = np.where((bpn[:, 0] == bpn_pick[0]) & (bpn[:, 1] == bpn_pick[1]) & (bpn[:, 2] == bpn_pick[2]))[0]

    return bpn_pick, ind_r
Ejemplo n.º 6
0
def dsc_finder(L_G2_G1, L_G1_GO1):
    """
    The DSC lattice is computed for the bi-crystal, if the transformation
    matrix l_g2_g1 is given and the basis vectors of the underlying crystal
    l_g_go (in the orthogonal reference go frame) are known. The following
    relationship is used: **The reciprocal of the coincidence site lattice of
    the reciprocal lattices is the DSC lattice**

    Parameters
    ----------------
    l_g2_g1: numpy array
    transformation matrix (r_g1tog2_g1)

    l_g1_go1: numpy array
    basis vectors (as columns) of the underlying lattice expressed in the
    orthogonal 'go' reference frame

    Returns
    ------------
    l_dsc_g1: numpy array
    The dsc lattice basis vectors (as columns) expressed in the g1 reference

    Notes
    ---------
    The "Reduced" refer to the use of LLL algorithm to compute a
    basis that is as close to orthogonal as possible.
    (Refer to http://en.wikipedia.org/wiki/Lattice_reduction) for further
    detials on the concept of Lattice Reduction
    """

    L_G2_G1 = np.array(L_G2_G1)
    L_G1_GO1 = np.array(L_G1_GO1)

    L_GO1_G1 = np.linalg.inv(L_G1_GO1)
    # % % Reciprocal lattice of G1
    # --------------------------------------------------------------
    L_rG1_GO1 = reciprocal_mat(L_G1_GO1)
    L_GO1_rG1 = np.linalg.inv(L_rG1_GO1)
    # L_rG1_G1 = np.dot(L_GO1_G1, L_rG1_GO1)
    # % % L_G1_rG1 = L_rG1_G1^(-1);
    # % % Reciprocal lattice of G2
    L_G2_GO1 = np.dot(L_G1_GO1, L_G2_G1)
    L_rG2_GO1 = reciprocal_mat(L_G2_GO1)

    # % % Transformation of the Reciprocal lattices
    # % % R_rG1TorG2_rG1 = L_rG2_G1*L_G1_rG1;
    L_rG2_rG1 = np.dot(L_GO1_rG1, L_rG2_GO1)
    Sigma_star = sigma_calc(L_rG2_rG1)

    # % % CSL of the reciprocal lattices
    L_rCSL_rG1 = csl_finder_smith(L_rG2_rG1)
    L_rCSL_GO1 = np.dot(L_rG1_GO1, L_rCSL_rG1)
    # % % Reciprocal of the CSL of the reciprocal lattices
    L_DSC_GO1 = reciprocal_mat(L_rCSL_GO1)
    L_DSC_G1 = np.dot(L_GO1_G1, L_DSC_GO1)

    # % % Reduction of the DSC lattice in G1 reference frame
    DSC_Int = int_man.int_finder(L_DSC_G1, 1e-06)
    t_ind = np.where(abs(DSC_Int) == abs(DSC_Int).max())
    t_ind_1 = t_ind[0][0]
    t_ind_2 = t_ind[1][0]
    Mult1 = DSC_Int[t_ind_1, t_ind_2] / L_DSC_G1[t_ind_1, t_ind_2]
    DSC_Reduced = lll_reduction(DSC_Int)
    DSC_Reduced = DSC_Reduced / Mult1
    L_DSC_G1 = DSC_Reduced

    # % % % Check this assertion: L_DSC_G1 = [Int_Matrix]/Sigma
    if int_man.int_check(Sigma_star*L_DSC_G1, 10).all():
        L_DSC_G1 = np.around(Sigma_star*L_DSC_G1) / Sigma_star
    else:
        raise Exception('L_DSC_G1 is not equal to [Int_Matrix]/Sigma')
    return L_DSC_G1
Ejemplo n.º 7
0
def bicryst_planar_den(inds, t_mat, l_g_go, inds_type='miller_index',
                       mat_ref='g1'):
    """
    The function computes the planar densities of the planes
    1 and 2 and the two-dimensional CSL

    Parameters
    ---------------
    inds: numpy array
    The boundary plane indices

    inds_type: string
    {'miller_index', 'normal_go', 'normal_g'}

    t_mat: numpy array
    Transformation matrix from g1 to g2 in go1 reference frame

    mat_ref: string
    {'go1', 'g1'}

    lattice: Lattice class
    Attributes of the underlying lattice

    Returns
    -----------
    pl_den_pl1, pl_den_pl2: numpy array
    The planar density of planes 1 and 2

    pl_den_csl: numpy array
    The planare density of the two-dimensional CSL
    """
    import GBpy.lattice as lat
    if isinstance(l_g_go, lat.Lattice):
        l_g_go = np.array(l_g_go.l_g_go, dtype=np.float64)
    l_g1_go1 = l_g_go
    l_rg1_go1 = fcd.reciprocal_mat(l_g1_go1)
    l_go1_rg1 = np.linalg.inv(l_rg1_go1)

    if inds_type == 'normal_go':
        bp1_go1 = inds
        miller1_inds = int_man.int_finder(np.dot(l_go1_rg1, bp1_go1))
    elif inds_type == 'miller_index':
        miller1_inds = inds
    elif inds_type == 'normal_g':
        bp1_g1 = inds
        l_g1_rg1 = np.dot(l_go1_rg1, l_g1_go1)
        miller1_inds = int_man.int_finder(np.dot(l_g1_rg1, bp1_g1))
    else:
        raise Exception('Wrong index type')

    if mat_ref == 'go1':
        l_2d_csl_g1, l_pl1_g1, l_pl2_g1 = gb_2d_csl(miller1_inds,
                                                    t_mat, l_g_go,
                                                    'miller_index', 'go1')
    elif mat_ref == 'g1':
        l_2d_csl_g1, l_pl1_g1, l_pl2_g1 = gb_2d_csl(miller1_inds,
                                                    t_mat, l_g_go,
                                                    'miller_index', 'g1')
    else:
        raise Exception('Wrong reference axis type')

    check_2d_csl(l_pl1_g1, l_pl2_g1, l_2d_csl_g1)

    pl_den_pl1 = pl_density(l_pl1_g1, l_g1_go1)
    pl_den_pl2 = pl_density(l_pl2_g1, l_g1_go1)
    pl_den_csl = pl_density(l_2d_csl_g1, l_g1_go1)

    return pl_den_pl1, pl_den_pl2, pl_den_csl
Ejemplo n.º 8
0
def gb_2d_csl(inds, t_mat, l_g_go,
              inds_type='miller_index', mat_ref='g1'):
    """
    For a given boundary plane normal 'bp1_g1' and the misorientation
    matrix 't_g1tog2_g1', the two-dimensional CSL lattice is computed

    Parameters
    ------------------
    inds: numpy array
    The boundary plane indices

    inds_type: string
    {'miller_index', 'normal_go', 'normal_g'}

    t_mat: numpy array
    Transformation matrix from g1 to g2 in 'mat_ref' reference frame

    mat_ref: string
    {'go1', 'g1'}

    lattice: Lattice class
    Attributes of the underlying lattice

    Returns
    -----------
    l_2d_csl_g1, l_pl1_g1, l_pl2_g1: numpy arrays
    l_2d_csl_g1 is the 2d CSL in g1 ref frame
    l_pl1_g1 is the plane 1 basis in g1 ref frame
    l_pl2_g1 is the plane 2 basis in g1 ref frame
    """
    import GBpy.lattice as lat
    if isinstance(l_g_go, lat.Lattice):
        l_g_go = np.array(l_g_go.l_g_go, dtype=np.float64)
    
    l_g1_go1 = l_g_go
    
    l_go1_g1 = np.linalg.inv(l_g1_go1)
    l_rg1_go1 = fcd.reciprocal_mat(l_g1_go1)
    l_go1_rg1 = np.linalg.inv(l_rg1_go1)

    if inds_type == 'normal_go':
        bp1_go1 = inds
        miller1_ind = int_man.int_finder(np.dot(l_go1_rg1, bp1_go1))
    elif inds_type == 'miller_index':
        miller1_ind = inds
    elif inds_type == 'normal_g':
        bp1_g1 = inds
        l_g1_rg1 = np.dot(l_go1_rg1, l_g1_go1)
        miller1_ind = int_man.int_finder(np.dot(l_g1_rg1, bp1_g1))
    else:
        raise Exception('Wrong index type')

    if mat_ref == 'go1':
        t_g1tog2_g1 = np.dot(l_go1_g1, np.dot(t_mat, l_g1_go1))
    elif mat_ref == 'g1':
        t_g1tog2_g1 = t_mat
    else:
        raise Exception('Wrong reference axis type')

    bp1_go1 = int_man.int_finder(np.dot(l_rg1_go1, miller1_ind))
    l_g2_g1 = t_g1tog2_g1
    l_g2_go1 = np.dot(l_g1_go1, l_g2_g1)
    l_rg2_go1 = fcd.reciprocal_mat(l_g2_go1)
    l_go1_rg2 = np.linalg.inv(l_rg2_go1)
    # bp2_g2 = int_man.int_finder(np.dot(-l_go1_g2, bp1_go1))
    miller2_ind = int_man.int_finder(np.dot(-l_go1_rg2, bp1_go1))
    
    l_pl1_g1 = bp_basis(miller1_ind)
    l_pl2_g2 = bp_basis(miller2_ind)

    l_pl2_g1 = np.dot(l_g2_g1, l_pl2_g2)

    l_2d_csl_g1 = csl_finder_2d(l_pl1_g1, l_pl2_g1)

    return l_2d_csl_g1, l_pl1_g1, l_pl2_g1
Ejemplo n.º 9
0
def bp_basis(miller_ind):
    """
    The function computes the primitve basis of the plane if the
    boundary plane indices are specified

    Parameters
    ---------------
    miller_ind: numpy array
    Miller indices of the plane (h k l)

    Returns
    -----------
    l_pl_g1: numpy array
    The primitive basis of the plane in 'g1' reference frame
    """
    miller_ind = int_man.int_finder(miller_ind)
    miller_ind = int_man.convert_array(miller_ind, dtype=np.int64, check=True)
    h = miller_ind[0]
    k = miller_ind[1]
    l = miller_ind[2]
    
    if h == 0 and k == 0 and l == 0:
        raise Exception('hkl indices cannot all be zero')
    else:
        if h != 0 and k != 0 and l != 0:
            gc_f1_p = gcd(k, l)
            bv1_g1 = np.array([[0], [-l / gc_f1_p], [k / gc_f1_p]])
            bv2_g1 = compute_basis_vec([h, k, l])
        else:
                if h == 0:
                    if k == 0:
                        bv1_g1 = np.array([[1], [0], [0]])
                        bv2_g1 = np.array([[0], [1], [0]])
                    elif l == 0:
                        bv1_g1 = np.array([[0], [0], [1]])
                        bv2_g1 = np.array([[1], [0], [0]])
                    else:
                        gc_f1_p = gcd(k, l)
                        bv1_g1 = np.array([[0], [-l / gc_f1_p],
                                           [k / gc_f1_p]])
                        bv2_g1 = np.array([[1], [-l / gc_f1_p],
                                           [k / gc_f1_p]])
                else:
                    if k == 0:
                        if l == 0:
                            bv1_g1 = np.array([[0], [1], [0]])
                            bv2_g1 = np.array([[0], [0], [1]])
                        else:
                            gc_f1_p = gcd(h, l)
                            bv1_g1 = np.array([[-l / gc_f1_p], [0],
                                               [h / gc_f1_p]])
                            bv2_g1 = np.array([[-l / gc_f1_p], [1],
                                               [h / gc_f1_p]])
                    else:
                        if l == 0:
                            gc_f1_p = gcd(h, k)
                            bv1_g1 = np.array([[-k / gc_f1_p],
                                               [h / gc_f1_p], [0]])
                            bv2_g1 = np.array([[-k / gc_f1_p],
                                               [h / gc_f1_p], [1]])

    #  The reduced basis vectors for the plane
    if bv1_g1.dtype == object:
        bv1_g1 = bv1_g1.ravel().astype(np.float64) # should these be integers?
    if bv2_g1.dtype == object:
        bv2_g1 = bv2_g1.ravel().astype(np.float64) # should these be integers?
    
    l_pl_g1 = lll_reduction(np.column_stack([bv1_g1, bv2_g1]))
    return l_pl_g1
Ejemplo n.º 10
0
def plots(mesh_size, sigma_val, n, lat_type):
    ### Creating an instance of lattice class
    elem = GBl.Lattice(lat_type)
    ### Getting the primitive lattice in orthogonal frame
    l_g_go = elem.l_g_go


    ### Creating a meshgrid of boundary plane miller indices in CSL lattice
    r = mesh_size
    x_csl = np.arange(-r, r+1, 1.0)
    y_csl = np.arange(-r, r+1, 1.0)
    z_csl = np.arange(-r, r+1, 1.0)
    num_mi = np.size(x_csl)*np.size(y_csl)*np.size(z_csl)
    xx_csl, yy_csl, zz_csl = np.meshgrid(x_csl, y_csl, z_csl, indexing='xy')
    xx_csl, yy_csl, zz_csl = xx_csl.reshape(1, num_mi)[0], yy_csl.reshape(1, num_mi)[0], zz_csl.reshape(1, num_mi)[0]
    mil_ind_csl = np.column_stack([xx_csl, yy_csl, zz_csl])
    ind = np.where((mil_ind_csl[:, 0] == 0) & (mil_ind_csl[:, 1] == 0) & (mil_ind_csl[:, 2] == 0))[0][0]
    mil_ind_csl = np.delete(mil_ind_csl, ind, 0)
    mil_ind_csl = GBim.int_finder(mil_ind_csl, tol=1e-06, order='rows')
    mil_ind_csl = GBt.unique_rows_tol(mil_ind_csl)
    ### Try to remove (-h -k -l) for all (h k l) !!!
    gb_dir = os.path.dirname(inspect.getfile(GBpy))
    pkl_path =  gb_dir + '/pkl_files/cF_Id_csl_common_rotations.pkl'
    pkl_content = pickle.load(open(pkl_path))
    sig_mis_N = pkl_content[str(sigma_val)]['N'][0]
    sig_mis_D = pkl_content[str(sigma_val)]['D'][0]
    ### Extracting the sigma misorientation from the pickle file
    ### Misorientation is in the primitive frame of associated lattice
    sig_mis_g = sig_mis_N/sig_mis_D
    ### Converting the misorientation to orthogonal frame/superlattice of the crystal
    ### Done using similarity transformation
    sig_mis_go = np.dot(np.dot(l_g_go, sig_mis_g), np.linalg.inv(l_g_go)).reshape(1,3,3)[0]
    ### Getting the csl basis in primitive frame
    l_csl_g, l_dsc_g = GBfcd.find_csl_dsc(l_g_go, sig_mis_g)
    ### Converting the csl basis to orthogonal frame
    l_csl_go = np.dot(l_g_go, l_csl_g)
    ### reciprocal csl basis in po frame
    l_rcsl_go = GBfcd.reciprocal_mat(l_csl_go)
    ### Converting the miller indices to normals in po frame
    bpn_go = np.dot(l_rcsl_go, mil_ind_csl.transpose()).transpose()
    ### Finding the boundary plane normals in the fz using five_param_fz
    bp_fz_norms_go1, bp_symm_grp, symm_grp_ax = five_param_fz(sig_mis_go, bpn_go)
    ### Finding unique normals
    bp_fz_norms_go1_unq, bfz_unq_ind = GBt.unique_rows_tol(bp_fz_norms_go1, return_index=True)
    ### Finding the input hkl indices corresponding to unique FZ normals
    mil_ind_csl_unq = mil_ind_csl[bfz_unq_ind]
    ############ Calculating interplanar distance (d sigma hkl) for unique FZ bpn #########
    l_rcsl_go = GBfcd.reciprocal_mat(l_csl_go)
    mt_cslr_go = np.dot(l_rcsl_go.transpose(), l_rcsl_go)
    d_inv_sqr = np.diag(np.dot(np.dot(mil_ind_csl_unq, mt_cslr_go),mil_ind_csl_unq.transpose()))
    d_inv = np.sqrt(d_inv_sqr)
    d_sig_hkl = np.true_divide(1, d_inv)

    ############ Calculating unit cell area for 2-D csl unit cells for unique FZ bpn ########

    # mil_ind_p = np.dot(np.linalg.inv(GBfcd.reciprocal_mat(l_g_go)), bpn_go.transpose()).transpose()
    # mil_ind_p = int_man.int_finder(mil_ind_p, 1e-06, 'rows')
    pl_den = []
    num_bpn_unq = np.shape(bp_fz_norms_go1_unq)[0]
    for ct1 in range(num_bpn_unq):
        _, _, pl_den_csl = GBb2.bicryst_planar_den(bp_fz_norms_go1_unq[ct1, :], sig_mis_g, l_g_go, 'normal_go', 'g1')
        pl_den.append(pl_den_csl)
    pl_den = np.array(pl_den)
    a_sig_hkl = np.true_divide(1, pl_den)

    ### Checking the csl primitive unit cell volume equality
    v_sig_hkl = np.multiply(d_sig_hkl, a_sig_hkl)
    # print v_sig_hkl
    v_basis = abs(np.linalg.det(l_csl_go))
    if np.all(abs(v_sig_hkl-v_basis) < 1e-04):
        print "The two volumes match!"
    else:
        print " Mismatch!"

    ### Sorting in increasing order of 2d csl primitive unit cell area
    ind_area_sort = np.argsort(a_sig_hkl)
    a_sig_hkl_sort = np.sort(a_sig_hkl)
    d_sig_hkl_sort = d_sig_hkl[ind_area_sort]
    bp_fz_norms_go1_unq_sort = bp_fz_norms_go1_unq[ind_area_sort]

    ### Check to ensure required number of unique bpn are returned
    if np.shape(bp_fz_norms_go1_unq_sort)[0] < n:
        print "Please input a larger mesh grid or reduce the number of boundaries!"
        n = np.shape(bp_fz_norms_go1_unq_sort)[0]

    ### Selecting the lowest 'n' area boundaries and their attributes for plotting
    a_plot = a_sig_hkl_sort[:n]
    pd_plot = np.true_divide(1, a_plot)
    d_plot = d_sig_hkl_sort[:n]
    bp_fz_plot = bp_fz_norms_go1_unq_sort[:n]

    ### d vs pd plot
    fig1 = plt.figure(figsize=(12, 12), facecolor='w')
    plt.margins(0.05)
    plt.xlabel('Interplanar spacing')
    plt.ylabel('Planar density of 2D-CSL')
    plt.plot(d_plot, pd_plot, 'ro')
    # plt.show()
    plt.savefig('d_vs_pd_' + str(r) + '_' + str(n)+ '.png', dpi=100, bbox_inches='tight')

    ### FZ plot for the sorted and selected boundaries
    na = '_'+ str(r) + '_'+ str(n)
    plot_fig(symm_grp_ax, bp_fz_plot, np.pi/6, na)
    # plt.show()
    return