Skip to content

Refactoring of Molecule module and change to how graphs are stored. #85

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 23 commits into from
Jul 6, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
a31603f
Created rmgpy.molecule subpackage.
jwallen Jun 5, 2012
4c8db82
Moved several modules into the rmgpy.molecule subpackage.
jwallen Jun 5, 2012
ac12f01
Updated references to moved rmgpy.molecule submodules.
jwallen Jun 5, 2012
5021e15
Moved rmgpy.molecule unit test modules into molecule subfolder.
jwallen Jun 5, 2012
3f8ecee
Updated references to moved rmgpy.molecule submodules in unit tests.
jwallen Jun 5, 2012
7f8e1d9
Created new rmgpy.molecule.symmetry module for symmetry number calcul…
jwallen Jun 5, 2012
e9656a3
Split symmetry number unit tests to separate module.
jwallen Jun 5, 2012
287f161
Removed implicit hydrogens functionality from Molecule objects.
jwallen Jun 5, 2012
6573ee9
Removed assorted references to implicit/explicit hydrogens.
jwallen Jun 5, 2012
1033d46
Now storing dict of edges on Vertex and vertices on Edge.
jwallen Jun 5, 2012
4f103d9
Added new implementation of VF2 algorithm for graph isomorphism.
jwallen Jun 5, 2012
5efe114
Updated symmetry number functions to work with new Graph format.
jwallen Jun 5, 2012
21f5757
Added new rmgpy.molecule.adjlist module for working with adjacency li…
jwallen Jun 5, 2012
d07a1df
Updated Atom, Bond, and Molecule to work with new Graph format.
jwallen Jun 5, 2012
744b10c
Updated GroupAtom, GroupBond, and Group to work with new Graph format.
jwallen Jun 5, 2012
0581d15
Updated molecule drawing functionality to work with new Graph format.
jwallen Jun 6, 2012
8a9cb44
Updated thermo and kinetics database code to work with new Graph format.
jwallen Jun 6, 2012
6bbb693
Reordered a couple of 'if' blocks to be more efficient.
rwest Jun 14, 2012
82b6a2b
Small changes to docstring and comment.
rwest Jun 14, 2012
d177753
Fixed bug in cycle detection algorithm caused by new graph format.
jwallen Jun 14, 2012
acccd69
Fix ring correction searching in group additive thermo estimator.
rwest Jun 19, 2012
108886f
Fix issue #82 in rmgpy.molecule.graph.Graph.getSmallestSetOfSmallestR…
rwest Jun 19, 2012
0bd9b13
Change SMILES writer to remove stereochemistry.
rwest Jun 19, 2012
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions rmgpy/chemkin.py
Original file line number Diff line number Diff line change
Expand Up @@ -843,13 +843,6 @@ def writeThermoEntry(species):
elementCounts.append(1)
else:
elementCounts[elements.index(symbol)] += 1
# Also handle implicit hydrogen atoms
symbol = 'H'
if symbol not in elements:
elements.append(symbol)
elementCounts.append(atom.implicitHydrogens)
else:
elementCounts[elements.index(symbol)] += atom.implicitHydrogens
# Remove elements with zero count
index = 0
while index < len(elementCounts):
Expand Down
3 changes: 1 addition & 2 deletions rmgpy/data/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@
import codecs

from rmgpy.quantity import *
from rmgpy.molecule import Molecule
from rmgpy.group import Group, InvalidAdjacencyListError
from rmgpy.molecule import Molecule, Group, InvalidAdjacencyListError

from reference import *

Expand Down
87 changes: 40 additions & 47 deletions rmgpy/data/kinetics.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@
from rmgpy.quantity import Quantity
from rmgpy.reaction import Reaction, ReactionError
from rmgpy.kinetics import *
from rmgpy.group import GroupBond, Group
from rmgpy.molecule import Bond
from rmgpy.molecule import Bond, GroupBond, Group
from rmgpy.species import Species

