コード例 #1
0
    def radical_site_test(self):
        """Test that a charged molecule isn't filtered if it introduces new radical site"""
        adj1 = """
        multiplicity 2
        1 O u1 p2 c0 {3,S}
        2 O u0 p2 c0 {3,D}
        3 N u0 p1 c0 {1,S} {2,D}
        """
        adj2 = """
        multiplicity 2
        1 O u0 p3 c-1 {3,S}
        2 O u0 p2 c0 {3,D}
        3 N u1 p0 c+1 {1,S} {2,D}
        """
        adj3 = """
        multiplicity 2
        1 O u1 p2 c0 {3,S}
        2 O u0 p3 c-1 {3,S}
        3 N u0 p1 c+1 {1,S} {2,S}
        """

        mol_list = [
            Molecule().from_adjacency_list(adj1),
            Molecule().from_adjacency_list(adj2),
            Molecule().from_adjacency_list(adj3)
        ]

        for mol in mol_list:
            mol.update(
            )  # the charge_filtration uses the atom.sorting_label attribute

        filtered_list = charge_filtration(mol_list,
                                          get_charge_span_list(mol_list))
        self.assertEqual(len(filtered_list), 2)
        self.assertTrue(
            any([mol.get_charge_span() == 1 for mol in filtered_list]))
        for mol in filtered_list:
            if mol.get_charge_span() == 1:
                for atom in mol.vertices:
                    if atom.charge == -1:
                        self.assertTrue(atom.is_oxygen())
                    if atom.charge == 1:
                        self.assertTrue(atom.is_nitrogen())
コード例 #2
0
    def radical_site_test(self):
        """Test that a charged molecule isn't filtered if it introduces new radical site"""
        adj1 = """
        multiplicity 2
        1 O u1 p2 c0 {3,S}
        2 O u0 p2 c0 {3,D}
        3 N u0 p1 c0 {1,S} {2,D}
        """
        adj2 = """
        multiplicity 2
        1 O u0 p3 c-1 {3,S}
        2 O u0 p2 c0 {3,D}
        3 N u1 p0 c+1 {1,S} {2,D}
        """
        adj3 = """
        multiplicity 2
        1 O u1 p2 c0 {3,S}
        2 O u0 p3 c-1 {3,S}
        3 N u0 p1 c+1 {1,S} {2,S}
        """

        mol_list = [Molecule().fromAdjacencyList(adj1),
                    Molecule().fromAdjacencyList(adj2),
                    Molecule().fromAdjacencyList(adj3)]

        for mol in mol_list:
            mol.update()  # the charge_filtration uses the atom.sortingLabel attribute

        filtered_list = charge_filtration(mol_list, get_charge_span_list(mol_list))
        self.assertEqual(len(filtered_list), 2)
        self.assertTrue(any([mol.getChargeSpan() == 1 for mol in filtered_list]))
        for mol in filtered_list:
            if mol.getChargeSpan() == 1:
                for atom in mol.vertices:
                    if atom.charge == -1:
                        self.assertTrue(atom.isOxygen())
                    if atom.charge == 1:
                        self.assertTrue(atom.isNitrogen())
