Esempio n. 1
0
def update_molecule(mol, to_single_bonds=False):
    """
    Returns a copy of the current molecule with updated atomTypes
    if to_single_bonds is True, the returned mol contains only single bonds.
    This is useful for isomorphism comparison
    """
    new_mol = Molecule()
    try:
        atoms = mol.atoms
    except AttributeError:
        return None
    atom_mapping = dict()
    for atom1 in atoms:
        new_atom = new_mol.addAtom(Atom(atom1.element))
        atom_mapping[atom1] = new_atom
    for atom1 in atoms:
        for atom2 in atom1.bonds.keys():
            bond_order = 1.0 if to_single_bonds else atom1.bonds[
                atom2].getOrderNum()
            bond = Bond(atom_mapping[atom1], atom_mapping[atom2], bond_order)
            new_mol.addBond(bond)
    try:
        new_mol.updateAtomTypes()
    except AtomTypeError:
        pass
    new_mol.multiplicity = mol.multiplicity
    return new_mol
Esempio n. 2
0
    def testSubgraphIsomorphism(self):
        # Simple test comparing C-C to C-C-C (no hydrogens)
        mol = Molecule()

        c1 = Atom(getElement(6))
        c2 = c1.copy()

        mol.addAtom(c1)
        mol.addAtom(c2)
        mol.addBond(Bond(c1, c2))

        mol2 = Molecule()

        c1 = c1.copy()
        c2 = c1.copy()
        c3 = c1.copy()

        mol2.addAtom(c1)
        mol2.addAtom(c2)
        mol2.addAtom(c3)
        mol2.addBond(Bond(c1, c2))
        mol2.addBond(Bond(c2, c3))

        self.assertTrue(self.vf3.isSubgraphIsomorphic(mol2, mol, None))
        self.assertFalse(self.vf3.isSubgraphIsomorphic(mol, mol2, None))

        # Ring membership is a semantic property of molecules,
        # so straight chains are not considered sub graphs of rings

        hexane = Molecule().fromSMILES("C1CCCCC1")

        self.assertFalse(self.vf3.isSubgraphIsomorphic(hexane, mol, None))
        self.assertFalse(self.vf3.isSubgraphIsomorphic(hexane, mol2, None))

        # Benzene and hexane, while technically sharing the same shape,
        # differ in semantic information.
        benzene = Molecule().fromSMILES("C1=CC=CC=C1")

        self.assertFalse(self.vf3.isSubgraphIsomorphic(hexane, benzene, None))

        # Test sub graph isomorphism on rings
        hexaneMinusH = hexane.copy(True)
        hexaneMinusH.removeVertex(hexaneMinusH.vertices[6])

        self.assertTrue(self.vf3.isSubgraphIsomorphic(hexane, hexaneMinusH, None))
        self.assertFalse(self.vf3.isSubgraphIsomorphic(hexaneMinusH, hexane, None))
        
        benzeneMinusH = benzene.copy(True)
        benzeneMinusH.removeVertex(benzeneMinusH.vertices[6])

        self.assertTrue(self.vf3.isSubgraphIsomorphic(benzene, benzeneMinusH, None))
        self.assertFalse(self.vf3.isSubgraphIsomorphic(benzeneMinusH, hexane, None))
Esempio n. 3
0
 def testToAdjacencyListForNonIntegerBonds(self):
     """
     Test the adjacency list can be created for molecules with bond orders
     that don't fit into single, double, triple, or benzene
     """
     from rmgpy.molecule.molecule import Atom, Bond, Molecule
     atom1 = Atom(element='H', lonePairs=0)
     atom2 = Atom(element='H', lonePairs=0)
     bond = Bond(atom1, atom2, 0.5)
     mol = Molecule(multiplicity=1)
     mol.addAtom(atom1)
     mol.addAtom(atom2)
     mol.addBond(bond)
     adjlist = mol.toAdjacencyList()
     self.assertIn('H', adjlist)
     self.assertIn('{1,0.5}', adjlist)
