Пример #1
0
    def generateThermoData(self, molecule):
        """
        Determine the group additivity thermodynamic data for the given
        `molecule`.
        """

        thermoData = None

        if sum([atom.radicalElectrons for atom in molecule.atoms]) > 0:

            # Make a copy of the structure so we don't change the original
            saturatedStruct = molecule.copy(deep=True)

            # Saturate structure by replacing all radicals with bonds to
            # hydrogen atoms
            added = {}
            for atom in saturatedStruct.atoms:
                for i in range(atom.radicalElectrons):
                    H = Atom('H')
                    bond = Bond('S')
                    saturatedStruct.addAtom(H)
                    saturatedStruct.addBond(atom, H, bond)
                    if atom not in added:
                        added[atom] = []
                    added[atom].append([H, bond])
                    atom.decrementRadical()

            # Update the atom types of the saturated structure (not sure why
            # this is necessary, because saturating with H shouldn't be
            # changing atom types, but it doesn't hurt anything and is not
            # very expensive, so will do it anyway)
            saturatedStruct.updateConnectivityValues()
            saturatedStruct.sortVertices()
            saturatedStruct.updateAtomTypes()

            # Get thermo estimate for saturated form of structure
            thermoData = self.generateThermoData(saturatedStruct)
            assert thermoData is not None, "Thermo data of saturated %s of molecule %s is None!" % (saturatedStruct, molecule)
            
            # For each radical site, get radical correction
            # Only one radical site should be considered at a time; all others
            # should be saturated with hydrogen atoms
            for atom in added:

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

                saturatedStruct.updateConnectivityValues()
            
                thermoData += self.__getThermoData(self.radicalDatabase, saturatedStruct, {'*':atom})

                # Re-saturate
                for H, bond in added[atom]:
                    saturatedStruct.addAtom(H)
                    saturatedStruct.addBond(atom, H, bond)
                    atom.decrementRadical()

                # Subtract the enthalpy of the added hydrogens
                for H, bond in added[atom]:
                    thermoData.H298 -= 52.103 * 4184

            # Correct the entropy for the symmetry number

        else:
            # Generate estimate of thermodynamics
            for atom in molecule.atoms:
                # Iterate over heavy (non-hydrogen) atoms
                if atom.isNonHydrogen():
                    # Get initial thermo estimate from main group database
                    try:
                        if thermoData is None:
                            thermoData = self.__getThermoData(self.groupDatabase, molecule, {'*':atom})
                        else:
                            thermoData += self.__getThermoData(self.groupDatabase, molecule, {'*':atom})
                    except KeyError:
                        print molecule
                        print molecule.toAdjacencyList()
                        raise
                    # Correct for gauche and 1,5- interactions
                    try:
                        thermoData += self.__getThermoData(self.gaucheDatabase, molecule, {'*':atom})
                    except KeyError: pass
                    try:
                        thermoData += self.__getThermoData(self.int15Database, molecule, {'*':atom})
                    except KeyError: pass
                    try:
                        thermoData += self.__getThermoData(self.otherDatabase, molecule, {'*':atom})
                    except KeyError: pass
            
            # Do ring corrections separately because we only want to match
            # 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
                ringStructure = Molecule()
                for atom in ring: ringStructure.addAtom(atom)
                for atom1 in ring:
                    for atom2 in ring:
                        if molecule.hasBond(atom1, atom2):
                            ringStructure.addBond(atom1, atom2, molecule.getBond(atom1, atom2))

                # Get thermo correction for this ring
                thermoData += self.__getThermoData(self.ringDatabase, ringStructure, {})

        return thermoData