コード例 #3
0
    def electronegativity_test(self):
        """Test that structures with charge separation are only kept if they obey the electronegativity rule

        (If a structure must have charge separation, negative charges will be assigned to more electronegative atoms,
        whereas positive charges will be assigned to less electronegative atoms)

        In this test, only the three structures with no charge separation and the structure where both partial charges
        are on the nitrogen atoms should be kept."""
        adj1 = """
        multiplicity 2
        1 N u0 p1 c0 {2,S} {3,D}
        2 N u1 p1 c0 {1,S} {4,S}
        3 S u0 p1 c0 {1,D} {5,D}
        4 H u0 p0 c0 {2,S}
        5 O u0 p2 c0 {3,D}
        """
        adj2 = """
        multiplicity 2
        1 N u0 p1 c0 {2,D} {3,S}
        2 N u0 p1 c0 {1,D} {4,S}
        3 S u1 p1 c0 {1,S} {5,D}
        4 H u0 p0 c0 {2,S}
        5 O u0 p2 c0 {3,D}
        """
        adj3 = """
        multiplicity 2
        1 N u0 p1 c0 {2,D} {3,S}
        2 N u0 p1 c0 {1,D} {4,S}
        3 S u0 p2 c0 {1,S} {5,S}
        4 H u0 p0 c0 {2,S}
        5 O u1 p2 c0 {3,S}
        """
        adj4 = """
        multiplicity 2
        1 N u1 p0 c+1 {2,S} {3,D}
        2 N u0 p2 c-1 {1,S} {4,S}
        3 S u0 p1 c0 {1,D} {5,D}
        4 H u0 p0 c0 {2,S}
        5 O u0 p2 c0 {3,D}
        """
        adj5 = """
        multiplicity 2
        1 N u1 p0 c+1 {2,D} {3,S}
        2 N u0 p1 c0 {1,D} {4,S}
        3 S u0 p2 c-1 {1,S} {5,D}
        4 H u0 p0 c0 {2,S}
        5 O u0 p2 c0 {3,D}
        """
        adj6 = """
        multiplicity 2
        1 N u1 p1 c0 {2,S} {3,S}
        2 N u0 p2 c-1 {1,S} {4,S}
        3 S u0 p1 c+1 {1,S} {5,D}
        4 H u0 p0 c0 {2,S}
        5 O u0 p2 c0 {3,D}
        """
        adj7 = """
        multiplicity 2
        1 N u1 p0 c+1 {2,D} {3,S}
        2 N u0 p1 c0 {1,D} {4,S}
        3 S u0 p2 c0 {1,S} {5,S}
        4 H u0 p0 c0 {2,S}
        5 O u0 p3 c-1 {3,S}
        """

        mol_list = [
            Molecule().from_adjacency_list(adj1),
            Molecule().from_adjacency_list(adj2),
            Molecule().from_adjacency_list(adj3),
            Molecule().from_adjacency_list(adj4),
            Molecule().from_adjacency_list(adj5),
            Molecule().from_adjacency_list(adj6),
            Molecule().from_adjacency_list(adj7)
        ]

        for mol in mol_list:
            mol.update(
            )  # the charge_filtration uses the atom.sorting_label attribute

        filtered_list = charge_filtration(mol_list,
                                          get_charge_span_list(mol_list))
        self.assertEqual(len(filtered_list), 4)
        self.assertTrue(
            any([mol.get_charge_span() == 1 for mol in filtered_list]))
        for mol in filtered_list:
            if mol.get_charge_span() == 1:
                for atom in mol.vertices:
                    if abs(atom.charge) == 1:
                        self.assertTrue(atom.is_nitrogen())
コード例 #4
0
ファイル: resonance.py プロジェクト: zhedian/RMG-Py
def _generate_resonance_structures(mol_list, method_list, keep_isomorphic=False, copy=False, filter_structures=True):
    """
    Iteratively generate all resonance structures for a list of starting molecules using the specified methods.

    Args:
        mol_list             starting list of molecules
        method_list          list of resonance structure algorithms
        keep_isomorphic      if False, removes any structures that give is_isomorphic=True (default)
                            if True, only remove structures that give is_identical=True
        copy                if False, append new resonance structures to input list (default)
                            if True, make a new list with all of the resonance structures
    """
    cython.declare(index=cython.int, molecule=Molecule, new_mol_list=list, new_mol=Molecule, mol=Molecule)

    if copy:
        # Make a copy of the list so we don't modify the input list
        mol_list = mol_list[:]

    min_octet_deviation = min(filtration.get_octet_deviation_list(mol_list))
    min_charge_span = min(filtration.get_charge_span_list(mol_list))

    # Iterate over resonance structures
    index = 0
    while index < len(mol_list):
        molecule = mol_list[index]
        new_mol_list = []

        # On-the-fly filtration: Extend methods only for molecule that don't deviate too much from the octet rule
        # (a +2 distance from the minimal deviation is used, octet deviations per species are in increments of 2)
        # Sometimes rearranging the structure requires an additional higher charge span structure, so allow
        # structures with a +1 higher charge span compared to the minimum, e.g., [O-]S#S[N+]#N
        # This is run by default even if filter_structures=False.
        octet_deviation = filtration.get_octet_deviation(molecule)
        charge_span = molecule.get_charge_span()
        if octet_deviation <= min_octet_deviation + 2 and charge_span <= min_charge_span + 1:
            for method in method_list:
                new_mol_list.extend(method(molecule))
            if octet_deviation < min_octet_deviation:
                # update min_octet_deviation to make this criterion tighter
                min_octet_deviation = octet_deviation
            if charge_span < min_charge_span:
                # update min_charge_span to make this criterion tighter
                min_charge_span = charge_span

        for new_mol in new_mol_list:
            # Append to structure list if unique
            for mol in mol_list:
                if not keep_isomorphic and mol.is_isomorphic(new_mol):
                    break
                elif keep_isomorphic and mol.is_identical(new_mol):
                    break
            else:
                mol_list.append(new_mol)

        # Move to the next resonance structure
        index += 1

    # check net charge
    for mol in mol_list:
        if mol.get_net_charge() != 0:
            raise ResonanceError('Resonance generation gave a net charged molecule:\n{0}'
                                 'Ions are not yet supported in RMG.'.format(
                mol.to_adjacency_list()))

    return mol_list