################################################################################
Expand Down Expand Up @@ -239,15 +238,15 @@ def __apply(self, struct, doForward, unique):
atom2.applyAction(['CHANGE_BOND', label1, -info, label2])
bond.applyAction(['CHANGE_BOND', label1, -info, label2])
elif (action[0] == 'FORM_BOND' and doForward) or (action[0] == 'BREAK_BOND' and not doForward):
bond = GroupBond(order=['S']) if pattern else Bond(order='S')
struct.addBond(atom1, atom2, bond)
bond = GroupBond(atom1, atom2, order=['S']) if pattern else Bond(atom1, atom2, order='S')
struct.addBond(bond)
atom1.applyAction(['FORM_BOND', label1, info, label2])
atom2.applyAction(['FORM_BOND', label1, info, label2])
elif (action[0] == 'BREAK_BOND' and doForward) or (action[0] == 'FORM_BOND' and not doForward):
if not struct.hasBond(atom1, atom2):
raise InvalidActionError('Attempted to remove a nonexistent bond.')
bond = struct.getBond(atom1, atom2)
struct.removeBond(atom1, atom2)
struct.removeBond(bond)
atom1.applyAction(['BREAK_BOND', label1, info, label2])
atom2.applyAction(['BREAK_BOND', label1, info, label2])

Expand Down Expand Up @@ -1981,7 +1980,7 @@ def addKineticsRulesFromTrainingSet(self, thermoDatabase=None):
data.changeT0(1)

# Estimate the thermo for the reactants and products
item = deepcopy(entry.item)
item = Reaction(reactants=[m.copy(deep=True) for m in entry.item.reactants], products=[m.copy(deep=True) for m in entry.item.products])
item.reactants = [Species(molecule=[m]) for m in item.reactants]
for reactant in item.reactants:
reactant.generateResonanceIsomers()
Expand Down Expand Up @@ -2356,9 +2355,8 @@ def __matchReactantToTemplate(self, reactant, templateReactant):
if isinstance(struct, LogicNode):
mappings = []
for child_structure in struct.getPossibleStructures(self.groups.entries):
ismatch, map = reactant.findSubgraphIsomorphisms(child_structure)
if ismatch: mappings.extend(map)
return len(mappings) > 0, mappings
mappings.extend(reactant.findSubgraphIsomorphisms(child_structure))
return mappings
elif isinstance(struct, Group):
return reactant.findSubgraphIsomorphisms(struct)

Expand Down Expand Up @@ -2492,8 +2490,6 @@ def __generateReactions(self, reactants, forward=True):
for i in range(len(reactants)):
for j in range(len(reactants[i])):
reactants[i][j] = reactants[i][j].copy(deep=True)
# Each molecule must have explicit hydrogen atoms
reactants[i][j].makeHydrogensExplicit()

if forward:
template = self.forwardTemplate
Expand All @@ -2508,18 +2504,17 @@ def __generateReactions(self, reactants, forward=True):
# Iterate over all resonance isomers of the reactant
for molecule in reactants[0]:

ismatch, mappings = self.__matchReactantToTemplate(molecule, template.reactants[0])
if ismatch:
for map in mappings:
reactantStructures = [molecule]
try:
productStructures = self.__generateProductStructures(reactantStructures, [map], forward)
except ForbiddenStructureException:
pass
else:
if productStructures is not None:
rxn = self.__createReaction(reactantStructures, productStructures, forward)
if rxn: rxnList.append(rxn)
mappings = self.__matchReactantToTemplate(molecule, template.reactants[0])
for map in mappings:
reactantStructures = [molecule]
try:
productStructures = self.__generateProductStructures(reactantStructures, [map], forward)
except ForbiddenStructureException:
pass
else:
if productStructures is not None:
rxn = self.__createReaction(reactantStructures, productStructures, forward)
if rxn: rxnList.append(rxn)