Esempio n. 4
0
 def testToAdjacencyListForNonIntegerBonds(self):
     """
     Test the adjacency list can be created for molecules with bond orders
     that don't fit into single, double, triple, or benzene
     """
     from rmgpy.molecule.molecule import Atom, Bond, Molecule
     atom1 = Atom(element='H',lonePairs=0)
     atom2 = Atom(element='H',lonePairs=0)
     bond = Bond(atom1, atom2, 0.5)
     mol = Molecule(multiplicity=1)
     mol.addAtom(atom1)
     mol.addAtom(atom2)
     mol.addBond(bond)
     adjlist = mol.toAdjacencyList()
     self.assertIn('H', adjlist)
     self.assertIn('{1,0.5}',adjlist)
    def getResonanceHybrid(self):
        """
        Returns a molecule object with bond orders that are the average 
        of all the resonance structures.
        """
        # get labeled resonance isomers
        self.generate_resonance_structures(keep_isomorphic=True)

        # only consider reactive molecules as representative structures
        molecules = [mol for mol in self.molecule if mol.reactive]

        # return if no resonance
        if len(molecules) == 1:
            return molecules[0]

        # create a sorted list of atom objects for each resonance structure
        cython.declare(atomsFromStructures = list, oldAtoms = list, newAtoms = list,
                       numResonanceStructures=cython.short, structureNum = cython.short,
                       oldBondOrder = cython.float,
                       index1 = cython.short, index2 = cython.short,
                      newMol=Molecule, oldMol = Molecule,
                      atom1=Atom, atom2=Atom, 
                      bond=Bond,  
                      atoms=list,)

        atomsFromStructures = []
        for newMol in molecules:
            newMol.atoms.sort(key=lambda atom: atom.id)
            atomsFromStructures.append(newMol.atoms)

        numResonanceStructures = len(molecules)

        # make original structure with no bonds
        newMol = Molecule()
        originalAtoms = atomsFromStructures[0]
        for atom1 in originalAtoms:
            atom = newMol.addAtom(Atom(atom1.element))
            atom.id = atom1.id

        newAtoms = newMol.atoms

        # initialize bonds to zero order
        for index1, atom1 in enumerate(originalAtoms):
            for atom2 in atom1.bonds:
                index2 = originalAtoms.index(atom2)
                bond = Bond(newAtoms[index1],newAtoms[index2], 0)
                newMol.addBond(bond)

        # set bonds to the proper value
        for structureNum, oldMol in enumerate(molecules):
            oldAtoms = atomsFromStructures[structureNum]

            for index1, atom1 in enumerate(oldAtoms):
                # make bond orders average of resonance structures
                for atom2 in atom1.bonds:
                    index2 = oldAtoms.index(atom2)

                    newBond = newMol.getBond(newAtoms[index1], newAtoms[index2])
                    oldBondOrder = oldMol.getBond(oldAtoms[index1], oldAtoms[index2]).getOrderNum()
                    newBond.applyAction(('CHANGE_BOND',None,oldBondOrder / numResonanceStructures / 2))
                # set radicals in resonance hybrid to maximum of all structures
                if atom1.radicalElectrons > 0:
                    newAtoms[index1].radicalElectrons = max(atom1.radicalElectrons,
                                                            newAtoms[index1].radicalElectrons)
        newMol.updateAtomTypes(logSpecies = False, raiseException=False)
        return newMol
