Example #1
0
 def __init__(self, sch_symbol, operations, tolerance=0.1):
     from pymatgen.symmetry.analyzer import generate_full_symmops
     self.sch_symbol = sch_symbol
     super(PointGroupOperations, self).__init__([
         op.rotation_matrix
         for op in generate_full_symmops(operations, tolerance)
     ])
Example #2
0
def get_symmetry(mol, already_oriented=False):
    '''
    Return a list of SymmOps for a molecule's point symmetry
    already_oriented: whether or not the principle axes of mol are already reoriented 
    '''
    pga = PointGroupAnalyzer(mol)
    #Handle linear molecules
    if '*' in pga.sch_symbol:
        if already_oriented == False:
            #Reorient the molecule
            oriented_mol, P = reoriented_molecule(mol)
            pga = PointGroupAnalyzer(oriented_mol)
        pg = pga.get_pointgroup()
        symm_m = []
        for op in pg:
            symm_m.append(op)
        #Add 12-fold  and reflections in place of ininitesimal rotation
        for axis in [[1, 0, 0], [0, 1, 0], [0, 0, 1]]:
            op = SymmOp.from_rotation_and_translation(aa2matrix(axis, pi / 6),
                                                      [0, 0, 0])
            if pga.is_valid_op(op):
                symm_m.append(op)
                #Any molecule with infinitesimal symmetry is linear;
                #Thus, it possess mirror symmetry for any axis perpendicular
                #To the rotational axis. pymatgen does not add this symmetry
                #for all linear molecules - for example, hydrogen
                if axis == [1, 0, 0]:
                    symm_m.append(SymmOp.from_xyz_string('x,-y,z'))
                    symm_m.append(SymmOp.from_xyz_string('x,y,-z'))
                elif axis == [0, 1, 0]:
                    symm_m.append(SymmOp.from_xyz_string('-x,y,z'))
                    symm_m.append(SymmOp.from_xyz_string('x,y,-z'))
                elif axis == [0, 0, 1]:
                    symm_m.append(SymmOp.from_xyz_string('-x,y,z'))
                    symm_m.append(SymmOp.from_xyz_string('x,-y,z'))
                #Generate a full list of SymmOps for the molecule's pointgroup
                symm_m = generate_full_symmops(symm_m, 1e-3)
                break
        #Reorient the SymmOps into mol's original frame
        if not already_oriented:
            new = []
            for op in symm_m:
                new.append(P.inverse * op * P)
            return new
        elif already_oriented:
            return symm_m
    #Handle nonlinear molecules
    else:
        pg = pga.get_pointgroup()
        symm_m = []
        for op in pg:
            symm_m.append(op)
        return symm_m
Example #3
0
def mol_get_rot_list0(mol, tol=1.e-5, log=sys.stdout):
    from pymatgen.symmetry.analyzer import PointGroupAnalyzer,\
            generate_full_symmops
    from scipy.linalg import det

    analyzer = PointGroupAnalyzer(mol)
    print(" sch_symbol = {}".format(analyzer.sch_symbol), file=log)

    # Pick rotations only.
    symmops = [
        o for o in analyzer.symmops if abs(det(o.rotation_matrix) - 1) < 1.e-5
    ]
    symmops = generate_full_symmops(symmops, tol, max_recursion_depth=50)
    rot_list = [o.rotation_matrix for o in symmops]
    return rot_list