# Bimolecular reactants: A + B --> products
elif len(reactants) == 2 and len(template.reactants) == 2:
Expand All @@ -2532,11 +2527,30 @@ def __generateReactions(self, reactants, forward=True):
for moleculeB in moleculesB:

# Reactants stored as A + B
ismatchA, mappingsA = self.__matchReactantToTemplate(moleculeA, template.reactants[0])
ismatchB, mappingsB = self.__matchReactantToTemplate(moleculeB, template.reactants[1])
mappingsA = self.__matchReactantToTemplate(moleculeA, template.reactants[0])
mappingsB = self.__matchReactantToTemplate(moleculeB, template.reactants[1])

# Iterate over each pair of matches (A, B)
if ismatchA and ismatchB:
for mapA in mappingsA:
for mapB in mappingsB:
reactantStructures = [moleculeA, moleculeB]
try:
productStructures = self.__generateProductStructures(reactantStructures, [mapA, mapB], forward)
except ForbiddenStructureException:
pass
else:
if productStructures is not None:
rxn = self.__createReaction(reactantStructures, productStructures, forward)
if rxn: rxnList.append(rxn)

# Only check for swapped reactants if they are different
if reactants[0] is not reactants[1]:

# Reactants stored as B + A
mappingsA = self.__matchReactantToTemplate(moleculeA, template.reactants[1])
mappingsB = self.__matchReactantToTemplate(moleculeB, template.reactants[0])

# Iterate over each pair of matches (A, B)
for mapA in mappingsA:
for mapB in mappingsB:
reactantStructures = [moleculeA, moleculeB]
Expand All @@ -2549,27 +2563,6 @@ def __generateReactions(self, reactants, forward=True):
rxn = self.__createReaction(reactantStructures, productStructures, forward)
if rxn: rxnList.append(rxn)

# Only check for swapped reactants if they are different
if reactants[0] is not reactants[1]:

# Reactants stored as B + A
ismatchA, mappingsA = self.__matchReactantToTemplate(moleculeA, template.reactants[1])
ismatchB, mappingsB = self.__matchReactantToTemplate(moleculeB, template.reactants[0])

# Iterate over each pair of matches (A, B)
if ismatchA and ismatchB:
for mapA in mappingsA:
for mapB in mappingsB:
reactantStructures = [moleculeA, moleculeB]
try:
productStructures = self.__generateProductStructures(reactantStructures, [mapA, mapB], forward)
except ForbiddenStructureException:
pass
else:
if productStructures is not None:
rxn = self.__createReaction(reactantStructures, productStructures, forward)
if rxn: rxnList.append(rxn)

# Remove duplicates from the reaction list
index0 = 0
while index0 < len(rxnList):
Expand Down
2 changes: 1 addition & 1 deletion rmgpy/data/states.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@

from rmgpy.quantity import constants
from rmgpy.statmech import *
from rmgpy.group import Group
from rmgpy.molecule import Group

from base import *

Expand Down
37 changes: 12 additions & 25 deletions rmgpy/data/thermo.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@

from rmgpy.quantity import constants
from rmgpy.thermo import *
from rmgpy.molecule import Molecule, Atom, Bond
from rmgpy.group import Group
from rmgpy.molecule import Molecule, Atom, Bond, Group

################################################################################

Expand Down Expand Up @@ -607,12 +606,7 @@ def getThermoDataFromGroups(self, species):
:class:`Species` object `species` by estimation using the group
additivity values. If no group additivity values are loaded, a
:class:`DatabaseError` is raised.
"""
# Ensure molecules are using explicit hydrogens
implicitH = [mol.implicitHydrogens for mol in species.molecule]
for molecule in species.molecule:
molecule.makeHydrogensExplicit()

"""
thermo = []
for molecule in species.molecule:
molecule.clearLabeledAtoms()
Expand All @@ -624,11 +618,6 @@ def getThermoDataFromGroups(self, species):
indices = H298.argsort()

