diff --git a/documentation/source/users/rmg/output.rst b/documentation/source/users/rmg/output.rst index 5b044f11e5..ce2b94214a 100755 --- a/documentation/source/users/rmg/output.rst +++ b/documentation/source/users/rmg/output.rst @@ -42,3 +42,4 @@ network. The Solver Folder ------------------ RMG currently includes a solver for isothermal batch reactors. This is in fact a critical part of the model enlargement algorithm. If you have included simulations in your input file, the solutions will be located in ``/solver``. You will probably only be interested in the files with the largest number tags. +Please note that up to and including RMG-Py version 2.3.0 these files showed mole fraction of each species at each step, but they now show amount (number of moles) of each species; you must divide by the sum if you wish to get a mole fraction. diff --git a/documentation/source/users/rmg/releaseNotes.rst b/documentation/source/users/rmg/releaseNotes.rst index 11a9bd6054..e97def6dac 100644 --- a/documentation/source/users/rmg/releaseNotes.rst +++ b/documentation/source/users/rmg/releaseNotes.rst @@ -4,6 +4,16 @@ Release Notes ************* + +RMG-Py Version 2.3.... +====================== +(pre-release development version) + +- Miscellaneous changes: + - Output files in 'solver' directory now show species amounts (numbers of moles) not mole fractions. + + + RMG-Py Version 2.3.0 ==================== Date: Dec 20, 2018 diff --git a/rmgpy/data/kinetics/database.py b/rmgpy/data/kinetics/database.py index 331a2dacf3..c4cfdedab5 100644 --- a/rmgpy/data/kinetics/database.py +++ b/rmgpy/data/kinetics/database.py @@ -248,7 +248,11 @@ def loadLibraries(self, path, libraries=None): label=os.path.dirname(library_file)[len(path)+1:] logging.info('Loading kinetics library {0} from {1}...'.format(label, library_file)) library = KineticsLibrary(label=label) - library.load(library_file, self.local_context, self.global_context) + try: + library.load(library_file, self.local_context, self.global_context) + except: + logging.error("Problem loading reaction library {0!r}".format(library_file)) + raise self.libraries[library.label] = library self.libraryOrder.append((library.label,'Reaction Library')) diff --git a/rmgpy/data/kinetics/family.py b/rmgpy/data/kinetics/family.py index 3827222436..0af8f7f3be 100644 --- a/rmgpy/data/kinetics/family.py +++ b/rmgpy/data/kinetics/family.py @@ -301,7 +301,9 @@ def __apply(self, struct, doForward, unique): elif (action[0] == 'FORM_BOND' and doForward) or (action[0] == 'BREAK_BOND' and not doForward): if struct.hasBond(atom1, atom2): raise InvalidActionError('Attempted to create an existing bond.') - bond = GroupBond(atom1, atom2, order=[1]) if pattern else Bond(atom1, atom2, order=1) + if info not in (1, 0): # Can only form single or vdW bonds + raise InvalidActionError('Attempted to create bond of type {:!r}'.format(info)) + bond = GroupBond(atom1, atom2, order=[info]) if pattern else Bond(atom1, atom2, order=info) struct.addBond(bond) atom1.applyAction(['FORM_BOND', label1, info, label2]) atom2.applyAction(['FORM_BOND', label1, info, label2]) @@ -1402,11 +1404,16 @@ def applyRecipe(self, reactantStructures, forward=True, unique=True): # reaction templates return None + # Remove vdW bonds + for struct in productStructures: + struct.removeVanDerWaalsBonds() + # Make sure we don't create a different net charge between reactants and products reactant_net_charge = product_net_charge = 0 for struc in reactantStructures: struc.update() reactant_net_charge += struc.getNetCharge() + for struct in productStructures: # If product structures are Molecule objects, update their atom types # If product structures are Group objects and the reaction is in certain families diff --git a/rmgpy/molecule/adjlist.py b/rmgpy/molecule/adjlist.py index b67cca2ca1..e98d87ce8f 100644 --- a/rmgpy/molecule/adjlist.py +++ b/rmgpy/molecule/adjlist.py @@ -35,6 +35,7 @@ import logging import warnings import re +import numpy as np from .molecule import Atom, Bond, getAtomType from .group import GroupAtom, GroupBond from .element import getElement, PeriodicSystem @@ -89,7 +90,8 @@ def check_partial_charge(atom): theoretical = valence - order - atom.radicalElectrons - 2*atom.lonePairs - if atom.charge != theoretical: + if not (-0.301 < atom.charge - theoretical < 0.301): + # It should be 0, but -0.1 is caused by a Hydrogen bond raise InvalidAdjacencyListError( ('Invalid valency for atom {symbol} ({type}) with {radicals} unpaired electrons, ' '{lonePairs} pairs of electrons, {charge} charge, and bonds [{bonds}].' diff --git a/rmgpy/molecule/atomtype.pxd b/rmgpy/molecule/atomtype.pxd index c01555f3c7..4ffc4d463a 100644 --- a/rmgpy/molecule/atomtype.pxd +++ b/rmgpy/molecule/atomtype.pxd @@ -46,6 +46,7 @@ cdef class AtomType: cdef public list oDouble cdef public list sDouble cdef public list triple + cdef public list quadruple cdef public list benzene cdef public list lonePairs cdef public list charge diff --git a/rmgpy/molecule/atomtype.py b/rmgpy/molecule/atomtype.py index 64f67cab26..a44c16b6e6 100644 --- a/rmgpy/molecule/atomtype.py +++ b/rmgpy/molecule/atomtype.py @@ -76,6 +76,7 @@ class AtomType: 'oDouble' ''list'' The number of double bonds to oxygen 'sDouble' ''list'' The number of double bonds to sulfur 'triple' ''list'' The total number of triple bonds on the atom + 'quadruple' ''list'' The total number of quadruple bonds on the atom 'benzene' ''list'' The total number of benzene bonds on the atom 'lonePairs' ''list'' The number of lone pairs on the atom 'charge' ''list'' The partial charge of the atom @@ -91,6 +92,7 @@ def __init__(self, label='', generic=None, specific=None, oDouble=None, sDouble=None, triple=None, + quadruple=None, benzene=None, lonePairs=None, charge=None): @@ -111,6 +113,7 @@ def __init__(self, label='', generic=None, specific=None, self.oDouble = oDouble or [] self.sDouble = sDouble or [] self.triple = triple or [] + self.quadruple = quadruple or [] self.benzene = benzene or [] self.lonePairs = lonePairs or [] self.charge = charge or [] @@ -140,6 +143,7 @@ def __reduce__(self): 'oDouble': self.oDouble, 'sDouble': self.sDouble, 'triple': self.triple, + 'quadruple': self.quadruple, 'benzene': self.benzene, 'lonePairs': self.lonePairs, 'charge': self.charge @@ -167,11 +171,13 @@ def __setstate__(self, d): self.oDouble = d['oDouble'] self.sDouble = d['sDouble'] self.triple = d['triple'] + self.quadruple = d['quadruple'] self.benzene = d['benzene'] self.lonePairs = d['lonePairs'] self.charge = d['charge'] - def setActions(self, incrementBond, decrementBond, formBond, breakBond, incrementRadical, decrementRadical, incrementLonePair, decrementLonePair): + def setActions(self, incrementBond, decrementBond, formBond, breakBond, incrementRadical, decrementRadical, + incrementLonePair, decrementLonePair): self.incrementBond = incrementBond self.decrementBond = decrementBond self.formBond = formBond @@ -206,6 +212,7 @@ def getFeatures(self): self.oDouble, self.sDouble, self.triple, + self.quadruple, self.benzene, self.lonePairs, self.charge] @@ -236,10 +243,10 @@ def getFeatures(self): 'R!H', 'Val4','Val5','Val6','Val7', 'He','Ne','Ar', - 'C','Ca','Cs','Csc','Cd','CO','CS','Cdd','Cdc','Ct','Cb','Cbf','C2s','C2sc','C2d','C2dc','C2tc', + 'C','Ca','Cs','Csc','Cd','CO','CS','Cdd','Cdc','Ct','Cb','Cbf','Cq','C2s','C2sc','C2d','C2dc','C2tc', 'N','N0sc','N1s','N1sc','N1dc','N3s','N3sc','N3d','N3t','N3b','N5sc','N5dc','N5ddc','N5dddc','N5tc','N5b','N5bd', 'O','Oa','O0sc','O2s','O2sc','O2d','O4sc','O4dc','O4tc','O4b', - 'Si','Sis','Sid','Sidd','Sit','SiO','Sib','Sibf', + 'Si','Sis','Sid','Sidd','Sit','SiO','Sib','Sibf','Siq', 'S','Sa','S0sc','S2s','S2sc','S2d','S2dc','S2tc','S4s','S4sc','S4d','S4dd','S4dc','S4b','S4t','S4tdc','S6s','S6sc','S6d','S6dd','S6ddd','S6dc','S6t','S6td','S6tt','S6tdc', 'Cl','Cl1s', 'I','I1s', @@ -248,18 +255,18 @@ def getFeatures(self): atomTypes['R!H'] = AtomType(label='R!H', generic=['R'], specific=[ 'Val4','Val5','Val6','Val7', 'He','Ne','Ar', - 'C','Ca','Cs','Csc','Cd','CO','CS','Cdd','Cdc','Ct','Cb','Cbf','C2s','C2sc','C2d','C2dc','C2tc', + 'C','Ca','Cs','Csc','Cd','CO','CS','Cdd','Cdc','Ct','Cb','Cbf','Cq','C2s','C2sc','C2d','C2dc','C2tc', 'N','N0sc','N1s','N1sc','N1dc','N3s','N3sc','N3d','N3t','N3b','N5sc','N5dc','N5ddc','N5dddc','N5tc','N5b','N5bd', 'O','Oa','O0sc','O2s','O2sc','O2d','O4sc','O4dc','O4tc','O4b', - 'Si','Sis','Sid','Sidd','Sit','SiO','Sib','Sibf', + 'Si','Sis','Sid','Sidd','Sit','SiO','Sib','Sibf','Siq', 'S','Sa','S0sc','S2s','S2sc','S2d','S2dc','S2tc','S4s','S4sc','S4d','S4dd','S4dc','S4b','S4t','S4tdc','S6s','S6sc','S6d','S6dd','S6ddd','S6dc','S6t','S6td','S6tt','S6tdc', 'Cl','Cl1s', 'I','I1s', 'F','F1s']) atomTypes['Val4'] = AtomType(label='Val4', generic=['R','R!H'], specific=[ - 'C','Ca','Cs','Csc','Cd','CO','CS','Cdd','Cdc','Ct','Cb','Cbf','C2s','C2sc','C2d','C2dc','C2tc', - 'Si','Sis','Sid','Sidd','Sit','SiO','Sib','Sibf']) + 'C','Ca','Cs','Csc','Cd','CO','CS','Cq','Cdd','Cdc','Ct','Cb','Cbf','C2s','C2sc','C2d','C2dc','C2tc', + 'Si','Sis','Sid','Sidd','Sit','SiO','Sib','Sibf','Siq']) atomTypes['Val5'] = AtomType(label='Val5', generic=['R','R!H'], specific=[ 'N','N0sc','N1s','N1sc','N1dc','N3s','N3sc','N3d','N3t','N3b','N5sc','N5dc','N5ddc','N5dddc','N5tc','N5b','N5bd']) @@ -279,241 +286,248 @@ def getFeatures(self): atomTypes['Ne' ] = AtomType('Ne', generic=['R','R!H'], specific=[]) atomTypes['Ar' ] = AtomType('Ar', generic=['R','R!H'], specific=[]) -atomTypes['C' ] = AtomType('C', generic=['R','R!H','Val4'], specific=['Ca','Cs','Csc','Cd','CO','CS','Cdd','Cdc','Ct','Cb','Cbf','C2s','C2sc','C2d','C2dc','C2tc'], - single=[], allDouble=[], rDouble=[], oDouble=[], sDouble=[], triple=[], benzene=[], lonePairs=[], charge=[]) +atomTypes['C' ] = AtomType('C', generic=['R','R!H','Val4'], specific=['Ca','Cs','Csc','Cd','CO','Cq','CS','Cdd','Cdc','Ct','Cb','Cbf','C2s','C2sc','C2d','C2dc','C2tc'], + single=[], allDouble=[], rDouble=[], oDouble=[], sDouble=[], triple=[], quadruple=[], benzene=[], lonePairs=[], charge=[]) # todo: double check to see if quadruple should be blank or 0 for all of these as well as being 1 for quadruple atomTypes['Ca' ] = AtomType('Ca', generic=['R','R!H','C','Val4'], specific=[], # (shared electrons = 4) - single=[0], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[0], lonePairs=[2], charge=[0]) + single=[0], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[], benzene=[0], lonePairs=[2], charge=[0]) # examples for Ca: atomic carbon (closed shell) atomTypes['Cs' ] = AtomType('Cs', generic=['R','R!H','C','Val4'], specific=[], # (shared electrons = 4-8) - single=[0,1,2,3,4], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], benzene=[0], lonePairs=[0], charge=[0]) + single=[0,1,2,3,4], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], quadruple=[], benzene=[0], lonePairs=[0], charge=[0]) # examples for Cs: C, CC, atomTypes['Csc' ] = AtomType('Csc', generic=['R','R!H','C','Val4'], specific=[], # (shared electrons = 3-6) - single=[0,1,2,3], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[0], lonePairs=[0], charge=[+1]) + single=[0,1,2,3], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[], benzene=[0], lonePairs=[0], charge=[+1]) # examples for Csc: C1=CCC([O-])[CH+]1, O[O+]=C[C+]C([O-])[O-] atomTypes['Cd' ] = AtomType('Cd', generic=['R','R!H','C','Val4'], specific=[], # (shared electrons = 6-8) - single=[0,1,2], allDouble=[1], rDouble=[1], oDouble=[0], sDouble=[0], triple=[0], benzene=[0], lonePairs=[0], charge=[0]) + single=[0,1,2], allDouble=[1], rDouble=[1], oDouble=[0], sDouble=[0], triple=[0], quadruple=[], benzene=[0], lonePairs=[0], charge=[0]) # examples for Cd: C=C, C=N atomTypes['Cdc' ] = AtomType('Cdc', generic=['R','R!H','C','Val4'], specific=[], # (shared electrons = 6) - single=[0,1], allDouble=[1], rDouble=[0,1], oDouble=[0,1], sDouble=[0,1], triple=[0], benzene=[0], lonePairs=[0], charge=[+1]) + single=[0,1], allDouble=[1], rDouble=[0,1], oDouble=[0,1], sDouble=[0,1], triple=[0], quadruple=[], benzene=[0], lonePairs=[0], charge=[+1]) # examples for Cdc: [CH+]=C=[CH-], [CH+]=N[O-] (one of the res structures of Fulminic acid) atomTypes['CO' ] = AtomType('CO', generic=['R','R!H','C','Val4'], specific=[], # (shared electrons = 6-8) - single=[0,1,2], allDouble=[1], rDouble=[0], oDouble=[1], sDouble=[0], triple=[0], benzene=[0], lonePairs=[0], charge=[0]) + single=[0,1,2], allDouble=[1], rDouble=[0], oDouble=[1], sDouble=[0], triple=[0], quadruple=[], benzene=[0], lonePairs=[0], charge=[0]) # examples for CO: C=O atomTypes['CS' ] = AtomType('CS', generic=['R','R!H','C','Val4'], specific=[], # (shared electrons = 6-8) - single=[0,1,2], allDouble=[1], rDouble=[0], oDouble=[0], sDouble=[1], triple=[0], benzene=[0], lonePairs=[0], charge=[0]) + single=[0,1,2], allDouble=[1], rDouble=[0], oDouble=[0], sDouble=[1], triple=[0], quadruple=[], benzene=[0], lonePairs=[0], charge=[0]) # examples for CS: C=S atomTypes['Cdd' ] = AtomType('Cdd', generic=['R','R!H','C','Val4'], specific=[], # (shared electrons = 8) - single=[0], allDouble=[2], rDouble=[0,1,2], oDouble=[0,1,2], sDouble=[0,1,2], triple=[0], benzene=[0], lonePairs=[0], charge=[0]) + single=[0], allDouble=[2], rDouble=[0,1,2], oDouble=[0,1,2], sDouble=[0,1,2], triple=[0], quadruple=[], benzene=[0], lonePairs=[0], charge=[0]) # examples for Cdd: O=C=O, C=C=C atomTypes['Ct' ] = AtomType('Ct', generic=['R','R!H','C','Val4'], specific=[], # (shared electrons = 7-8) - single=[0,1], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[1], benzene=[0], lonePairs=[0], charge=[0]) + single=[0,1], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[1], quadruple=[], benzene=[0], lonePairs=[0], charge=[0]) # examples for Ct: C#C, C#N atomTypes['Cb' ] = AtomType('Cb', generic=['R','R!H','C','Val4'], specific=[], - single=[0,1], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[1,2], lonePairs=[], charge=[]) + single=[0,1], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[], benzene=[1,2], lonePairs=[], charge=[]) # examples for Cb: benzene (C6H6) atomTypes['Cbf' ] = AtomType('Cbf', generic=['R','R!H','C','Val4'], specific=[], - single=[0], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[3], lonePairs=[], charge=[]) + single=[0], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[], benzene=[3], lonePairs=[], charge=[]) # examples for Cbf: Naphthalene +atomTypes['Cq' ] = AtomType('Cq', generic=['R','R!H','C','Val4'], specific=[], + single=[0], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], quadruple=[1], benzene=[0], lonePairs=[], charge=[]) +# examples for Cq: C2 atomTypes['C2s' ] = AtomType('C2s', generic=['R','R!H','C','Val4'], specific=[], # (shared electrons = 4-6) - single=[0,1,2], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[0], lonePairs=[1], charge=[0]) + single=[0,1,2], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[], benzene=[0], lonePairs=[1], charge=[0]) # examples for C2s: singlet[CH2] atomTypes['C2sc'] = AtomType('C2sc', generic=['R','R!H','C','Val4'], specific=[], # (shared electrons = 5-8) - single=[0,1,2,3], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[0], lonePairs=[1], charge=[-1]) + single=[0,1,2,3], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[], benzene=[0], lonePairs=[1], charge=[-1]) # examples for C2sc: [CH2-][N+]#N atomTypes['C2d' ] = AtomType('C2d', generic=['R','R!H','C','Val4'], specific=[], # (shared electrons = 6) - single=[0], allDouble=[1], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[0], lonePairs=[1], charge=[0]) + single=[0], allDouble=[1], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[], benzene=[0], lonePairs=[1], charge=[0]) # examples for C2d: singlet[C]=C atomTypes['C2dc'] = AtomType('C2dc', generic=['R','R!H','C','Val4'], specific=[], # (shared electrons = 7-8) - single=[0,1], allDouble=[1], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[0], lonePairs=[1], charge=[-1]) + single=[0,1], allDouble=[1], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[], benzene=[0], lonePairs=[1], charge=[-1]) # examples for C2dc: C=[C-][N+]#N, [CH-]=[N+]=O, [CH+]=C=[CH-] atomTypes['C2tc'] = AtomType('C2tc', generic=['R','R!H','C','Val4'], specific=[], # (shared electrons = 8) - single=[0], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[1], benzene=[0], lonePairs=[1], charge=[-1]) + single=[0], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[1], quadruple=[], benzene=[0], lonePairs=[1], charge=[-1]) # examples for C2tc: [C-]#[O+], H[N+]#[C-] atomTypes['N' ] = AtomType('N', generic=['R','R!H','Val5'], specific=['N0sc','N1s','N1sc','N1dc','N3s','N3sc','N3d','N3t','N3b','N5sc','N5dc','N5ddc','N5dddc','N5tc','N5b','N5bd'], - single=[], allDouble=[], rDouble=[], oDouble=[], sDouble=[], triple=[], benzene=[], lonePairs=[], charge=[]) + single=[], allDouble=[], rDouble=[], oDouble=[], sDouble=[], triple=[], quadruple=[], benzene=[], lonePairs=[], charge=[]) atomTypes['N0sc'] = AtomType('N0sc', generic=['R','R!H','N','Val5'], specific=[], # (shared electrons = 7-8) - single=[0,1], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], benzene=[0], lonePairs=[3], charge=[-2]) + single=[0,1], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], quadruple=[], benzene=[0], lonePairs=[3], charge=[-2]) # examples for N0sc: [NH+]#[N+][N-2] with adjList 1 N u0 p0 c+1 {2,S} {3,T}; 2 H u0 p0 c0 {1,S}; 3 N u0 p0 c+1 {1,T} {4,S}; 4 N u0 p3 c-2 {3,S} atomTypes['N1s' ] = AtomType('N1s', generic=['R','R!H','N','Val5'], specific=[], # (shared electrons = 5-6) - single=[0,1], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], benzene=[0], lonePairs=[2], charge=[0]) + single=[0,1], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], quadruple=[], benzene=[0], lonePairs=[2], charge=[0]) # examples for N1s: closed shell N-N, closed shell NH atomTypes['N1sc'] = AtomType('N1sc', generic=['R','R!H','N','Val5'], specific=[], # (shared electrons = 6-8) - single=[0,1,2], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[0], lonePairs=[2], charge=[-1]) + single=[0,1,2], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[], benzene=[0], lonePairs=[2], charge=[-1]) # examples for N1sc: [NH-][S+]=C, [NH-][N+]#C atomTypes['N1dc'] = AtomType('N1dc', generic=['R','R!H','N','Val5'], specific=[], # (shared electrons = 8) - single=[0], allDouble=[1], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[0], lonePairs=[2], charge=[-1]) + single=[0], allDouble=[1], rDouble=[], oDouble=[], sDouble=[], triple=[0],quadruple=[], benzene=[0], lonePairs=[2], charge=[-1]) # examples for N1dc: [N-]=[N+]=N terminal nitrogen on azide (two lone pairs), [N-]=[NH+], [N-]=[SH+] atomTypes['N3s' ] = AtomType('N3s', generic=['R','R!H','N','Val5'], specific=[], # (shared electrons = 5-8) - single=[0,1,2,3], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], benzene=[0], lonePairs=[1], charge=[0]) + single=[0,1,2,3], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], quadruple=[], benzene=[0], lonePairs=[1], charge=[0]) # examples for N3s: NH3, NH2, NH, N, C[NH]... atomTypes['N3sc'] = AtomType('N3sc', generic=['R','R!H','N','Val5'], specific=[], # (shared electrons = 4-6) - single=[0,1,2], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], benzene=[0], lonePairs=[1], charge=[+1]) + single=[0,1,2], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], quadruple=[], benzene=[0], lonePairs=[1], charge=[+1]) # examples for N3sc: !! N3sc should eventually be deleted, see #1206 atomTypes['N3d' ] = AtomType('N3d', generic=['R','R!H','N','Val5'], specific=[], # (shared electrons = 7-8) - single=[0,1], allDouble=[1], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[0], lonePairs=[1], charge=[0]) + single=[0,1], allDouble=[1], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[], benzene=[0], lonePairs=[1], charge=[0]) # examples for N3d: N=O, N=N, C=N, [O]N=O, [N]=O, [N]=C atomTypes['N3t' ] = AtomType('N3t', generic=['R','R!H','N','Val5'], specific=[], # (shared electrons = 8) - single=[0], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[1], benzene=[0], lonePairs=[1], charge=[0]) + single=[0], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[1], quadruple=[], benzene=[0], lonePairs=[1], charge=[0]) # examples for N3t: N2, N#C, N#[C], N#CC atomTypes['N3b' ] = AtomType('N3b', generic=['R','R!H','N','Val5'], specific=[], - single=[0], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], benzene=[2], lonePairs=[1], charge=[0]) + single=[0], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], quadruple=[], benzene=[2], lonePairs=[1], charge=[0]) # examples for N3b: Oxazole, Pyradine, Pyrazine, 1,3,5-Triazine, Benzimidazole, Purine atomTypes['N5sc'] = AtomType('N5sc', generic=['R','R!H','N','Val5'], specific=[], # (shared electrons = 4-8) single=[0,1,2,3,4], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], benzene=[0], lonePairs=[0], charge=[+1,+2]) # examples for N5sc: [NH3+][O-] atomTypes['N5dc'] = AtomType('N5dc', generic=['R','R!H','N','Val5'], specific=[], # (shared electrons = 6-8) - single=[0,1,2], allDouble=[1], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[0], lonePairs=[0], charge=[+1]) + single=[0,1,2], allDouble=[1], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[], benzene=[0], lonePairs=[0], charge=[+1]) # examples for N5dc: O[N+](=O)(O-) nitrate group, [N+](=O)(O)[O-], O=[N+][O-], [N+](=O)(O[N+](=O)[O-])[O-], C=[N+]=[SH-], [NH2+]=[SH-] atomTypes['N5ddc'] = AtomType('N5ddc', generic=['R','R!H','N','Val5'], specific=[], # (shared electrons = 8) - single=[0], allDouble=[2], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[0], lonePairs=[0], charge=[+1]) + single=[0], allDouble=[2], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[], benzene=[0], lonePairs=[0], charge=[+1]) # examples for N5ddc: N=[N+]=[N-] center nitrogen on azide, [N-]=[N+]=O, C=[N+]=[SH-] atomTypes['N5dddc'] = AtomType('N5dddc', generic=['R','R!H','N','Val5'], specific=[], # (shared electrons = 6) - single=[0], allDouble=[3], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[0], lonePairs=[0], charge=[-1]) + single=[0], allDouble=[3], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[], benzene=[0], lonePairs=[0], charge=[-1]) # examples for N5dddc: C=[N-](=C)=[NH2+] atomTypes['N5tc'] = AtomType('N5tc', generic=['R','R!H','N','Val5'], specific=[], # (shared electrons = 7-8) - single=[0,1], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[1], benzene=[0], lonePairs=[0], charge=[+1]) + single=[0,1], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[1], quadruple=[], benzene=[0], lonePairs=[0], charge=[+1]) # examples for N5tc: C[N+]#[C-] isocyano group, N#[N+][O-], [NH+]#[C-] (note that C- has p1 here), [N+]#[C-] (note that C- has p1 here), [O-][N+]#C (one of the res structures of Fulminic acid), C[N+]#[C-] (note that C- has p1 here) atomTypes['N5b' ] = AtomType('N5b', generic=['R','R!H','N','Val5'], specific=[], - single=[0,1], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], benzene=[2], lonePairs=[0], charge=[0,+1]) + single=[0,1], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], quadruple=[], benzene=[2], lonePairs=[0], charge=[0,+1]) # examples for N5b: Pyrrole, Indole, Benzimidazole, Purine; Note that this is the only N atomType with valence 5 which isn't necessarily charged. atomTypes['N5bd'] = AtomType('N5bd', generic=['R','R!H','N','Val5'], specific=[], - single=[0], allDouble=[1], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[2], lonePairs=[0], charge=[0]) + single=[0], allDouble=[1], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[], benzene=[2], lonePairs=[0], charge=[0]) # examples for N5bd: AdjList """1 N u0 p0 c0 {2,B} {6,B} {7,D} 2 C u0 p0 {1,B} {3,B} {8,S} 3 C u0 p0 {2,B} {4,B} {9,S} 4 C u0 p0 {3,B} {5,B} {10,S} 5 C u0 p0 {4,B} {6,B} {11,S} 6 N u0 p1 {1,B} {5,B} 7 O u0 p2 c0 {1,D} 8 H u0 p0 {2,S} 9 H u0 p0 {3,S} 10 H u0 p0 {4,S} 11 H u0 p0 {5,S}""" atomTypes['O' ] = AtomType('O', generic=['R','R!H','Val6'], specific=['Oa','O0sc','O2s','O2sc','O2d','O4sc','O4dc','O4tc','O4b'], - single=[], allDouble=[], rDouble=[], oDouble=[], sDouble=[], triple=[], benzene=[], lonePairs=[], charge=[]) + single=[], allDouble=[], rDouble=[], oDouble=[], sDouble=[], triple=[], quadruple=[], benzene=[], lonePairs=[], charge=[]) atomTypes['Oa' ] = AtomType('Oa', generic=['R','R!H','O','Val6'], specific=[], # (shared electrons = 6) - single=[0], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[0], lonePairs=[3], charge=[0]) + single=[0], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[0], benzene=[0], lonePairs=[3], charge=[0]) # examples for Oa: atomic oxygen (closed shell) atomTypes['O0sc'] = AtomType('O0sc', generic=['R','R!H','O','Val6'], specific=[], # (shared electrons = 8) - single=[0,1], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[0], lonePairs=[3], charge=[-1]) + single=[0,1], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[], benzene=[0], lonePairs=[3], charge=[-1]) # examples for O0sc: Nitric acid O[N+](=O)([O-]) atomTypes['O2s' ] = AtomType('O2s', generic=['R','R!H','O','Val6'], specific=[], # (shared electrons = 8) - single=[0,1,2], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[0], lonePairs=[2], charge=[0]) + single=[0,1,2], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[], benzene=[0], lonePairs=[2], charge=[0]) # examples for O2s: H2O, OH, CH3OH atomTypes['O2sc'] = AtomType('O2sc', generic=['R','R!H','O','Val6'], specific=[], # (shared electrons = 6) - single=[0,1], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[0], lonePairs=[2], charge=[+1]) + single=[0,1], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[], benzene=[0], lonePairs=[2], charge=[+1]) # examples for O2sc: C=[S-][O+] atomTypes['O2d' ] = AtomType('O2d', generic=['R','R!H','O','Val6'], specific=[], # (shared electrons = 8) - single=[0], allDouble=[1], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[0], lonePairs=[2], charge=[0]) + single=[0], allDouble=[1], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[], benzene=[0], lonePairs=[2], charge=[0]) # examples for O2d: CO2, CH2O atomTypes['O4sc'] = AtomType('O4sc', generic=['R','R!H','O','Val6'], specific=[], # (shared electrons = 5-8) - single=[0,1,2,3], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[0], lonePairs=[1], charge=[+1]) + single=[0,1,2,3], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[], benzene=[0], lonePairs=[1], charge=[+1]) # examples for O4sc: [O-][OH+]C atomTypes['O4dc'] = AtomType('O4dc', generic=['R','R!H','O','Val6'], specific=[], # (shared electrons = 7-8) - single=[0,1], allDouble=[1], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[0], lonePairs=[1], charge=[+1]) + single=[0,1], allDouble=[1], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[], benzene=[0], lonePairs=[1], charge=[+1]) # examples for O4dc: the positively charged O in ozone [O-][O+]=O atomTypes['O4tc'] = AtomType('O4tc', generic=['R','R!H','O','Val6'], specific=[], # (shared electrons = 8) - single=[0], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[1], benzene=[0], lonePairs=[1], charge=[+1]) + single=[0], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[1], quadruple=[], benzene=[0], lonePairs=[1], charge=[+1]) # examples for O4tc: [C-]#[O+] atomTypes['O4b' ] = AtomType('O4b', generic=['R','R!H','O','Val6'], specific=[], - single=[0], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], benzene=[2], lonePairs=[1], charge=[0]) + single=[0], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], quadruple=[], benzene=[2], lonePairs=[1], charge=[0]) # examples for S4b: Furane, Benzofurane, Benzo[c]thiophene, Oxazole... -atomTypes['Si' ] = AtomType('Si', generic=['R','R!H','Val4'], specific=['Sis','Sid','Sidd','Sit','SiO','Sib','Sibf'], - single=[], allDouble=[], rDouble=[], oDouble=[], sDouble=[], triple=[], benzene=[], lonePairs=[], charge=[]) +atomTypes['Ne' ] = AtomType('Ne', generic=['R','R!H'], specific=[]) +atomTypes['Si' ] = AtomType('Si', generic=['R','R!H','Val4'], specific=['Sis','Sid','Sidd','Sit','SiO','Sib','Sibf','Siq'], + single=[], allDouble=[], rDouble=[], oDouble=[], sDouble=[], triple=[], quadruple=[], benzene=[], lonePairs=[], charge=[]) atomTypes['Sis' ] = AtomType('Sis', generic=['R','R!H','Si','Val4'], specific=[], - single=[], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[0], lonePairs=[], charge=[]) + single=[], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[], benzene=[0], lonePairs=[], charge=[]) atomTypes['SiO' ] = AtomType('SiO', generic=['R','R!H','Si','Val4'], specific=[], - single=[], allDouble=[1], rDouble=[], oDouble=[1], sDouble=[], triple=[0], benzene=[0], lonePairs=[], charge=[]) + single=[], allDouble=[1], rDouble=[], oDouble=[1], sDouble=[], triple=[0], quadruple=[], benzene=[0], lonePairs=[], charge=[]) atomTypes['Sid' ] = AtomType('Sid', generic=['R','R!H','Si','Val4'], specific=[], - single=[], allDouble=[1], rDouble=[], oDouble=[0], sDouble=[], triple=[0], benzene=[0], lonePairs=[], charge=[]) + single=[], allDouble=[1], rDouble=[], oDouble=[0], sDouble=[], triple=[0], quadruple=[], benzene=[0], lonePairs=[], charge=[]) atomTypes['Sidd'] = AtomType('Sidd', generic=['R','R!H','Si','Val4'], specific=[], - single=[], allDouble=[2], rDouble=[0,1,2], oDouble=[0,1,2], sDouble=[0,1,2], triple=[0], benzene=[0], lonePairs=[], charge=[]) + single=[], allDouble=[2], rDouble=[0,1,2], oDouble=[0,1,2], sDouble=[0,1,2], triple=[0], quadruple=[], benzene=[0], lonePairs=[], charge=[]) atomTypes['Sit' ] = AtomType('Sit', generic=['R','R!H','Si','Val4'], specific=[], - single=[], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[1], benzene=[0], lonePairs=[], charge=[]) + single=[], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[1], quadruple=[], benzene=[0], lonePairs=[], charge=[]) atomTypes['Sib' ] = AtomType('Sib', generic=['R','R!H','Si','Val4'], specific=[], - single=[], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[2], lonePairs=[], charge=[]) + single=[], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[], benzene=[2], lonePairs=[], charge=[]) atomTypes['Sibf'] = AtomType('Sibf', generic=['R','R!H','Si','Val4'], specific=[], - single=[], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[3], lonePairs=[], charge=[]) + single=[], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[], benzene=[3], lonePairs=[], charge=[]) +atomTypes['Siq' ] = AtomType('Siq', generic=['R','R!H','Si','Val4'], specific=[], + single=[0], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], quadruple=[1], benzene=[0], lonePairs=[], charge=[]) atomTypes['S' ] = AtomType('S', generic=['R','R!H','Val6'], specific=['Sa','S0sc','S2s','S2sc','S2d','S2dc','S2tc','S4s','S4sc','S4d','S4dd','S4dc','S4b','S4t','S4tdc','S6s','S6sc','S6d','S6dd','S6ddd','S6dc','S6t','S6td','S6tt','S6tdc'], - single=[], allDouble=[], rDouble=[], oDouble=[], sDouble=[], triple=[], benzene=[], lonePairs=[], charge=[]) + single=[], allDouble=[], rDouble=[], oDouble=[], sDouble=[], triple=[], quadruple=[], benzene=[], lonePairs=[], charge=[]) atomTypes['Sa' ] = AtomType('Sa', generic=['R','R!H','S','Val6'], specific=[], # (shared electrons = 6) - single=[0], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], benzene=[0], lonePairs=[3], charge=[0]) + single=[0], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], quadruple=[], benzene=[0], lonePairs=[3], charge=[0]) # examples for Sa: atomic sulfur (closed shell) atomTypes['S0sc'] = AtomType('S0sc', generic=['R','R!H','S','Val6'], specific=[], # (shared electrons = 7-8) - single=[0,1], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[0], lonePairs=[3], charge=[-1]) + single=[0,1], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[], benzene=[0], lonePairs=[3], charge=[-1]) # examples for S0sc: [S-][S+]=S atomTypes['S2s' ] = AtomType('S2s', generic=['R','R!H','S','Val6'], specific=[], # (shared electrons = 6-8) - single=[0,1,2], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], benzene=[0], lonePairs=[2], charge=[0]) + single=[0,1,2], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], quadruple=[], benzene=[0], lonePairs=[2], charge=[0]) # examples for S2s: [S], [SH], S {H2S}, [S][S], SS {H2S2}, SSC, CSSC, SO {HSOH}... atomTypes['S2sc'] = AtomType('S2sc', generic=['R','R!H','S','Val6'], specific=[], # (shared electrons = 7-10) - single=[0,1,2,3], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], benzene=[0], lonePairs=[2], charge=[-1,+1]) + single=[0,1,2,3], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], quadruple=[], benzene=[0], lonePairs=[2], charge=[-1,+1]) # examples for S2sc: N#[N+][S-](O)O atomTypes['S2d' ] = AtomType('S2d', generic=['R','R!H','S','Val6'], specific=[], # (shared electrons = 8) - single=[0], allDouble=[1], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[0], lonePairs=[2], charge=[0]) + single=[0], allDouble=[1], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[], benzene=[0], lonePairs=[2], charge=[0]) # examples for S2d: S=S, C=S, S=O, S=N, S=C=S, S=C=O, S=C=S... atomTypes['S2dc'] = AtomType('S2dc', generic=['R','R!H','S','Val6'], specific=[], - single=[0,1], allDouble=[1,2], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[0], lonePairs=[2], charge=[-1]) + single=[0,1], allDouble=[1,2], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[], benzene=[0], lonePairs=[2], charge=[-1]) # *Composite atomType; examples for S2dc: [SH-]=[N+] atomTypes['S2tc'] = AtomType('S2tc', generic=['R','R!H','S','Val6'], specific=[], # (shared electrons = 10) - single=[0], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[1], benzene=[0], lonePairs=[2], charge=[-1]) + single=[0], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[1], quadruple=[], benzene=[0], lonePairs=[2], charge=[-1]) # examples for S2tc: [S-]#[NH+] atomTypes['S4s' ] = AtomType('S4s', generic=['R','R!H','S','Val6'], specific=[], # (shared electrons = 6-10) - single=[0,1,2,3,4], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], benzene=[0], lonePairs=[1], charge=[0]) + single=[0,1,2,3,4], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], quadruple=[], benzene=[0], lonePairs=[1], charge=[0]) # examples for S4s: H4S, SH3CH3... atomTypes['S4sc'] = AtomType('S4sc', generic=['R','R!H','S','Val6'], specific=[], # (shared electrons = 5-8) - single=[0,1,2,3,4,5], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], benzene=[0], lonePairs=[1], charge=[-1,+1]) + single=[0,1,2,3,4,5], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], quadruple=[], benzene=[0], lonePairs=[1], charge=[-1,+1]) # examples for S4sc: CS[S+]([O-])C, O[SH..-][N+]#N atomTypes['S4d' ] = AtomType('S4d', generic=['R','R!H','S','Val6'], specific=[], # (shared electrons = 8-10) - single=[0,1,2], allDouble=[1], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[0], lonePairs=[1], charge=[0]) + single=[0,1,2], allDouble=[1], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[], benzene=[0], lonePairs=[1], charge=[0]) # examples for S4d: O=S(O)O {Sulfurous acid} atomTypes['S4dd'] = AtomType('S4dd', generic=['R','R!H','S','Val6'], specific=[], # (shared electrons = 10) - single=[0], allDouble=[2], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[0], lonePairs=[1], charge=[0]) + single=[0], allDouble=[2], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[], benzene=[0], lonePairs=[1], charge=[0]) # examples for S4dd: O=S=O atomTypes['S4dc'] = AtomType('S4dc', generic=['R','R!H','S','Val6'], specific=[], - single=[0,1,2,3,4,5], allDouble=[1,2], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[0], lonePairs=[1], charge=[-1,+1]) + single=[0,1,2,3,4,5], allDouble=[1,2], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[], benzene=[0], lonePairs=[1], charge=[-1,+1]) # *Composite atomType; examples for S4dc: [CH2-][S+]=C {where the [CH2-] has a lone pair}, [O+][S-](=O)=O, [O-][S+]=C, [NH-][S+]=C {where the [NH-] has two lone pairs}, [O-][S+]=O atomTypes['S4b' ] = AtomType('S4b', generic=['R','R!H','S','Val6'], specific=[], - single=[0], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], benzene=[2], lonePairs=[1], charge=[0]) + single=[0], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], quadruple=[], benzene=[2], lonePairs=[1], charge=[0]) # examples for S4b: Thiophene, Benzothiophene, Benzo[c]thiophene, Thiazole, Benzothiazole... atomTypes['S4t' ] = AtomType('S4t', generic=['R','R!H','S','Val6'], specific=[], # (shared electrons = 10) - single=[0,1], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[1], benzene=[0], lonePairs=[1], charge=[0]) + single=[0,1], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[1], quadruple=[], benzene=[0], lonePairs=[1], charge=[0]) # examples for S4t: C#S, C#SO, C#[S] atomTypes['S4tdc'] = AtomType('S4tdc',generic=['R','R!H','S','Val6'], specific=[], - single=[0,1,2], allDouble=[0,1,2], rDouble=[], oDouble=[], sDouble=[], triple=[1,2], benzene=[0], lonePairs=[1], charge=[-1,+1]) + single=[0,1,2], allDouble=[0,1,2], rDouble=[], oDouble=[], sDouble=[], triple=[1,2], quadruple=[], benzene=[0], lonePairs=[1], charge=[-1,+1]) # *Composite atomType; examples for S4tdc: [C-]#[S+] atomTypes['S6s' ] = AtomType('S6s', generic=['R','R!H','S','Val6'], specific=[], # (shared electrons = 6-12) - single=[0,1,2,3,4,5,6], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], benzene=[0], lonePairs=[0], charge=[0]) + single=[0,1,2,3,4,5,6], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], quadruple=[0], benzene=[0], lonePairs=[0], charge=[0]) # examples for S6s: H6S, F6S atomTypes['S6sc'] = AtomType('S6sc', generic=['R','R!H','S','Val6'], specific=[], # (shared electrons = 7-14) - single=[0,1,2,3,4,5,6,7], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], benzene=[0], lonePairs=[0], charge=[-1,+1,+2]) + single=[0,1,2,3,4,5,6,7], allDouble=[0], rDouble=[0], oDouble=[0], sDouble=[0], triple=[0], quadruple=[0], benzene=[0], lonePairs=[0], charge=[-1,+1,+2]) # examples for S6sc: [O-][S+2](O)(O)[O-]CS(=O) atomTypes['S6d' ] = AtomType('S6d', generic=['R','R!H','S','Val6'], specific=[], # (shared electrons = 8-12) - single=[0,1,2,3,4], allDouble=[1], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[0], lonePairs=[0], charge=[0]) + single=[0,1,2,3,4], allDouble=[1], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[], benzene=[0], lonePairs=[0], charge=[0]) # examples for S6d: [SH4]=O, SF4=O, [SH4]=C, C[SH3]=C... atomTypes['S6dd'] = AtomType('S6dd', generic=['R','R!H','S','Val6'], specific=[], # (shared electrons = 10-12) - single=[0,1,2], allDouble=[2], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[0], lonePairs=[0], charge=[0]) + single=[0,1,2], allDouble=[2], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[], benzene=[0], lonePairs=[0], charge=[0]) # examples for S6dd: S(=O)(=O)(O)O {H2SO4, Sulfuric acid}, Perfluorooctanesulfonic acid, Pyrosulfuric acid, Thiosulfuric acid {middle S}, OS(=O)(=O)OOS(=O)(=O)O atomTypes['S6ddd'] = AtomType('S6ddd', generic=['R','R!H','S','Val6'], specific=[], # (shared electrons = 12) - single=[0], allDouble=[3], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[0], lonePairs=[0], charge=[0]) + single=[0], allDouble=[3], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[], benzene=[0], lonePairs=[0], charge=[0]) # examples for S6ddd: O=S(=O)(=O) atomTypes['S6dc'] = AtomType('S6dc', generic=['R','R!H','S','Val6'], specific=[], - single=[0,1,2,3,4,5], allDouble=[1,2,3], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[0], lonePairs=[0], charge=[-1,+1,+2]) + single=[0,1,2,3,4,5], allDouble=[1,2,3], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[0], benzene=[0], lonePairs=[0], charge=[-1,+1,+2]) # *Composite atomType; examples for S6dc: O=[S+2]([O-])[O-], [CH-]=[SH3+], [CH-]=[SH2+]O, [CH-][SH2+], O=[S+](=O)[O-], [OH+]=[S-](=O)=O atomTypes['S6t' ] = AtomType('S6t', generic=['R','R!H','S','Val6'], specific=[], # (shared electrons = 9-12) - single=[0,1,2,3], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[1], benzene=[0], lonePairs=[0], charge=[0]) + single=[0,1,2,3], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[1], quadruple=[], benzene=[0], lonePairs=[0], charge=[0]) # examples for S6t: H3S#N atomTypes['S6td'] = AtomType('S6td', generic=['R','R!H','S','Val6'], specific=[], # (shared electrons = 11-12) - single=[0,1], allDouble=[1], rDouble=[], oDouble=[], sDouble=[], triple=[1], benzene=[0], lonePairs=[0], charge=[0]) + single=[0,1], allDouble=[1], rDouble=[], oDouble=[], sDouble=[], triple=[1], quadruple=[], benzene=[0], lonePairs=[0], charge=[0]) # examples for S6td: HS(=O)#N atomTypes['S6tt'] = AtomType('S6tt', generic=['R','R!H','S','Val6'], specific=[], # (shared electrons = 12) - single=[0], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[2], benzene=[0], lonePairs=[0], charge=[0]) + single=[0], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[2], quadruple=[], benzene=[0], lonePairs=[0], charge=[0]) # examples for S6tt: N#S#N atomTypes['S6tdc'] = AtomType('S6tdc',generic=['R','R!H','S','Val6'], specific=[], - single=[0,1,2,3,4], allDouble=[0,1,2], rDouble=[], oDouble=[], sDouble=[], triple=[1,2], benzene=[0], lonePairs=[0], charge=[-1,+1]) + single=[0,1,2,3,4], allDouble=[0,1,2], rDouble=[], oDouble=[], sDouble=[], triple=[1,2], quadruple=[], benzene=[0], lonePairs=[0], charge=[-1,+1]) # *Composite atomType; examples for S6tdc: [SH2+]#[C-], [N-]=[S+]#N atomTypes['Cl' ] = AtomType('Cl', generic=['R','R!H','Val7'], specific=['Cl1s']) atomTypes['Cl1s'] = AtomType('Cl1s', generic=['R','R!H','Cl','Val7'], specific=[], - single=[0,1], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[0], lonePairs=[3], charge=[0]) + single=[0,1], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[0], benzene=[0], lonePairs=[3], charge=[0]) # examples for Cl1s: HCl, [Cl] +atomTypes['Ar' ] = AtomType('Ar', generic=['R','R!H'], specific=[]) atomTypes['I' ] = AtomType('I', generic=['R','R!H','Val7'], specific=['I1s']) atomTypes['I1s'] = AtomType('I1s', generic=['R','R!H','I','Val7'], specific=[], - single=[0,1], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], benzene=[0], lonePairs=[3], charge=[0]) + single=[0,1], allDouble=[0], rDouble=[], oDouble=[], sDouble=[], triple=[0], quadruple=[0], benzene=[0], lonePairs=[3], charge=[0]) # examples for I1s: HI, [I], IO, CH3I, I2 atomTypes['F' ] = AtomType('F', generic=['R','R!H','Val7'], specific=['F1s']) @@ -543,7 +557,7 @@ def getFeatures(self): atomTypes['CO' ].setActions(incrementBond=['Cdd','C2tc'], decrementBond=['Cs'], formBond=['CO','Cdc'], breakBond=['CO'], incrementRadical=['CO'], decrementRadical=['CO'], incrementLonePair=['C2d'], decrementLonePair=[]) atomTypes['CS' ].setActions(incrementBond=['Cdd','C2tc'], decrementBond=['Cs'], formBond=['CS','Cdc'], breakBond=['CS'], incrementRadical=['CS'], decrementRadical=['CS'], incrementLonePair=['C2d'], decrementLonePair=[]) atomTypes['Cdd' ].setActions(incrementBond=[], decrementBond=['Cd','CO','CS'], formBond=[], breakBond=[], incrementRadical=[], decrementRadical=[], incrementLonePair=[], decrementLonePair=[]) -atomTypes['Ct' ].setActions(incrementBond=[], decrementBond=['Cd','CO','CS'], formBond=['Ct'], breakBond=['Ct'], incrementRadical=['Ct'], decrementRadical=['Ct'], incrementLonePair=['C2tc'],decrementLonePair=[]) +atomTypes['Ct' ].setActions(incrementBond=['Cq'], decrementBond=['Cd','CO','CS'], formBond=['Ct'], breakBond=['Ct'], incrementRadical=['Ct'], decrementRadical=['Ct'], incrementLonePair=['C2tc'],decrementLonePair=[]) atomTypes['Cb' ].setActions(incrementBond=['Cbf'], decrementBond=[], formBond=['Cb'], breakBond=['Cb'], incrementRadical=['Cb'], decrementRadical=['Cb'], incrementLonePair=[], decrementLonePair=[]) atomTypes['Cbf' ].setActions(incrementBond=[], decrementBond=['Cb'], formBond=[], breakBond=['Cb'], incrementRadical=[], decrementRadical=[], incrementLonePair=[], decrementLonePair=[]) atomTypes['C2s' ].setActions(incrementBond=['C2d'], decrementBond=[], formBond=['C2s'], breakBond=['C2s'], incrementRadical=['C2s'], decrementRadical=['C2s'], incrementLonePair=['Ca'], decrementLonePair=['Cs']) @@ -551,6 +565,7 @@ def getFeatures(self): atomTypes['C2d' ].setActions(incrementBond=['C2tc'], decrementBond=['C2s'], formBond=['C2dc'], breakBond=[], incrementRadical=[], decrementRadical=[], incrementLonePair=[], decrementLonePair=['Cd','CO','CS']) atomTypes['C2dc'].setActions(incrementBond=[], decrementBond=['C2sc'], formBond=[], breakBond=['C2d'], incrementRadical=[], decrementRadical=[], incrementLonePair=[], decrementLonePair=['Cdc']) atomTypes['C2tc'].setActions(incrementBond=[], decrementBond=['C2d'], formBond=[], breakBond=[], incrementRadical=[], decrementRadical=[], incrementLonePair=[], decrementLonePair=['Ct']) +atomTypes['Cq' ].setActions(incrementBond=[], decrementBond=['Ct'], formBond=[], breakBond=[], incrementRadical=[], decrementRadical=[], incrementLonePair=[], decrementLonePair=[]) atomTypes['N' ].setActions(incrementBond=['N'], decrementBond=['N'], formBond=['N'], breakBond=['N'], incrementRadical=['N'], decrementRadical=['N'], incrementLonePair=['N'], decrementLonePair=['N']) atomTypes['N0sc'].setActions(incrementBond=[], decrementBond=[], formBond=['N0sc'], breakBond=['N0sc'], incrementRadical=['N0sc'], decrementRadical=['N0sc'], incrementLonePair=[], decrementLonePair=['N1s','N1sc']) @@ -581,14 +596,17 @@ def getFeatures(self): atomTypes['O4tc'].setActions(incrementBond=[], decrementBond=['O4dc'], formBond=[], breakBond=[], incrementRadical=[], decrementRadical=[], incrementLonePair=[], decrementLonePair=[]) atomTypes['O4b' ].setActions(incrementBond=[], decrementBond=[], formBond=[], breakBond=[], incrementRadical=[], decrementRadical=[], incrementLonePair=[], decrementLonePair=[]) +atomTypes['Ne' ].setActions(incrementBond=[], decrementBond=[], formBond=[], breakBond=[], incrementRadical=['Ne'], decrementRadical=['Ne'], incrementLonePair=[], decrementLonePair=[]) + atomTypes['Si' ].setActions(incrementBond=['Si'], decrementBond=['Si'], formBond=['Si'], breakBond=['Si'], incrementRadical=['Si'], decrementRadical=['Si'], incrementLonePair=[], decrementLonePair=[]) atomTypes['Sis' ].setActions(incrementBond=['Sid','SiO'], decrementBond=[], formBond=['Sis'], breakBond=['Sis'], incrementRadical=['Sis'], decrementRadical=['Sis'], incrementLonePair=[], decrementLonePair=[]) atomTypes['Sid' ].setActions(incrementBond=['Sidd','Sit'], decrementBond=['Sis'], formBond=['Sid'], breakBond=['Sid'], incrementRadical=['Sid'], decrementRadical=['Sid'], incrementLonePair=[], decrementLonePair=[]) atomTypes['Sidd'].setActions(incrementBond=[], decrementBond=['Sid','SiO'], formBond=[], breakBond=[], incrementRadical=[], decrementRadical=[], incrementLonePair=[], decrementLonePair=[]) -atomTypes['Sit' ].setActions(incrementBond=[], decrementBond=['Sid'], formBond=['Sit'], breakBond=['Sit'], incrementRadical=['Sit'], decrementRadical=['Sit'], incrementLonePair=[], decrementLonePair=[]) +atomTypes['Sit' ].setActions(incrementBond=['Siq'], decrementBond=['Sid'], formBond=['Sit'], breakBond=['Sit'], incrementRadical=['Sit'], decrementRadical=['Sit'], incrementLonePair=[], decrementLonePair=[]) atomTypes['SiO' ].setActions(incrementBond=['Sidd'], decrementBond=['Sis'], formBond=['SiO'], breakBond=['SiO'], incrementRadical=['SiO'], decrementRadical=['SiO'], incrementLonePair=[], decrementLonePair=[]) atomTypes['Sib' ].setActions(incrementBond=[], decrementBond=[], formBond=['Sib'], breakBond=['Sib'], incrementRadical=['Sib'], decrementRadical=['Sib'], incrementLonePair=[], decrementLonePair=[]) atomTypes['Sibf'].setActions(incrementBond=[], decrementBond=[], formBond=[], breakBond=[], incrementRadical=[], decrementRadical=[], incrementLonePair=[], decrementLonePair=[]) +atomTypes['Siq' ].setActions(incrementBond=[], decrementBond=['Sit'], formBond=[], breakBond=[], incrementRadical=[], decrementRadical=[], incrementLonePair=[], decrementLonePair=[]) atomTypes['S' ].setActions(incrementBond=['S'], decrementBond=['S'], formBond=['S'], breakBond=['S'], incrementRadical=['S'], decrementRadical=['S'], incrementLonePair=['S'], decrementLonePair=['S']) atomTypes['S0sc'].setActions(incrementBond=['S0sc'], decrementBond=['S0sc'], formBond=['S0sc'], breakBond=['Sa','S0sc'], incrementRadical=['S0sc'], decrementRadical=['S0sc'], incrementLonePair=[], decrementLonePair=['S2s','S2sc','S2dc','S2tc']) @@ -633,8 +651,9 @@ def getFeatures(self): for atomType in atomTypes.values(): for items in [atomType.generic, atomType.specific, - atomType.incrementBond, atomType.decrementBond, atomType.formBond, - atomType.breakBond, atomType.incrementRadical, atomType.decrementRadical, atomType.incrementLonePair, atomType.decrementLonePair]: + atomType.incrementBond, atomType.decrementBond, atomType.formBond, + atomType.breakBond, atomType.incrementRadical, atomType.decrementRadical, atomType.incrementLonePair, + atomType.decrementLonePair]: for index in range(len(items)): items[index] = atomTypes[items[index]] @@ -644,15 +663,20 @@ def getFeatures(atom, bonds): Returns a list of features needed to determine atomType for :class:'Atom' or :class:'GroupAtom' object 'atom and with local bond structure `bonds`, a ``dict`` containing atom-bond pairs. - """ cython.declare(single=cython.int, allDouble=cython.int, rDouble=cython.int, sDouble=cython.int, oDouble=cython.int, triple=cython.int, - benzene=cython.int) + benzene=cython.int, quadruple=cython.int) cython.declare(features=cython.list) # Count numbers of each higher-order bond type - single = 0; rDouble = 0; oDouble = 0; sDouble = 0; triple = 0; benzene = 0 + single = 0; + rDouble = 0; + oDouble = 0; + sDouble = 0; + triple = 0; + benzene = 0; + quadruple = 0 for atom2, bond12 in bonds.iteritems(): if bond12.isSingle(): single += 1 @@ -664,12 +688,18 @@ def getFeatures(atom, bonds): else: # rDouble is for double bonds NOT to oxygen or Sulfur rDouble += 1 - elif bond12.isTriple(): triple += 1 - elif bond12.isBenzene(): benzene += 1 + elif bond12.isTriple(): + triple += 1 + elif bond12.isBenzene(): + benzene += 1 + elif bond12.isQuadruple(): + quadruple += 1 # allDouble is for all double bonds, to anything allDouble = rDouble + oDouble + sDouble - features = [single, allDouble, rDouble, oDouble, sDouble, triple, benzene, atom.lonePairs, atom.charge] + # Warning: some parts of code assume this list matches the list returned by countBonds() + # possibly the two methods could be merged or one could call the other. + features = [single, allDouble, rDouble, oDouble, sDouble, triple, quadruple, benzene, atom.lonePairs, atom.charge] return features @@ -704,11 +734,11 @@ def getAtomType(atom, bonds): oDouble = molFeatureList[3] sDouble = molFeatureList[4] triple = molFeatureList[5] - benzene = molFeatureList[6] - lonePairs = molFeatureList[7] - charge = molFeatureList[8] + quadruple = molFeatureList[6] + benzene = molFeatureList[7] + lonePairs = molFeatureList[8] + charge = molFeatureList[9] raise AtomTypeError( 'Unable to determine atom type for atom {0}, which has {1:d} single bonds, {2:d} double bonds to C, {3:d} double bonds to O, {4:d} double bonds to S, {5:d} triple bonds, {6:d} benzene bonds, {7:d} lone pairs, and {8:d} charge.'.format( - atom, single, rDouble, oDouble, sDouble, triple, benzene, lonePairs, charge)) - + atom, single, rDouble, oDouble, sDouble, triple, quadruple, benzene, lonePairs, charge)) diff --git a/rmgpy/molecule/atomtypeTest.py b/rmgpy/molecule/atomtypeTest.py index 2e9f6d2703..20bd6e4cd2 100644 --- a/rmgpy/molecule/atomtypeTest.py +++ b/rmgpy/molecule/atomtypeTest.py @@ -523,7 +523,7 @@ def testCarbonTypes(self): self.assertEqual(self.atomType(self.mol59, 0), 'C2dc') self.assertEqual(self.atomType(self.mol60, 2), 'C2dc') self.assertEqual(self.atomType(self.mol20, 0), 'C2tc') - self.assertEqual(self.atomType(self.mol29, 0), 'C2tc') + self.assertEqual(self.atomType(self.mol29, 0), 'C2tc') # todo: add in a ciq unit test? def testNitrogenTypes(self): """ @@ -571,7 +571,7 @@ def testSiliconTypes(self): self.assertEqual(self.atomType(self.mol4, 1), 'SiO') self.assertEqual(self.atomType(self.mol4, 5), 'Sid') self.assertEqual(self.atomType(self.mol4, 4), 'Sidd') - self.assertEqual(self.atomType(self.mol4, 7), 'Sit') + self.assertEqual(self.atomType(self.mol4, 7), 'Sit') #todo: add in Siq unit test? def testSulfurTypes(self): """ diff --git a/rmgpy/molecule/atomtypedatabase.py b/rmgpy/molecule/atomtypedatabase.py index 021c9755df..bea1cc2cbe 100644 --- a/rmgpy/molecule/atomtypedatabase.py +++ b/rmgpy/molecule/atomtypedatabase.py @@ -34,11 +34,12 @@ """ class AbstractAtomType(object): - def __init__(self, element = None, label=None, double=-1, triple=-1, benzene=-1, lp=-1, chrg=-1): + def __init__(self, element = None, label=None, double=-1, triple=-1, quadruple=-1, benzene=-1, lp=-1, chrg=-1): self.element = element self.label = label self.double = double self.triple = triple + self.quadruple = quadruple self.benzene = benzene self.lp = lp self.chrg = chrg @@ -61,37 +62,43 @@ def __init__(self, *args, **kwargs): class Xs(AbstractAtomType): def __init__(self, *args, **kwargs): super(self.__class__, self).__init__(*args, **kwargs) - self.double, self.triple, self.benzene = 0, 0, 0 + self.double, self.triple, self.benzene, self.quadruple = 0, 0, 0, 0 self.label = 's' class Xd(AbstractAtomType): def __init__(self, *args, **kwargs): super(self.__class__, self).__init__(*args, **kwargs) - self.double, self.triple, self.benzene = 1, 0, 0 + self.double, self.triple, self.benzene, self.quadruple = 1, 0, 0, 0 self.label = 'd' class Xdd(AbstractAtomType): def __init__(self, *args, **kwargs): super(self.__class__, self).__init__(*args, **kwargs) - self.double, self.triple, self.benzene = 2, 0, 0 + self.double, self.triple, self.benzene, self.quadruple = 2, 0, 0, 0 self.label = 'dd' class Xt(AbstractAtomType): def __init__(self, *args, **kwargs): super(self.__class__, self).__init__(*args, **kwargs) - self.double, self.triple, self.benzene = 0, 1, 0 + self.double, self.triple, self.benzene, self.quadruple = 0, 1, 0, 0 self.label = 't' +class Xq(AbstractAtomType): + def __init__(self, *args, **kwargs): + super(self.__class__, self).__init__(*args, **kwargs) + self.double, self.triple, self.benzene, self.quadruple = 0, 0, 0, 1 + self.label = 'q' + class Xb(AbstractAtomType): def __init__(self, *args, **kwargs): super(self.__class__, self).__init__(*args, **kwargs) - self.double, self.triple, self.benzene = 0, 0, 2 + self.double, self.triple, self.benzene, self.quadruple = 0, 0, 2, 0 self.label = 'b' class Xbf(AbstractAtomType): def __init__(self, *args, **kwargs): super(self.__class__, self).__init__(*args, **kwargs) - self.double, self.triple, self.benzene = 0, 0, 3 + self.double, self.triple, self.benzene, self.quadruple = 0, 0, 3, 0 self.label = 'bf' def create_atom_types(): diff --git a/rmgpy/molecule/converter.py b/rmgpy/molecule/converter.py index be87c22ba7..75d85b4523 100644 --- a/rmgpy/molecule/converter.py +++ b/rmgpy/molecule/converter.py @@ -81,7 +81,7 @@ def toRDKitMol(mol, removeHs=True, returnMapping=False, sanitize=True): rdAtomIndices[atom] = index rdBonds = Chem.rdchem.BondType - orders = {'S': rdBonds.SINGLE, 'D': rdBonds.DOUBLE, 'T': rdBonds.TRIPLE, 'B': rdBonds.AROMATIC} + orders = {'S': rdBonds.SINGLE, 'D': rdBonds.DOUBLE, 'T': rdBonds.TRIPLE, 'B': rdBonds.AROMATIC, 'Q': rdBonds.QUADRUPLE} # Add the bonds for atom1 in mol.vertices: for atom2, bond in atom1.edges.iteritems(): @@ -154,6 +154,7 @@ def fromRDKitMol(mol, rdkitmol): if rdbondtype.name == 'SINGLE': order = 1 elif rdbondtype.name == 'DOUBLE': order = 2 elif rdbondtype.name == 'TRIPLE': order = 3 + elif rdbondtype.name == 'QUADRUPLE': order = 4 elif rdbondtype.name == 'AROMATIC': order = 1.5 bond = mm.Bond(mol.vertices[i], mol.vertices[j], order) @@ -221,7 +222,7 @@ def toOBMol(mol, returnMapping=False): a.SetIsotope(atom.element.isotope) a.SetFormalCharge(atom.charge) obAtomIds[atom] = a.GetId() - orders = {1: 1, 2: 2, 3: 3, 1.5: 5} + orders = {1: 1, 2: 2, 3: 3, 4: 4, 1.5: 5} for atom1 in mol.vertices: for atom2, bond in atom1.edges.iteritems(): index1 = atoms.index(atom1) @@ -274,7 +275,7 @@ def fromOBMol(mol, obmol): for obbond in openbabel.OBMolBondIter(obmol): # Process bond type oborder = obbond.GetBondOrder() - if oborder not in [1,2,3] and obbond.IsAromatic() : + if oborder not in [1,2,3,4] and obbond.IsAromatic() : oborder = 1.5 bond = mm.Bond(mol.vertices[obbond.GetBeginAtomIdx() - 1], mol.vertices[obbond.GetEndAtomIdx() - 1], oborder)#python array indices start at 0 diff --git a/rmgpy/molecule/draw.py b/rmgpy/molecule/draw.py index 99c5f3a41f..17dcca932a 100644 --- a/rmgpy/molecule/draw.py +++ b/rmgpy/molecule/draw.py @@ -1046,7 +1046,15 @@ def __renderBond(self, atom1, atom2, bond, cr): dv = math.sin(angle + math.pi / 2) if (self.symbols[atom1] != '' or \ self.symbols[atom2] != ''): - if bond.isTriple(): + if bond.isQuadruple(): + # Draw quadruple bond centered on bond axis + du *= 1.5; dv *= 1.5 + self.__drawLine(cr, x1 - du, y1 - dv, x2 - du, y2 - dv) + self.__drawLine(cr, x1 + du, y1 + dv, x2 + du, y2 + dv) + du *= 2.2; dv *= 2.2 + self.__drawLine(cr, x1 - du, y1 - dv, x2 - du, y2 - dv) + self.__drawLine(cr, x1 + du, y1 + dv, x2 + du, y2 + dv) + elif bond.isTriple(): # Draw triple bond centered on bond axis du *= 3; dv *= 3 self.__drawLine(cr, x1 - du, y1 - dv, x2 - du, y2 - dv) @@ -1087,6 +1095,11 @@ def __renderBond(self, atom1, atom2, bond, cr): du *= 3; dv *= 3; dx = 2 * dx / bondLength; dy = 2 * dy / bondLength self.__drawLine(cr, x1 - du + dx, y1 - dv + dy, x2 - du - dx, y2 - dv - dy) self.__drawLine(cr, x1 + du + dx, y1 + dv + dy, x2 + du - dx, y2 + dv - dy, dashed=True) + elif bond.isQuadruple(): + du *= 3; dv *= 3; dx = 2 * dx / bondLength; dy = 2 * dy / bondLength + self.__drawLine(cr, x1 - du + dx, y1 - dv + dy, x2 - du - dx, y2 - dv - dy) + self.__drawLine(cr, x1 + du + dx, y1 + dv + dy, x2 + du - dx, y2 + dv - dy) + self.__drawLine(cr, x1 + 2 * du + dx, y1 + 2 * dv + dy, x2 + 2 * du - dx, y2 + 2 * dv - dy) def __renderAtom(self, symbol, atom, x0, y0, cr, heavyFirst=True, drawLonePairs=False): """ diff --git a/rmgpy/molecule/group.pxd b/rmgpy/molecule/group.pxd index 8fe1268e8f..36934712de 100644 --- a/rmgpy/molecule/group.pxd +++ b/rmgpy/molecule/group.pxd @@ -139,6 +139,8 @@ cdef class Group(Graph): cpdef removeBond(self, GroupBond bond) + cpdef removeVanDerWaalsBonds(self) + cpdef sortAtoms(self) cpdef list sortByConnectivity(self, list atomList) diff --git a/rmgpy/molecule/group.py b/rmgpy/molecule/group.py index 1693c69972..18ed1b3881 100644 --- a/rmgpy/molecule/group.py +++ b/rmgpy/molecule/group.py @@ -170,6 +170,9 @@ def __formBond(self, order): where `order` specifies the order of the forming bond, and should be 1 (since we only allow forming of single bonds). """ + if order == 0: + # no change to atom types! + return if order != 1: raise ActionError('Unable to update GroupAtom due to FORM_BOND action: Invalid order "{0}".'.format(order)) atomType = [] @@ -186,6 +189,9 @@ def __breakBond(self, order): where `order` specifies the order of the breaking bond, and should be 1 (since we only allow breaking of single bonds). """ + if order == 0: + # no change to atom types! + return if order != 1: raise ActionError('Unable to update GroupAtom due to BREAK_BOND action: Invalid order "{0}".'.format(order)) atomType = [] @@ -499,7 +505,7 @@ def countBonds(self, wildcards = False): options for bond orders will not be counted """ #count up number of bonds - single = 0; rDouble = 0; oDouble = 0; sDouble = 0; triple = 0; benzene = 0 + single = 0; rDouble = 0; oDouble = 0; sDouble = 0; triple = 0; quadruple = 0; benzene = 0 for atom2, bond12 in self.bonds.iteritems(): if not wildcards and len(bond12.order) > 1: continue @@ -515,11 +521,13 @@ def countBonds(self, wildcards = False): # rDouble is for double bonds NOT to oxygen or Sulfur rDouble += 1 if bond12.isTriple(wildcards = True): triple += 1 + if bond12.isQuadruple(wildcards=True): quadruple += 1 if bond12.isBenzene(wildcards = True): benzene += 1 allDouble = rDouble + oDouble + sDouble - return [single, allDouble, rDouble, oDouble, sDouble, triple, benzene] + # Warning: some parts of code assume this matches precisely the list returned by getFeatures() + return [single, allDouble, rDouble, oDouble, sDouble, triple, quadruple, benzene] def makeSampleAtom(self): """ @@ -658,9 +666,13 @@ def getOrderStr(self): values.append('D') elif value == 3: values.append('T') + elif value == 4: + values.append('Q') elif value == 1.5: values.append('B') elif value == 0: + values.append('vdW') + elif value == 0.1: values.append('H') else: raise TypeError('Bond order number {} is not hardcoded as a string'.format(value)) @@ -679,10 +691,14 @@ def setOrderStr(self, newOrder): values.append(2) elif value == 'T': values.append(3) + elif value == 'Q': + values.append(4) + elif value == 'vdW': + values.append(0) elif value == 'B': values.append(1.5) elif value == 'H': - values.append(0) + values.append(0.1) else: # try to see if an float disguised as a string was input by mistake try: @@ -752,6 +768,37 @@ def isTriple(self, wildcards = False): else: return abs(self.order[0]-3) <= 1e-9 and len(self.order) == 1 + def isQuadruple(self, wildcards = False): + """ + Return ``True`` if the bond represents a quadruple bond or ``False`` if + not. If `wildcards` is ``False`` we return False anytime there is more + than one bond order, otherwise we return ``True`` if any of the options + are quadruple. + """ + if wildcards: + for order in self.order: + if abs(order-4) <= 1e-9: + return True + else: return False + else: + return abs(self.order[0]-4) <= 1e-9 and len(self.order) == 1 + + def isVanDerWaals(self, wildcards = False): + """ + Return ``True`` if the bond represents a van der Waals bond or ``False`` if + not. If `wildcards` is ``False`` we return False anytime there is more + than one bond order, otherwise we return ``True`` if any of the options + are van der Waals. + """ + if wildcards: + for order in self.order: + if abs(order[0]) <= 1e-9: + return True + else: + return False + else: + return abs(self.order[0]) <= 1e-9 and len(self.order) == 1 + def isBenzene(self, wildcards = False): """ Return ``True`` if the bond represents a benzene bond or ``False`` if @@ -789,7 +836,7 @@ def __changeBond(self, order): in bond order. `order` is normally 1 or -1, but can be any value """ newOrder = [value + order for value in self.order] - if any([value < 0 or value > 3 for value in newOrder]): + if any([value < 0 or value > 4 for value in newOrder]): raise ActionError('Unable to update Bond due to CHANGE_BOND action: Invalid resulting order "{0}".'.format(newOrder)) # Change any modified benzene orders to the appropriate stable order newOrder = set(newOrder) @@ -1006,6 +1053,16 @@ def removeBond(self, bond): """ return self.removeEdge(bond) + def removeVanDerWaalsBonds(self): + """ + Remove all bonds that are definitely only van der Waals bonds. + """ + cython.declare(atom=GroupAtom, bond=GroupBond) + for atom in self.atoms: + for bond in atom.edges.values(): + if bond.isVanDerWaals(wildcards=False): + self.removeBond(bond) + def sortAtoms(self): """ Sort the atoms in the graph. This can make certain operations, e.g. @@ -1803,7 +1860,7 @@ def addImplicitAtomsFromAtomType(self): for atom1 in copyGroup.atoms: atomtypeFeatureList = atom1.atomType[0].getFeatures() - lonePairsRequired[atom1]=atomtypeFeatureList[7] + lonePairsRequired[atom1] = atomtypeFeatureList[8] #set to 0 required if empty list atomtypeFeatureList = [featureList if featureList else [0] for featureList in atomtypeFeatureList] @@ -1812,9 +1869,10 @@ def addImplicitAtomsFromAtomType(self): oDoubleRequired = atomtypeFeatureList[3] sDoubleRequired = atomtypeFeatureList[4] tripleRequired = atomtypeFeatureList[5] + quadrupleRequired = atomtypeFeatureList[6] #count up number of bonds - single = 0; rDouble = 0; oDouble = 0; sDouble = 0; triple = 0; benzene = 0 + single = 0; rDouble = 0; oDouble = 0; sDouble = 0; triple = 0; quadruple = 0; benzene = 0 for atom2, bond12 in atom1.bonds.iteritems(): # Count numbers of each higher-order bond type if bond12.isSingle(): @@ -1828,6 +1886,7 @@ def addImplicitAtomsFromAtomType(self): # rDouble is for double bonds NOT to oxygen or Sulfur rDouble += 1 elif bond12.isTriple(): triple += 1 + elif bond12.isQuadruple(): quadruple += 1 elif bond12.isBenzene(): benzene += 1 @@ -1851,6 +1910,11 @@ def addImplicitAtomsFromAtomType(self): newAtom = GroupAtom(atomType=[atomTypes['C']], radicalElectrons=[0], charge=[], label='', lonePairs=None) newBond = GroupBond(atom1, newAtom, order=[3]) implicitAtoms[newAtom] = newBond + while quadruple < quadrupleRequired[0]: + quadruple +=1 + newAtom = GroupAtom(atomType=[atomTypes['C']], radicalElectrons=[0], charge=[], label='', lonePairs=None) + newBond = GroupBond(atom1, newAtom, order=[4]) + implicitAtoms[newAtom] = newBond for atom, bond in implicitAtoms.iteritems(): copyGroup.addAtom(atom) @@ -2255,24 +2319,28 @@ def pickWildcards(self): requiredFeatures1.reverse() requiredFeatures2.reverse() - #required features are a now list of [benzene, triple, sDouble, oDouble, rDouble, allDouble, single] + #required features are a now list of [benzene, quadruple, triple, sDouble, oDouble, rDouble, allDouble, single] for index, (feature1, feature2) in enumerate(zip(requiredFeatures1[:-1], requiredFeatures2[:-1])): if feature1 > 0 or feature2 > 0: if index == 0 and 1.5 in bond12.order: #benzene bonds bond12.order = [1.5] atom2.bonds[atom1].order = bond12.order break - elif index == 1 and 3 in bond12.order: #triple bond + elif index == 1 and 4 in bond12.order: #quadruple bond + bond12.order = [4] + atom2.bonds[atom1].order = bond12.order + break + elif index == 2 and 3 in bond12.order: #triple bond bond12.order = [3] atom2.bonds[atom1].order = bond12.order break - elif index > 1 and 2 in bond12.order: #any case of double bonds - if index == 2: #sDouble bonds + elif index > 2 and 2 in bond12.order: #any case of double bonds + if index == 3: #sDouble bonds if (feature1 > 0 and atom2.isSulfur()) or (feature2 > 0 and atom1.isSulfur()): bond12.order = [2] atom2.bonds[atom1].order = bond12.order break - elif index == 3: #oDoubleBonds + elif index == 4: #oDoubleBonds if (feature1 > 0 and atom2.isOxygen()) or (feature2 > 0 and atom1.isOxygen()): bond12.order = [2] atom2.bonds[atom1].order = bond12.order diff --git a/rmgpy/molecule/groupTest.py b/rmgpy/molecule/groupTest.py index 17f8e9ce98..79a0d2e480 100644 --- a/rmgpy/molecule/groupTest.py +++ b/rmgpy/molecule/groupTest.py @@ -354,13 +354,16 @@ def testCountBonds(self): 3 C ux {1,S} {5,D} 4 C u[0,1] {2,B} 5 O u0 {3,D} +6 C u0 {7,Q} +7 C u0 {6,Q} """ test = Group().fromAdjacencyList(adjlist) - #returns a list of [single, allDouble, rDouble, oDouble, sDouble, triple, benzene] - self.assertListEqual([1,0,0,0,0,0,0], test.atoms[0].countBonds()) - self.assertListEqual([1,1,1,0,0,1,0], test.atoms[0].countBonds(wildcards = True)) - self.assertListEqual([0,0,0,0,0,0,1], test.atoms[3].countBonds()) - self.assertListEqual([1,1,0,1,0,0,0], test.atoms[2].countBonds()) + #returns a list of [single, allDouble, rDouble, oDouble, sDouble, triple, quadruple, benzene] + self.assertListEqual([1,0,0,0,0,0,0,0], test.atoms[0].countBonds()) + self.assertListEqual([1,1,1,0,0,1,0,0], test.atoms[0].countBonds(wildcards = True)) + self.assertListEqual([0,0,0,0,0,0,0,1], test.atoms[3].countBonds()) + self.assertListEqual([1,1,0,1,0,0,0,0], test.atoms[2].countBonds()) + self.assertListEqual([0,0,0,0,0,0,1,0], test.atoms[5].countBonds()) def testHasWildcards(self): """ @@ -400,7 +403,7 @@ def setUp(self): A method called before each unit test in this class. """ self.bond = GroupBond(None, None, order=[2]) - self.orderList = [[1], [2], [3], [1.5], [1,2], [2,1], [2,3], [1,2,3]] + self.orderList = [[1], [2], [3], [1.5], [1,2], [2,1], [2,3], [1,2,3]] # todo : unit tests for vdw def testGetOrderStr(self): """ @@ -496,6 +499,9 @@ def testApplyActionBreakBond(self): def testApplyActionFormBond(self): """ Test the GroupBond.applyAction() method for a FORM_BOND action. + + Tests that forming a bond between things already bonded, raises + an ActionError """ action = ['FORM_BOND', '*1', 1, '*2'] for order0 in self.orderList: diff --git a/rmgpy/molecule/molecule.pxd b/rmgpy/molecule/molecule.pxd index 3c37d9d453..7fe22c99a4 100644 --- a/rmgpy/molecule/molecule.pxd +++ b/rmgpy/molecule/molecule.pxd @@ -109,12 +109,16 @@ cdef class Bond(Edge): cpdef bint isOrder(self, float otherOrder) + cpdef bint isVanDerWaals(self) except -2 + cpdef bint isSingle(self) except -2 cpdef bint isDouble(self) except -2 cpdef bint isTriple(self) except -2 + cpdef bint isQuadruple(self) except -2 + cpdef bint isBenzene(self) except -2 cpdef incrementOrder(self) @@ -153,6 +157,8 @@ cdef class Molecule(Graph): cpdef removeBond(self, Bond bond) + cpdef removeVanDerWaalsBonds(self) + cpdef sortAtoms(self) cpdef str getFormula(self) diff --git a/rmgpy/molecule/molecule.py b/rmgpy/molecule/molecule.py index f0d88d7419..392a96a39d 100644 --- a/rmgpy/molecule/molecule.py +++ b/rmgpy/molecule/molecule.py @@ -552,6 +552,10 @@ def getOrderStr(self): return 'D' elif self.isTriple(): return 'T' + elif self.isQuadruple(): + return 'Q' + elif self.isVanDerWaals(): + return 'vdW' elif self.isHydrogenBond(): return 'H' else: @@ -569,8 +573,12 @@ def setOrderStr(self, newOrder): self.order = 3 elif newOrder == 'B': self.order = 1.5 - elif newOrder == 'H': + elif newOrder == 'Q': + self.order = 4 + elif newOrder == 'vdW': self.order = 0 + elif newOrder == 'H': + self.order = 0.1 else: # try to see if an float disguised as a string was input by mistake try: @@ -606,6 +614,14 @@ def copy(self): b.order = self.order return b + + def isVanDerWaals(self): + """ + Return ``True`` if the bond represents a van der Waals bond or + ``False`` if not. + """ + return self.isOrder(0) or self.order == 'vdW' #todo: remove 'vdW' + def isOrder(self, otherOrder): """ Return ``True`` if the bond is of order otherOrder or ``False`` if @@ -638,6 +654,13 @@ def isTriple(self): """ return self.isOrder(3) + def isQuadruple(self): + """ + Return ``True`` if the bond represents a quadruple bond or ``False`` if + not. + """ + return self.isOrder(4) + def isBenzene(self): """ Return ``True`` if the bond represents a benzene bond or ``False`` if @@ -650,18 +673,18 @@ def isHydrogenBond(self): Return ``True`` if the bond represents a hydrogen bond or ``False`` if not. """ - return self.isOrder(0) + return self.isOrder(0.1) def incrementOrder(self): """ Update the bond as a result of applying a CHANGE_BOND action to increase the order by one. """ - if self.order <=2.0001: + if self.order <=3.0001: self.order += 1 else: raise gr.ActionError('Unable to increment Bond due to CHANGE_BOND action: '+\ - 'Bond order "{0}" is greater than 2.'.format(self.order)) + 'Bond order "{0}" is greater than 3.'.format(self.order)) def decrementOrder(self): """ @@ -681,7 +704,7 @@ def __changeBond(self, order): in bond order, and can be any real number. """ self.order += order - if self.order < -0.0001 or self.order >3.0001: + if self.order < -0.0001 or self.order >4.0001: raise gr.ActionError('Unable to update Bond due to CHANGE_BOND action: Invalid resulting order "{0}".'.format(self.order)) def applyAction(self, action): @@ -708,13 +731,21 @@ def get_bond_string(self): the atom labels in alphabetical order (i.e. 'C-H' is possible but not 'H-C') :return: str """ - bond_symbol_mapping = {0: '~', 1: '-', 1.5: ':', 2: '=', 3: '#'} + bond_symbol_mapping = {0.1: '~', 1: '-', 1.5: ':', 2: '=', 3: '#'} atom_labels = [self.atom1.symbol, self.atom2.symbol] atom_labels.sort() try: bond_symbol = bond_symbol_mapping[self.getOrderNum()] except KeyError: - bond_symbol = ''.format(self.getOrderNum()) + # Direct lookup didn't work, but before giving up try + # with the isOrder() method which allows a little latitude + # for floating point errors. + for order,symbol in bond_symbol_mapping.iteritems(): + if self.isOrder(order): + bond_symbol = symbol + break + else: # didn't break + bond_symbol = ''.format(self.getOrderNum()) return '{0}{1}{2}'.format(atom_labels[0], bond_symbol, atom_labels[1]) @@ -881,6 +912,16 @@ def removeBond(self, bond): self._fingerprint = None return self.removeEdge(bond) + def removeVanDerWaalsBonds(self): + """ + Remove all van der Waals bonds. + """ + cython.declare(atom=Atom, bond=Bond) + for atom in self.atoms: + for bond in atom.edges.values(): + if bond.isVanDerWaals(): + self.removeBond(bond) + def sortAtoms(self): """ Sort the atoms in the graph. This can make certain operations, e.g. @@ -1570,7 +1611,7 @@ def find_H_bonds(self): atm_cov = atm_covs[0] if (atm_cov.isOxygen() or atm_cov.isNitrogen()): #this H can be H-bonded for k,atm2 in enumerate(ONatoms): - if all([q.order != 0 for q in atm2.bonds.values()]): #atm2 not already H bonded + if all([not numpy.isclose(0.1, q.order) for q in atm2.bonds.values()]): #atm2 not already H bonded dist = len(find_shortest_path(atm1,atm2))-1 if dist > 3: j = ONinds[k] @@ -1594,13 +1635,13 @@ def generate_H_bonded_structures(self): Hbonds = self.find_H_bonds() for i,bd1 in enumerate(Hbonds): molc = self.copy(deep=True) - molc.addBond(Bond(molc.atoms[bd1[0]],molc.atoms[bd1[1]],order=0)) + molc.addBond(Bond(molc.atoms[bd1[0]],molc.atoms[bd1[1]],order=0.1)) structs.append(molc) for j,bd2 in enumerate(Hbonds): if j= 3) + self.assertTrue(order >= 4) # or benzene?? def testDecrementOrder(self): """ @@ -421,6 +434,8 @@ def testDecrementOrder(self): self.assertTrue(bond.isSingle()) elif order == 3: self.assertTrue(bond.isDouble()) + elif order == 'Q': + self.assertTrue(bond.isTriple()) except ActionError: self.assertTrue(order < 1) @@ -463,7 +478,7 @@ def testApplyActionIncrementBond(self): try: bond.applyAction(action) except ActionError: - self.assertTrue(3 <= order0,'Test failed with order {0}'.format(order0)) + self.assertTrue(4 <= order0,'Test failed with order {0}'.format(order0)) def testApplyActionDecrementBond(self): """ @@ -1038,7 +1053,7 @@ def test_remove_H_bonds(self): for j,atm2 in enumerate(testMol.atoms): if j