Example #4
0
def get_symmetry(mol, already_oriented=False):
    """
    Return a molecule's point symmetry.
    Note: for linear molecules, infinitessimal rotations are treated as 6-fold
    rotations, which works for 3d and 2d point groups.

    Args:
        mol: a Molecule object
        already_oriented: whether or not the principle axes of mol are already
            reoriented. Can save time if True, but is not required.

    Returns:
        a list of SymmOp objects which leave the molecule unchanged when applied
    """
    # For single atoms, we cannot represent the point group using a list of operations
    if len(mol) == 1:
        return []
    pga = PointGroupAnalyzer(mol)
    # Handle linear molecules
    if "*" in pga.sch_symbol:
        if not already_oriented:
            # Reorient the molecule
            oriented_mol, P = reoriented_molecule(mol)
            pga = PointGroupAnalyzer(oriented_mol)
        pg = pga.get_pointgroup()
        symm_m = []
        for op in pg:
            symm_m.append(op)
        # Add 12-fold  and reflections in place of ininitesimal rotation
        for axis in [[1, 0, 0], [0, 1, 0], [0, 0, 1]]:
            # op = SymmOp.from_rotation_and_translation(aa2matrix(axis, np.pi/6), [0,0,0])
            m1 = Rotation.from_rotvec(np.pi / 6 * axis).as_matrix()
            op = SymmOp.from_rotation_and_translation(m1, [0, 0, 0])
            if pga.is_valid_op(op):
                symm_m.append(op)
                # Any molecule with infinitesimal symmetry is linear;
                # Thus, it possess mirror symmetry for any axis perpendicular
                # To the rotational axis. pymatgen does not add this symmetry
                # for all linear molecules - for example, hydrogen
                if axis == [1, 0, 0]:
                    symm_m.append(SymmOp.from_xyz_string("x,-y,z"))
                    symm_m.append(SymmOp.from_xyz_string("x,y,-z"))
                    #r = SymmOp.from_xyz_string("-x,y,-z")
                elif axis == [0, 1, 0]:
                    symm_m.append(SymmOp.from_xyz_string("-x,y,z"))
                    symm_m.append(SymmOp.from_xyz_string("x,y,-z"))
                    #r = SymmOp.from_xyz_string("-x,-y,z")
                elif axis == [0, 0, 1]:
                    symm_m.append(SymmOp.from_xyz_string("-x,y,z"))
                    symm_m.append(SymmOp.from_xyz_string("x,-y,z"))
                    #r = SymmOp.from_xyz_string("x,-y,-z")
                # Generate a full list of SymmOps for the molecule's pointgroup
                symm_m = generate_full_symmops(symm_m, 1e-3)
                break
        # Reorient the SymmOps into mol's original frame
        if not already_oriented:
            new = []
            for op in symm_m:
                new.append(P.inverse * op * P)
            return new
        elif already_oriented:
            return symm_m
    # Handle nonlinear molecules
    else:
        pg = pga.get_pointgroup()
        symm_m = []
        for op in pg:
            symm_m.append(op)
        return symm_m
