예제 #1
0
파일: symmetry.py 프로젝트: alongd/RMG-Py
def calculateAtomSymmetryNumber(molecule, atom):
    """
    Return the symmetry number centered at `atom` in the structure. The
    `atom` of interest must not be in a cycle.
    """
    symmetryNumber = 1

    single = 0
    double = 0
    triple = 0
    benzene = 0
    numNeighbors = 0
    for bond in atom.edges.values():
        if bond.isSingle():
            single += 1
        elif bond.isDouble():
            double += 1
        elif bond.isTriple():
            triple += 1
        elif bond.isBenzene():
            benzene += 1
        numNeighbors += 1

    # If atom has zero or one neighbors, the symmetry number is 1
    if numNeighbors < 2:
        return symmetryNumber

    # Create temporary structures for each functional group attached to atom
    molecule0 = molecule
    molecule = molecule0.copy(True)
    atom = molecule.vertices[molecule0.vertices.index(atom)]
    molecule.removeAtom(atom)
    groups = molecule.split()

    # Determine equivalence of functional groups around atom
    groupIsomorphism = dict([(group, dict()) for group in groups])
    for group1 in groups:
        for group2 in groups:
            if group1 is not group2 and group2 not in groupIsomorphism[group1]:
                groupIsomorphism[group1][group2] = group1.isIsomorphic(group2)
                groupIsomorphism[group2][group1] = groupIsomorphism[group1][group2]
            elif group1 is group2:
                groupIsomorphism[group1][group1] = True
    count = [sum([int(groupIsomorphism[group1][group2]) for group2 in groups]) for group1 in groups]
    for i in range(count.count(2) / 2):
        count.remove(2)
    for i in range(count.count(3) / 3):
        count.remove(3)
        count.remove(3)
    for i in range(count.count(4) / 4):
        count.remove(4)
        count.remove(4)
        count.remove(4)
    count.sort()
    count.reverse()

    if atom.radicalElectrons == 0:
        if single == 4:
            # Four single bonds
            if count == [4]:
                symmetryNumber *= 12
            elif count == [3, 1]:
                symmetryNumber *= 3
            elif count == [2, 2]:
                symmetryNumber *= 2
            elif count == [2, 1, 1]:
                symmetryNumber *= 1
            elif count == [1, 1, 1, 1]:
                symmetryNumber *= 1
        elif single == 3:
            # Three single bonds
            if count == [3]:
                symmetryNumber *= 3
            elif count == [2, 1]:
                symmetryNumber *= 1
            elif count == [1, 1, 1]:
                symmetryNumber *= 1

        elif single == 2:
            # Two single bonds
            if count == [2]:
                symmetryNumber *= 2
        elif double == 2:
            # Two double bonds
            if count == [2]:
                symmetryNumber *= 2
    elif atom.radicalElectrons == 1:
        if single == 3:
            # Three single bonds
            if count == [3]:
                symmetryNumber *= 6
            elif count == [2, 1]:
                symmetryNumber *= 2
            elif count == [1, 1, 1]:
                symmetryNumber *= 1
    elif atom.radicalElectrons == 2:
        if single == 2:
            # Two single bonds
            if count == [2]:
                symmetryNumber *= 2

    if atom.isNitrogen():
        for groupN in groups:
            if groupN.toSMILES() == "[N+](=O)[O-]":
                symmetryNumber *= 2

    return symmetryNumber
예제 #2
0
def calculateAtomSymmetryNumber(molecule, atom):
    """
    Return the symmetry number centered at `atom` in the structure. The
    `atom` of interest must not be in a cycle.
    """
    symmetryNumber = 1

    single = 0
    double = 0
    triple = 0
    benzene = 0
    numNeighbors = 0
    for bond in atom.edges.values():
        if bond.isSingle(): single += 1
        elif bond.isDouble(): double += 1
        elif bond.isTriple(): triple += 1
        elif bond.isBenzene(): benzene += 1
        numNeighbors += 1

    # If atom has zero or one neighbors, the symmetry number is 1
    if numNeighbors < 2: return symmetryNumber

    # Create temporary structures for each functional group attached to atom
    molecule0 = molecule
    molecule = molecule0.copy(True)
    atom = molecule.vertices[molecule0.vertices.index(atom)]
    molecule.removeAtom(atom)
    groups = molecule.split()

    # Determine equivalence of functional groups around atom
    groupIsomorphism = dict([(group, dict()) for group in groups])
    for group1 in groups:
        for group2 in groups:
            if group1 is not group2 and group2 not in groupIsomorphism[group1]:
                groupIsomorphism[group1][group2] = group1.isIsomorphic(group2)
                groupIsomorphism[group2][group1] = groupIsomorphism[group1][
                    group2]
            elif group1 is group2:
                groupIsomorphism[group1][group1] = True
    count = [
        sum([int(groupIsomorphism[group1][group2]) for group2 in groups])
        for group1 in groups
    ]
    for i in range(count.count(2) / 2):
        count.remove(2)
    for i in range(count.count(3) / 3):
        count.remove(3)
        count.remove(3)
    for i in range(count.count(4) / 4):
        count.remove(4)
        count.remove(4)
        count.remove(4)
    count.sort()
    count.reverse()

    if atom.radicalElectrons == 0:
        if single == 4:
            # Four single bonds
            if count == [4]: symmetryNumber *= 12
            elif count == [3, 1]: symmetryNumber *= 3
            elif count == [2, 2]: symmetryNumber *= 2
            elif count == [2, 1, 1]: symmetryNumber *= 1
            elif count == [1, 1, 1, 1]:
                symmetryNumber *= 0.5  # found chirality
        elif single == 3:
            # Three single bonds
            if count == [3]: symmetryNumber *= 3
            elif count == [2, 1]: symmetryNumber *= 1
            elif count == [1, 1, 1]: symmetryNumber *= 1
        elif single == 2:
            # Two single bonds
            if count == [2]: symmetryNumber *= 2
        # for resonance hybrids
        elif single == 1:
            if count == [2, 1]: symmetryNumber *= 2
        elif double == 2:
            # Two double bonds
            if count == [2]: symmetryNumber *= 2
        # for nitrogen resonance hybrids
        elif single == 0:
            if count == [2]: symmetryNumber *= 2
    elif atom.radicalElectrons == 1:
        if single == 3:
            # Three single bonds
            if count == [3]: symmetryNumber *= 6
            elif count == [2, 1]: symmetryNumber *= 2
            elif count == [1, 1, 1]: symmetryNumber *= 1
    elif atom.radicalElectrons == 2:
        if single == 2:
            # Two single bonds
            if count == [2]:
                symmetryNumber *= 2

    return symmetryNumber