species.molecule = [species.molecule[ind] for ind in indices]
implicitH = [implicitH[ind] for ind in indices]

# Restore implicit hydrogens if necessary
for implicit, molecule in zip(implicitH, species.molecule):
if implicit: molecule.makeHydrogensImplicit()

return (thermo[indices[0]], None, None)

Expand All @@ -639,9 +628,6 @@ def estimateThermoViaGroupAdditivity(self, molecule):
additivity values. If no group additivity values are loaded, a
:class:`DatabaseError` is raised.
"""
implicitH = molecule.implicitHydrogens
molecule.makeHydrogensExplicit()

# For thermo estimation we need the atoms to already be sorted because we
# iterate over them; if the order changes during the iteration then we
# will probably not visit the right atoms, and so will get the thermo wrong
Expand All @@ -660,9 +646,9 @@ def estimateThermoViaGroupAdditivity(self, molecule):
for atom in saturatedStruct.atoms:
for i in range(atom.radicalElectrons):
H = Atom('H')
bond = Bond('S')
bond = Bond(atom, H, 'S')
saturatedStruct.addAtom(H)
saturatedStruct.addBond(atom, H, bond)
saturatedStruct.addBond(bond)
if atom not in added:
added[atom] = []
added[atom].append([H, bond])
Expand All @@ -689,7 +675,7 @@ def estimateThermoViaGroupAdditivity(self, molecule):

# Remove the added hydrogen atoms and bond and restore the radical
for H, bond in added[atom]:
saturatedStruct.removeBond(atom, H)
saturatedStruct.removeBond(bond)
saturatedStruct.removeAtom(H)
atom.incrementRadical()

Expand All @@ -706,7 +692,7 @@ def estimateThermoViaGroupAdditivity(self, molecule):
# Re-saturate
for H, bond in added[atom]:
saturatedStruct.addAtom(H)
saturatedStruct.addBond(atom, H, bond)
saturatedStruct.addBond(bond)
atom.decrementRadical()

# Subtract the enthalpy of the added hydrogens
Expand Down Expand Up @@ -746,14 +732,17 @@ def estimateThermoViaGroupAdditivity(self, molecule):
# each ring one time; this doesn't work yet
rings = molecule.getSmallestSetOfSmallestRings()
for ring in rings:

# Make a temporary structure containing only the atoms in the ring
# NB. if any of the ring corrections depend on ligands not in the ring, they will not be found!
ringStructure = Molecule()
for atom in ring: ringStructure.addAtom(atom)
newAtoms = dict()
for atom in ring:
newAtoms[atom] = atom.copy()
ringStructure.addAtom(newAtoms[atom]) # (addAtom deletes the atom's bonds)
for atom1 in ring:
for atom2 in ring:
if molecule.hasBond(atom1, atom2):
ringStructure.addBond(atom1, atom2, molecule.getBond(atom1, atom2))
ringStructure.addBond(Bond(newAtoms[atom1], newAtoms[atom2], atom1.bonds[atom2].order ))

# Get thermo correction for this ring
try:
Expand All @@ -768,8 +757,6 @@ def estimateThermoViaGroupAdditivity(self, molecule):
molecule.calculateSymmetryNumber()
thermoData.S298.value -= constants.R * math.log(molecule.symmetryNumber)

if implicitH: molecule.makeHydrogensImplicit()

return thermoData

def __addThermoData(self, thermoData1, thermoData2):
Expand Down
36 changes: 36 additions & 0 deletions rmgpy/molecule/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

################################################################################
#
# RMG - Reaction Mechanism Generator
#
# Copyright (c) 2002-2009 Prof. William H. Green ([email protected]) and the
# RMG Team ([email protected])
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the 'Software'),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
################################################################################

from .adjlist import *
from .atomtype import *
from .element import *
from .molecule import *
from .group import *
from .molecule_draw import drawMolecule
Loading