コード例 #5
0
    def electronegativity_test(self):
        """Test that structures with charge separation are only kept if they obey the electronegativity rule

        (If a structure must have charge separation, negative charges will be assigned to more electronegative atoms,
        whereas positive charges will be assigned to less electronegative atoms)

        In this test, only the three structures with no charge separation and the structure where both partial charges
        are on the nitrogen atoms should be kept."""
        adj1 = """
        multiplicity 2
        1 N u0 p1 c0 {2,S} {3,D}
        2 N u1 p1 c0 {1,S} {4,S}
        3 S u0 p1 c0 {1,D} {5,D}
        4 H u0 p0 c0 {2,S}
        5 O u0 p2 c0 {3,D}
        """
        adj2 = """
        multiplicity 2
        1 N u0 p1 c0 {2,D} {3,S}
        2 N u0 p1 c0 {1,D} {4,S}
        3 S u1 p1 c0 {1,S} {5,D}
        4 H u0 p0 c0 {2,S}
        5 O u0 p2 c0 {3,D}
        """
        adj3 = """
        multiplicity 2
        1 N u0 p1 c0 {2,D} {3,S}
        2 N u0 p1 c0 {1,D} {4,S}
        3 S u0 p2 c0 {1,S} {5,S}
        4 H u0 p0 c0 {2,S}
        5 O u1 p2 c0 {3,S}
        """
        adj4 = """
        multiplicity 2
        1 N u1 p0 c+1 {2,S} {3,D}
        2 N u0 p2 c-1 {1,S} {4,S}
        3 S u0 p1 c0 {1,D} {5,D}
        4 H u0 p0 c0 {2,S}
        5 O u0 p2 c0 {3,D}
        """
        adj5 = """
        multiplicity 2
        1 N u1 p0 c+1 {2,D} {3,S}
        2 N u0 p1 c0 {1,D} {4,S}
        3 S u0 p2 c-1 {1,S} {5,D}
        4 H u0 p0 c0 {2,S}
        5 O u0 p2 c0 {3,D}
        """
        adj6 = """
        multiplicity 2
        1 N u1 p1 c0 {2,S} {3,S}
        2 N u0 p2 c-1 {1,S} {4,S}
        3 S u0 p1 c+1 {1,S} {5,D}
        4 H u0 p0 c0 {2,S}
        5 O u0 p2 c0 {3,D}
        """
        adj7 = """
        multiplicity 2
        1 N u1 p0 c+1 {2,D} {3,S}
        2 N u0 p1 c0 {1,D} {4,S}
        3 S u0 p2 c0 {1,S} {5,S}
        4 H u0 p0 c0 {2,S}
        5 O u0 p3 c-1 {3,S}
        """

        mol_list = [Molecule().fromAdjacencyList(adj1),
                    Molecule().fromAdjacencyList(adj2),
                    Molecule().fromAdjacencyList(adj3),
                    Molecule().fromAdjacencyList(adj4),
                    Molecule().fromAdjacencyList(adj5),
                    Molecule().fromAdjacencyList(adj6),
                    Molecule().fromAdjacencyList(adj7)]

        for mol in mol_list:
            mol.update()  # the charge_filtration uses the atom.sortingLabel attribute

        filtered_list = charge_filtration(mol_list, get_charge_span_list(mol_list))
        self.assertEqual(len(filtered_list), 4)
        self.assertTrue(any([mol.getChargeSpan() == 1 for mol in filtered_list]))
        for mol in filtered_list:
            if mol.getChargeSpan() == 1:
                for atom in mol.vertices:
                    if abs(atom.charge) == 1:
                        self.assertTrue(atom.isNitrogen())