Esempio n. 6
0
    def getResonanceHybrid(self):
        """
        Returns a molecule object with bond orders that are the average 
        of all the resonance structures.
        """
        # get labeled resonance isomers
        self.generate_resonance_structures(keep_isomorphic=True)

        # only consider reactive molecules as representative structures
        molecules = [mol for mol in self.molecule if mol.reactive]

        # return if no resonance
        if len(molecules) == 1:
            return molecules[0]

        # create a sorted list of atom objects for each resonance structure
        cython.declare(atomsFromStructures = list, oldAtoms = list, newAtoms = list,
                       numResonanceStructures=cython.short, structureNum = cython.short,
                       oldBondOrder = cython.float,
                       index1 = cython.short, index2 = cython.short,
                      newMol=Molecule, oldMol = Molecule,
                      atom1=Atom, atom2=Atom, 
                      bond=Bond,  
                      atoms=list,)

        atomsFromStructures = []
        for newMol in molecules:
            newMol.atoms.sort(key=lambda atom: atom.id)
            atomsFromStructures.append(newMol.atoms)

        numResonanceStructures = len(molecules)

        # make original structure with no bonds
        newMol = Molecule()
        originalAtoms = atomsFromStructures[0]
        for atom1 in originalAtoms:
            atom = newMol.addAtom(Atom(atom1.element))
            atom.id = atom1.id

        newAtoms = newMol.atoms

        # initialize bonds to zero order
        for index1, atom1 in enumerate(originalAtoms):
            for atom2 in atom1.bonds:
                index2 = originalAtoms.index(atom2)
                bond = Bond(newAtoms[index1],newAtoms[index2], 0)
                newMol.addBond(bond)

        # set bonds to the proper value
        for structureNum, oldMol in enumerate(molecules):
            oldAtoms = atomsFromStructures[structureNum]

            for index1, atom1 in enumerate(oldAtoms):
                # make bond orders average of resonance structures
                for atom2 in atom1.bonds:
                    index2 = oldAtoms.index(atom2)

                    newBond = newMol.getBond(newAtoms[index1], newAtoms[index2])
                    oldBondOrder = oldMol.getBond(oldAtoms[index1], oldAtoms[index2]).getOrderNum()
                    newBond.applyAction(('CHANGE_BOND',None,oldBondOrder / numResonanceStructures / 2))
                # set radicals in resonance hybrid to maximum of all structures
                if atom1.radicalElectrons > 0:
                    newAtoms[index1].radicalElectrons = max(atom1.radicalElectrons,
                                                            newAtoms[index1].radicalElectrons)
        newMol.updateAtomTypes(logSpecies = False, raiseException=False)
        return newMol
    def assign_representative_molecule(self):

        # create a molecule from fragment.vertices.copy
        mapping = self.copyAndMap()

        # replace CuttingLabel with CC
        atoms = []
        additional_atoms = []
        additional_bonds = []
        for vertex in self.vertices:

            mapped_vertex = mapping[vertex]
            if isinstance(mapped_vertex, CuttingLabel):

                # replace cutting label with atom C
                atom_C1 = Atom(element=getElement('C'),
                               radicalElectrons=0,
                               charge=0,
                               lonePairs=0)

                for bondedAtom, bond in mapped_vertex.edges.iteritems():
                    new_bond = Bond(bondedAtom, atom_C1, order=bond.order)

                    bondedAtom.edges[atom_C1] = new_bond
                    del bondedAtom.edges[mapped_vertex]

                    atom_C1.edges[bondedAtom] = new_bond

                # add hydrogens and carbon to make it CC
                atom_H1 = Atom(element=getElement('H'),
                               radicalElectrons=0,
                               charge=0,
                               lonePairs=0)

                atom_H2 = Atom(element=getElement('H'),
                               radicalElectrons=0,
                               charge=0,
                               lonePairs=0)

                atom_C2 = Atom(element=getElement('C'),
                               radicalElectrons=0,
                               charge=0,
                               lonePairs=0)

                atom_H3 = Atom(element=getElement('H'),
                               radicalElectrons=0,
                               charge=0,
                               lonePairs=0)

                atom_H4 = Atom(element=getElement('H'),
                               radicalElectrons=0,
                               charge=0,
                               lonePairs=0)

                atom_H5 = Atom(element=getElement('H'),
                               radicalElectrons=0,
                               charge=0,
                               lonePairs=0)

                atoms.append(atom_C1)

                additional_atoms.extend(
                    [atom_H1, atom_H2, atom_H3, atom_H4, atom_H5, atom_C2])

                additional_bonds.extend([
                    Bond(atom_C1, atom_H1, 1),
                    Bond(atom_C1, atom_H2, 1),
                    Bond(atom_C2, atom_H3, 1),
                    Bond(atom_C2, atom_H4, 1),
                    Bond(atom_C2, atom_H5, 1),
                    Bond(atom_C1, atom_C2, 1)
                ])

            else:
                atoms.append(mapped_vertex)

        mol_repr = Molecule()
        mol_repr.atoms = atoms
        for atom in additional_atoms:
            mol_repr.addAtom(atom)
        for bond in additional_bonds:
            mol_repr.addBond(bond)
        # update connectivity
        mol_repr.update()

        # create a species object from molecule
        self.mol_repr = mol_repr

        return mapping