Example #5
0
        Returns whether or not two operations are conjugate (the same
        operation in a different reference frame). Rotations with the same order
        will not always return True. For example, a 5/12 and 1/12 rotation will
        not be considered conjugate.

        Args:
            op1: a SymmOp or OperationAnalyzer object
            op2: a SymmOp or OperationAnalyzer object to compare with op1

        Returns:
            True if op2 is conjugate to op1, and False otherwise
        """
        if type(op1) != OperationAnalyzer:
            opa1 = OperationAnalyzer(op1)
        return opa1.is_conjugate(op2)


# Test Functionality
if __name__ == "__main__":
    # ----------------------------------------------------
    op = SymmOp.from_rotation_and_translation(
        Rotation.from_rotvec(np.pi / 6 * np.array([1, 0, 0])).as_matrix(),
        [0, 0, 0])
    ops = [op]
    from pymatgen.symmetry.analyzer import generate_full_symmops

    symm_m = generate_full_symmops(ops, 1e-3)
    for op in symm_m:
        opa = OperationAnalyzer(op)
        print(opa.order)
Example #6
0
def ss_string_from_ops(ops, sg, complete=True):
    '''
    Print the Hermann-Mauguin symbol for a site symmetry group, using a list of
    SymmOps as input. Note that the symbol does not necessarily refer to the
    x,y,z axes. For information on reading these symbols, see:
    http://en.wikipedia.org/wiki/Hermann-Mauguin_notation#Point_groups
    args:
        ops: a list of SymmOp objects representing the site symmetry
        sg: International number of the spacegroup. Used to determine which
            axes to show. For example, a 3-fold rotation in a cubic system is
            written as ".3.", whereas a 3-fold rotation in a trigonal system
            is written as "3.."
        complete: whether or not all symmetry operations in the group
            are present. If False, we generate the rest
    '''

    #Return the symbol for a single axis
    #Will be called later in the function
    def get_symbol(opas, order, has_reflection):
        #ops: a list of Symmetry operations about the axis
        #order: highest order of any symmetry operation about the axis
        #has_reflection: whether or not the axis has mirror symmetry
        if has_reflection is True:
            #rotations have priority
            for opa in opas:
                if opa.order == order and opa.type == "rotation":
                    return str(opa.rotation_order) + "/m"
            for opa in opas:
                if (opa.order == order and opa.type == "rotoinversion"
                        and opa.order != 2):
                    return "-" + str(opa.rotation_order)
            return "m"
        elif has_reflection is False:
            #rotoinversion has priority
            for opa in opas:
                if opa.order == order and opa.type == "rotoinversion":
                    return "-" + str(opa.rotation_order)
            for opa in opas:
                if opa.order == order and opa.type == "rotation":
                    return str(opa.rotation_order)
            return "."

    #Given a list of single-axis symbols, return the one with highest symmetry
    #Will be called later in the function
    def get_highest_symbol(symbols):
        symbol_list = [
            '.', '2', 'm', '-2', '2/m', '3', '4', '-4', '4/m', '-3', '6', '-6',
            '6/m'
        ]
        max_index = 0
        for symbol in symbols:
            i = symbol_list.index(symbol)
            if i > max_index:
                max_index = i
        return symbol_list[max_index]

    #Return whether or not two axes are symmetrically equivalent
    #It is assumed that both axes possess the same symbol
    #Will be called within combine_axes
    def are_symmetrically_equivalent(index1, index2):
        axis1 = axes[index1]
        axis2 = axes[index2]
        condition1 = False
        condition2 = False
        #Check for an operation mapping one axis onto the other
        for op in ops:
            if condition1 is False or condition2 is False:
                new1 = op.operate(axis1)
                new2 = op.operate(axis2)
                if np.isclose(abs(np.dot(new1, axis2)), 1):
                    condition1 = True
                if np.isclose(abs(np.dot(new2, axis1)), 1):
                    condition2 = True
        if condition1 is True and condition2 is True:
            return True
        else:
            return False

    #Given a list of axis indices, return the combined symbol
    #Axes may or may not be symmetrically equivalent, but must be of the same
    #type (x/y/z, face-diagonal, body-diagonal)
    #Will be called for mid- and high-symmetry crystallographic point groups
    def combine_axes(indices):
        symbols = {}
        for index in deepcopy(indices):
            symbol = get_symbol(params[index], orders[index],
                                reflections[index])
            if symbol == ".":
                indices.remove(index)
            else:
                symbols[index] = symbol
        if indices == []:
            return "."
        #Remove redundant axes
        for i in deepcopy(indices):
            for j in deepcopy(indices):
                if j > i:
                    if symbols[i] == symbols[j]:
                        if are_symmetrically_equivalent(i, j):
                            if j in indices:
                                indices.remove(j)
        #Combine symbols for non-equivalent axes
        new_symbols = []
        for i in indices:
            new_symbols.append(symbols[i])
        symbol = ""
        while new_symbols != []:
            highest = get_highest_symbol(new_symbols)
            symbol += highest
            new_symbols.remove(highest)
        if symbol == "":
            print("Error: could not combine site symmetry axes.")
            return
        else:
            return symbol

    #Generate needed ops
    if complete is False:
        ops = generate_full_symmops(ops, 1e-3)
    #Get OperationAnalyzer object for all ops
    opas = []
    for op in ops:
        opas.append(OperationAnalyzer(op))
    #Store the symmetry of each axis
    params = [[], [], [], [], [], [], [], [], [], [], [], [], []]
    has_inversion = False
    #Store possible symmetry axes for crystallographic point groups
    axes = [[1, 0, 0], [0, 1, 0], [0, 0, 1], [1, 1, 0], [0, 1, 1], [1, 0, 1],
            [1, -1, 0], [0, 1, -1], [1, 0, -1], [1, 1, 1], [-1, 1, 1],
            [1, -1, 1], [1, 1, -1]]
    for i, axis in enumerate(axes):
        axes[i] = axis / np.linalg.norm(axis)
    for opa in opas:
        if opa.type != "identity" and opa.type != "inversion":
            found = False
            for i, axis in enumerate(axes):
                if np.isclose(abs(np.dot(opa.axis, axis)), 1):
                    found = True
                    params[i].append(opa)
            #Store uncommon axes for trigonal and hexagonal lattices
            if found is False:
                axes.append(opa.axis)
                #Check that new axis is not symmetrically equivalent to others
                unique = True
                for i, axis in enumerate(axes):
                    if i != len(axes) - 1:
                        if are_symmetrically_equivalent(i, len(axes) - 1):
                            unique = False
                if unique is True:
                    params.append([opa])
                elif unique is False:
                    axes.pop()
        elif opa.type == "inversion":
            has_inversion = True
    #Determine how many high-symmetry axes are present
    n_axes = 0
    #Store the order of each axis
    orders = []
    #Store whether or not each axis has reflection symmetry
    reflections = []
    for axis in params:
        order = 1
        high_symm = False
        has_reflection = False
        for opa in axis:
            if opa.order >= 3:
                high_symm = True
            if opa.order > order:
                order = opa.order
            if opa.order == 2 and opa.type == "rotoinversion":
                has_reflection = True
        orders.append(order)
        if high_symm == True:
            n_axes += 1
        reflections.append(has_reflection)
    #Triclinic, monoclinic, orthorhombic
    #Positions in symbol refer to x,y,z axes respectively
    if sg >= 1 and sg <= 74:
        symbol = (get_symbol(params[0], orders[0], reflections[0]) +
                  get_symbol(params[1], orders[1], reflections[1]) +
                  get_symbol(params[2], orders[2], reflections[2]))
        if symbol != "...":
            return symbol
        elif symbol == "...":
            if has_inversion is True:
                return "-1"
            else:
                return "1"
    #Trigonal, Hexagonal, Tetragonal
    elif sg >= 75 and sg <= 194:
        #1st symbol: z axis
        s1 = get_symbol(params[2], orders[2], reflections[2])
        #2nd symbol: x or y axes (whichever have higher symmetry)
        s2 = combine_axes([0, 1])
        #3rd symbol: face-diagonal axes (whichever have highest symmetry)
        s3 = combine_axes(list(range(3, len(axes))))
        symbol = s1 + " " + s2 + " " + s3
        if symbol != ". . .":
            return symbol
        elif symbol == ". . .":
            if has_inversion is True:
                return "-1"
            else:
                return "1"
    #Cubic
    elif sg >= 195 and sg <= 230:
        pass
        #1st symbol: x, y, and/or z axes (whichever have highest symmetry)
        s1 = combine_axes([0, 1, 2])
        #2nd symbol: body-diagonal axes (whichever has highest symmetry)
        s2 = combine_axes([9, 10, 11, 12])
        #3rd symbol: face-diagonal axes (whichever have highest symmetry)
        s3 = combine_axes([3, 4, 5, 6, 7, 8])
        symbol = s1 + " " + s2 + " " + s3
        if symbol != ". . .":
            return symbol
        elif symbol == ". . .":
            if has_inversion is True:
                return "-1"
            else:
                return "1"
    else:
        print("Error: invalid spacegroup number")
        return
Example #7
0
from __future__ import print_function

import unittest
import pickle

with open('mol.pickle', 'rb') as f:
    mol = pickle.load(f)

from pymatgen.symmetry.analyzer import PointGroupAnalyzer
analyzer = PointGroupAnalyzer(mol)
print(" sch_symbol = ", analyzer.sch_symbol)

from pymatgen.symmetry.analyzer import generate_full_symmops
symmops = generate_full_symmops(analyzer.symmops, tol=1.e-7)
print(" num symmops = ", len(symmops))


class KnowValues(unittest.TestCase):
    def test_PointGroupAnalyzer(self):
        self.assertTrue(analyzer.sch_symbol == 'D4h')
        self.assertTrue(len(symmops) == 16)


if __name__ == "__main__":
    print("Tests for pymatgen.")
    unittest.main()

Example #8
0
def orientation_in_wyckoff_position(mol,
                                    sg,
                                    index,
                                    randomize=True,
                                    exact_orientation=False,
                                    already_oriented=False):
    '''
    Tests if a molecule meets the symmetry requirements of a Wyckoff position.
    If it does, return the rotation matrix needed. Otherwise, returns False.

    args:
        mol: pymatgen.core.structure.Molecule object. Orientation is arbitrary
        sg: the spacegroup to check
        index: the index of the Wyckoff position within the sg to check
        randomize: whether or not to apply a random rotation consistent with
            the symmetry requirements.
        exact_orientation: whether to only check compatibility for the provided
            orientation of the molecule. Used within general case for checking.
            If True, this function only returns True or False
    '''
    #Obtain the Wyckoff symmetry
    symm_w_unedited = get_wyckoff_symmetry(sg)[index][0]
    found_params = []
    symm_w_partial = []
    symm_w = []
    orthogonal = True
    #Check if operations are orthogonal; 3-fold and 6-fold operations are not
    for op in symm_w_unedited:
        m1 = np.dot(op.rotation_matrix, np.transpose(op.rotation_matrix))
        m2 = np.dot(np.transpose(op.rotation_matrix), op.rotation_matrix)
        if (not allclose(m1, np.identity(3))) or (not allclose(
                m2, np.identity(3))):
            rotation_order = 0
            d = np.linalg.det(op.rotation_matrix)
            if isclose(d, 1):
                op_type = "rotation"
            elif isclose(d, -1):
                op_type = "improper rotation"
            if op_type == "rotation":
                newop = deepcopy(op)
                for n in range(1, 7):
                    newop = (newop * op)
                    if allclose(newop.rotation_matrix,
                                np.identity(3),
                                rtol=1e-2):
                        rotation_order = n + 1
                        break
            elif op_type == "improper rotation":
                #We only want the order of the rotational part of op,
                #So we multiply op by -1 for rotoinversions
                op_1 = SymmOp.from_rotation_and_translation(
                    op.rotation_matrix * -1, [0, 0, 0])
                new_op = deepcopy(op_1)
                for n in range(1, 7):
                    newop = (newop * op_1)
                    if allclose(newop.rotation_matrix, np.identity(3)):
                        rotation_order = n + 1
                        break
            if rotation_order == 0:
                print("Error: could not convert to orthogonal operation:")
                print(op)
                symm_w_partial.append(op)
            else:
                params = [rotation_order, op_type]
                if params not in found_params:
                    found_params.append(params)
        else:
            symm_w_partial.append(op)
    #Add 3-fold and 6-fold symmetry back in using absolute coordinates
    for params in found_params:
        order = params[0]
        op_type = params[1]
        if op_type == "rotation" and (order == 3 or order == 6):
            m = aa2matrix([0, 0, 1], (2 * pi) / order)
        elif op_type == "improper rotation" and (order == 3 or order == 6):
            m = aa2matrix([0, 0, 1], 2 * pi / order)
            m[2] *= -1
        symm_w_partial.append(
            SymmOp.from_rotation_and_translation(m, [0, 0, 0]))
    symm_w = generate_full_symmops(symm_w_partial, 1e-3)
    #Check exact orientation
    if exact_orientation is True:
        mo = deepcopy(mol)
        pga = PointGroupAnalyzer(mo)
        valid = True
        for op in symm_w:
            op_w = SymmOp.from_rotation_and_translation(
                op.rotation_matrix, [0, 0, 0])
            if not pga.is_valid_op(op_w):
                valid = False
        if valid is True:
            return True
        elif valid is False:
            return False
    #Obtain molecular symmetry, exact_orientation==False
    symm_m = get_symmetry(mol, already_oriented=already_oriented)
    #Store OperationAnalyzer objects for each SymmOp
    opa_w = []
    for op_w in symm_w:
        opa_w.append(OperationAnalyzer(op_w))
    opa_m = []
    for op_m in symm_m:
        opa_m.append(OperationAnalyzer(op_m))
    #Check for constraints from the Wyckoff symmetry...
    #If we find ANY two constraints (SymmOps with unique axes), the molecule's
    #point group MUST contain SymmOps which can be aligned to these particular
    #constraints. However, there may be multiple compatible orientations of the
    #molecule consistent with these constraints
    constraint1 = None
    constraint2 = None
    for i, op_w in enumerate(symm_w):
        if opa_w[i].axis is not None:
            constraint1 = opa_w[i]
            for j, op_w in enumerate(symm_w):
                if opa_w[j].axis is not None:
                    dot = np.dot(opa_w[i].axis, opa_w[j].axis)
                    if (not isclose(dot, 1)) and (not isclose(dot, -1)):
                        constraint2 = opa_w[j]
                        break
            break
    #Indirectly store the angle between the constraint axes
    if (constraint1 is not None and constraint2 is not None):
        dot_w = np.dot(constraint1.axis, constraint2.axis)
    #Store corresponding symmetry elements of the molecule
    constraints_m = []
    if constraint1 is not None:
        for i, op_m in enumerate(symm_m):
            if opa_m[i].is_conjugate(constraint1):
                constraints_m.append([opa_m[i], []])
                if constraint2 is not None:
                    for j, op_m2 in enumerate(symm_m):
                        if opa_m[j].is_conjugate(constraint2):
                            dot_m = np.dot(opa_m[i].axis, opa_m[j].axis)
                            #Ensure that the angles are equal
                            if isclose(dot_m, dot_w):
                                constraints_m[-1][1].append(opa_m[j])
    #Eliminate redundancy for 1st constraint
    list_i = list(range(len(constraints_m)))
    list_j = list(range(len(constraints_m)))
    for i, c1 in enumerate(constraints_m):
        if i in list_i:
            for j, c2 in enumerate(constraints_m):
                if i > j and j in list_j and j in list_i:
                    #check if c1 and c2 are symmetrically equivalent
                    #calculate moments of inertia about both axes
                    m1_a = get_moment_of_inertia(mol, c1[0].axis)
                    m2_a = get_moment_of_inertia(mol, c2[0].axis)
                    m1_b = get_moment_of_inertia(mol, c1[0].axis, scale=2.0)
                    m2_b = get_moment_of_inertia(mol, c2[0].axis, scale=2.0)
                    if isclose(m1_a, m2_a, rtol=1e-2) and isclose(
                            m1_b, m2_b, rtol=1e-2):
                        list_i.remove(j)
                        list_j.remove(j)
    c_m = deepcopy(constraints_m)
    constraints_m = []
    for i in list_i:
        constraints_m.append(c_m[i])
    #Eliminate redundancy for second constraint
    for k, c in enumerate(constraints_m):
        if c[1] != []:
            list_i = list(range(len(c[1])))
            list_j = list(range(len(c[1])))
            for i, c1 in enumerate(c[1]):
                if i in list_i:
                    for j, c2 in enumerate(c[1]):
                        if j > i and j in list_j and j in list_i:
                            #check if c1 and c2 are symmetrically equivalent
                            #calculate moments of inertia about both axes
                            m1_a = get_moment_of_inertia(mol, c1.axis)
                            m2_a = get_moment_of_inertia(mol, c2.axis)
                            m1_b = get_moment_of_inertia(mol,
                                                         c1.axis,
                                                         scale=2.0)
                            m2_b = get_moment_of_inertia(mol,
                                                         c2.axis,
                                                         scale=2.0)
                            if isclose(m1_a, m2_a, rtol=1e-2) and isclose(
                                    m1_b, m2_b, rtol=1e-2):
                                list_i.remove(j)
                                list_j.remove(j)
            c_m = deepcopy(c[1])
            constraints_m[k][1] = []
            for i in list_i:
                constraints_m[k][1].append(c_m[i])
    #Generate orientations consistent with the possible constraints
    orientations = []
    #Loop over molecular constraint sets
    for c1 in constraints_m:
        v1 = c1[0].axis
        v2 = constraint1.axis
        T = rotate_vector(v1, v2)
        #Loop over second molecular constraints
        for opa in c1[1]:
            v1 = np.dot(T, opa.axis)
            v2 = constraint2.axis
            R = rotate_vector(v1, v2)
            T2 = np.dot(T, R)
            orientations.append(T2)
        if c1[1] == []:
            if randomize is True:
                angle = rand() * 2 * pi
                R = aa2matrix(v1, angle)
                T2 = np.dot(T, R)
                orientations.append(T2)
            else:
                orientations.append(T)
    #Ensure the identity orientation is checked if no constraints are found
    if constraints_m == []:
        if randomize is True:
            R = aa2matrix(1, 1, random=True)
            orientations.append(R)
        else:
            orientations.append(np.identity(3))
    #Check each of the found orientations for consistency with the Wyckoff pos.
    #If consistent, put into an array of valid orientations
    allowed = []
    for o in orientations:
        o = SymmOp.from_rotation_and_translation(o, [0, 0, 0])
        mo = deepcopy(mol)
        mo.apply_operation(o)
        if orientation_in_wyckoff_position(
                mo,
                sg,
                index,
                exact_orientation=True,
                already_oriented=already_oriented) is True:
            allowed.append(o)
    #Return the array of allowed orientations. If there are none, return False
    if allowed == []:
        return False
    else:
        return allowed
Example #9
0
 def __init__(self, sch_symbol, operations, tolerance=0.1):
     self.sch_symbol = sch_symbol
     super(PointGroupOperations, self).__init__([
         op.rotation_matrix
         for op in generate_full_symmops(operations, tolerance)
     ])