示例#1
0
文件: mbac.py 项目: pw0908/RMG-Py
def geo_to_mol(coords, nums):
    """
    Convert molecular geometry specified by atomic coordinates and
    atomic numbers to RMG molecule.

    Use Open Babel for most cases because it's better at recognizing
    long bonds. Use RMG for hydrogen because Open Babel can't do it for
    mysterious reasons.
    """
    if list(nums) == [1, 1]:
        mol = Molecule()
        mol.fromXYZ(nums, coords)
    else:
        xyz = '{}\n\n'.format(len(nums))
        xyz += '\n'.join(
            '{0}  {1[0]: .10f}  {1[1]: .10f}  {1[2]: .10f}'.format(n, c)
            for n, c in zip(nums, coords))
        mol = pybel.readstring('xyz', xyz)
        mol = pybel_to_rmg(mol)
    return mol
示例#2
0
        def check_isomorphic(conformer):
            """
            Compares whatever is in the log file 'f' 
            to the SMILES of the passed in 'conformer'
            """
            starting_molecule = RMGMolecule(SMILES=conformer.smiles)
            starting_molecule = starting_molecule.toSingleBonds()

            atoms = self.read_log(os.path.join(scratch_dir, f))

            test_molecule = RMGMolecule()
            test_molecule.fromXYZ(atoms.arrays["numbers"],
                                  atoms.arrays["positions"])
            if not starting_molecule.isIsomorphic(test_molecule):
                logging.info(
                    "Output geometry of {} is not isomorphic with input geometry"
                    .format(calc.label))
                return False
            else:
                logging.info("{} was successful and was validated!".format(
                    calc.label))
                return True
示例#3
0
    def verifyOutputFile(self):
        """
        Check's that an output file exists and was successful.
        
        Returns a boolean flag that states whether a successful MOPAC simulation already exists for the molecule with the 
        given (augmented) InChI Key.
        
        The definition of finding a successful simulation is based on these criteria:
        1) finding an output file with the file name equal to the InChI Key
        2) NOT finding any of the keywords that are denote a calculation failure
        3) finding all the keywords that denote a calculation success.
        4) finding a match between the InChI of the given molecule and the InchI found in the calculation files
        5) checking that the optimized geometry, when connected by single bonds, is isomorphic with self.molecule (converted to single bonds)
        
        If any of the above criteria is not matched, False will be returned.
        If all succeed, then it will return True.
        """
        if not os.path.exists(self.outputFilePath):
            logging.debug("Output file {0} does not (yet) exist.".format(self.outputFilePath))
            return False
    
        InChIMatch=False #flag (1 or 0) indicating whether the InChI in the file matches InChIaug this can only be 1 if InChIFound is also 1
        InChIFound=False #flag (1 or 0) indicating whether an InChI was found in the log file
        
        # Initialize dictionary with "False"s 
        successKeysFound = dict([(key, False) for key in self.successKeys])
        
        with open(self.outputFilePath) as outputFile:
            for line in outputFile:
                line = line.strip()
                
                for element in self.failureKeys: #search for failure keywords
                    if element in line:
                        logging.error("MOPAC output file contains the following error: {0}".format(element) )
                        return False
                
                for element in self.successKeys: #search for success keywords
                    if element in line:
                        successKeysFound[element] = True
                
                if "InChI=" in line:
                    logFileInChI = line #output files should take up to 240 characters of the name in the input file
                    InChIFound = True
                    if self.uniqueIDlong in logFileInChI:
                        InChIMatch = True
                    elif self.uniqueIDlong.startswith(logFileInChI):
                        logging.info("InChI too long to check, but beginning matches so assuming OK.")
                        InChIMatch = True
                    else:
                        logging.warning("InChI in log file ({0}) didn't match that in geometry ({1}).".format(logFileInChI, self.uniqueIDlong))                    
                        # Use only up to first 80 characters to match due to MOPAC bug which deletes 81st character of InChI string
                        if self.uniqueIDlong.startswith(logFileInChI[:80]):
                            logging.warning("but the beginning matches so it's probably just a truncation problem.")
                            InChIMatch = True
        # Check that ALL 'success' keywords were found in the file.
        if not all( successKeysFound.values() ):
            logging.error('Not all of the required keywords for success were found in the output file!')
            return False
        
        if not InChIFound:
            logging.error("No InChI was found in the MOPAC output file {0}".format(self.outputFilePath))
            return False
        
        if not InChIMatch:
            #InChIs do not match (most likely due to limited name length mirrored in log file (240 characters), but possibly due to a collision)
            return self.checkForInChiKeyCollision(logFileInChI) # Not yet implemented!

        # Compare the optimized geometry to the original molecule
        qmData = self.parse()
        cclibMol = Molecule()
        cclibMol.fromXYZ(qmData.atomicNumbers, qmData.atomCoords.value)
        testMol = self.molecule.toSingleBonds()
        if not cclibMol.isIsomorphic(testMol):
            logging.info("Incorrect connectivity for optimized geometry in file {0}".format(self.outputFilePath))
            return False

        logging.info("Successful {1} quantum result in {0}".format(self.outputFilePath, self.__class__.__name__))
        return True
        
        #InChIs do not match (most likely due to limited name length mirrored in log file (240 characters), but possibly due to a collision)
        return self.checkForInChiKeyCollision(logFileInChI) # Not yet implemented!
示例#4
0
    def verifyOutputFile(self):
        """
        Check's that an output file exists and was successful.
        
        Returns a boolean flag that states whether a successful MOPAC simulation already exists for the molecule with the 
        given (augmented) InChI Key.
        
        The definition of finding a successful simulation is based on these criteria:
        1) finding an output file with the file name equal to the InChI Key
        2) NOT finding any of the keywords that are denote a calculation failure
        3) finding all the keywords that denote a calculation success.
        4) finding a match between the InChI of the given molecule and the InchI found in the calculation files
        5) checking that the optimized geometry, when connected by single bonds, is isomorphic with self.molecule (converted to single bonds)
        
        If any of the above criteria is not matched, False will be returned.
        If all succeed, then it will return True.
        """
        if not os.path.exists(self.outputFilePath):
            logging.debug("Output file {0} does not (yet) exist.".format(
                self.outputFilePath))
            return False

        InChIFound = False  #flag (1 or 0) indicating whether an InChI was found in the log file

        # Initialize dictionary with "False"s
        successKeysFound = dict([(key, False) for key in self.successKeys])

        with open(self.outputFilePath) as outputFile:
            for line in outputFile:
                line = line.strip()

                for element in self.failureKeys:  #search for failure keywords
                    if element in line:
                        logging.error(
                            "MOPAC output file contains the following error: {0}"
                            .format(element))
                        return False

                for element in self.successKeys:  #search for success keywords
                    if element in line:
                        successKeysFound[element] = True

                if "InChI=" in line:
                    logFileInChI = line  #output files should take up to 240 characters of the name in the input file
                    InChIFound = True
                    if self.uniqueIDlong in logFileInChI:
                        pass
                    elif self.uniqueIDlong.startswith(logFileInChI):
                        logging.info(
                            "InChI too long to check, but beginning matches so assuming OK."
                        )

                    else:
                        logging.warning(
                            "InChI in log file ({0}) didn't match that in geometry ({1})."
                            .format(logFileInChI, self.uniqueIDlong))
                        # Use only up to first 80 characters to match due to MOPAC bug which deletes 81st character of InChI string
                        if self.uniqueIDlong.startswith(logFileInChI[:80]):
                            logging.warning(
                                "but the beginning matches so it's probably just a truncation problem."
                            )

        # Check that ALL 'success' keywords were found in the file.
        if not all(successKeysFound.values()):
            logging.error(
                'Not all of the required keywords for success were found in the output file!'
            )
            return False

        if not InChIFound:
            logging.error(
                "No InChI was found in the MOPAC output file {0}".format(
                    self.outputFilePath))
            return False

        # Compare the optimized geometry to the original molecule
        qmData = self.parse()
        cclibMol = Molecule()
        cclibMol.fromXYZ(qmData.atomicNumbers, qmData.atomCoords.value)
        testMol = self.molecule.toSingleBonds()
        if not cclibMol.isIsomorphic(testMol):
            logging.info(
                "Incorrect connectivity for optimized geometry in file {0}".
                format(self.outputFilePath))
            return False

        logging.info("Successful {1} quantum result in {0}".format(
            self.outputFilePath, self.__class__.__name__))
        return True
示例#5
0
    def calculate_conformer(self, conformer, calculator):

        if isinstance(calculator, Gaussian):
            calc = calculator.get_conformer_calc(conformer=conformer,
                                                 convergence='Tight')

        else:
            calc = calculator.get_conformer_calc(conformer=conformer)

        scratch = calculator.scratch

        scratch_dir = os.path.join(calculator.scratch, "species",
                                   conformer.smiles, "conformers")

        f = calc.label + ".log"

        if not os.path.exists(os.path.join(scratch_dir, f)):
            logging.info("Submitting conformer calculation for {}".format(
                calc.label))
            label = self.submit_conformer(conformer, calc, "general")
            while not self.check_complete(label):
                time.sleep(15)

        else:
            logging.info(
                "It appears that we already have a complete log file for {}".
                format(calc.label))

            complete, converged = calculator.verify_output_file(
                os.path.join(scratch_dir, f))
            if not complete:
                logging.info(
                    "It seems that the file never completed for {} completed, running it again"
                    .format(calc.label))
                label = self.submit_conformer(conformer, calc, "general")
                while not self.check_complete(label):
                    time.sleep(15)

        complete, converged = calculator.verify_output_file(
            os.path.join(scratch_dir, f))

        if (complete and converged):
            logging.info("{} was successful and was validated!".format(
                calc.label))
            atoms = self.read_log(os.path.join(scratch_dir, f))

            starting_molecule = RMGMolecule(SMILES=conformer.smiles)
            starting_molecule = starting_molecule.toSingleBonds()

            test_molecule = RMGMolecule()
            test_molecule.fromXYZ(atoms.arrays["numbers"],
                                  atoms.arrays["positions"])

            if not starting_molecule.isIsomorphic(test_molecule):
                logging.info(
                    "Output geometry of {} is not isomorphic with input geometry"
                    .format(calc.label))
                result = False
            else:
                logging.info("{} was successful and was validated!".format(
                    calc.label))
                result = True

        if not complete:
            logging.info("It appears that {} was killed prematurely".format(
                calc.label))
            result = False

        elif not converged:
            logging.info("{} did not converge".format(calc.label))
            result = False
            if isinstance(calculator, Gaussian):
                if not calc.convergence.lower() in [
                        "tight", "verytight", "loose"
                ]:
                    logging.info("{} failed QM optimization".format(
                        calc.label))
                else:
                    logging.info(
                        "Resubmitting {} with default convergence criteria".
                        format(calc.label))
                    atoms = self.read_log(os.path.join(scratch_dir, f))
                    conformer.ase_molecule = atoms
                    conformer.update_coords_from("ase")
                    calc = calculator.get_conformer_calc(conformer,
                                                         convergence="")
                    logging.info(
                        "Removing the old log file that didn't converge, restarting from last geometry"
                    )
                    os.remove(os.path.join(scratch_dir, f))

                    label = self.submit_conformer(conformer, calc, "general")
                    while not self.check_complete(label):
                        time.sleep(15)

                    scratch_dir = os.path.join(calculator.scratch, "species",
                                               conformer.smiles, "conformers")
                    f = calc.label + ".log"
                    if not os.path.exists(os.path.join(scratch_dir, f)):
                        logging.info(
                            "It seems that {} was never run...".format(
                                calc.label))
                        result = False

                    complete, converged = calculator.verify_output_file(
                        os.path.join(scratch_dir, f))

                    if not complete:
                        logging.info(
                            "It appears that {} was killed prematurely".format(
                                calc.label))
                        result = False

                    elif not converged:
                        logging.info("{} failed second QM optimization".format(
                            calc.label))
                        result = False

                    else:
                        atoms = self.read_log(os.path.join(scratch_dir, f))

                        starting_molecule = RMGMolecule(
                            SMILES=conformer.smiles)
                        starting_molecule = starting_molecule.toSingleBonds()

                        test_molecule = RMGMolecule()
                        test_molecule.fromXYZ(atoms.arrays["numbers"],
                                              atoms.arrays["positions"])

                        if not starting_molecule.isIsomorphic(test_molecule):
                            logging.info(
                                "Output geometry of {} is not isomorphic with input geometry"
                                .format(calc.label))
                            result = False
                        else:
                            logging.info(
                                "{} was successful and was validated!".format(
                                    calc.label))
                            result = True

        if not result:
            fail_dir = os.path.join(scratch_dir, "failures")
            try:
                os.makedirs(os.path.join(scratch_dir, "failures"))
            except OSError:
                logging.info("{} already exists...".format(fail_dir))
            move(os.path.join(scratch_dir, f),
                 os.path.join(scratch_dir, "failures", f))
            return False

        return True
示例#6
0
    def verifyOutputFile(self):
        """
        Check's that an output file exists and was successful.
        
        Returns a boolean flag that states whether a successful MOPAC simulation already exists for the molecule with the 
        given (augmented) InChI Key.
        
        The definition of finding a successful simulation is based on these criteria:
        1) finding an output file with the file name equal to the InChI Key
        2) NOT finding any of the keywords that are denote a calculation failure
        3) finding all the keywords that denote a calculation success.
        4) finding a match between the InChI of the given molecule and the InchI found in the calculation files
        5) checking that the optimized geometry, when connected by single bonds, is isomorphic with self.molecule (converted to single bonds)
        
        If any of the above criteria is not matched, False will be returned.
        If all succeed, then it will return True.
        """
        if not os.path.exists(self.outputFilePath):
            logging.debug("Output file {0} does not (yet) exist.".format(
                self.outputFilePath))
            return False

        InChIMatch = False  #flag (1 or 0) indicating whether the InChI in the file matches InChIaug this can only be 1 if InChIFound is also 1
        InChIFound = False  #flag (1 or 0) indicating whether an InChI was found in the log file

        # Initialize dictionary with "False"s
        successKeysFound = dict([(key, False) for key in self.successKeys])

        with open(self.outputFilePath) as outputFile:
            for line in outputFile:
                line = line.strip()
                for element in self.failureKeys:  #search for failure keywords
                    if element in line:
                        logging.error(
                            "MOPAC output file contains the following error: {0}"
                            .format(element))
                        return False
                for element in self.successKeys:  #search for success keywords
                    if element in line:
                        successKeysFound[element] = True
                if "InChI=" in line:
                    logFileInChI = line  #output files should take up to 240 characters of the name in the input file
                    InChIFound = True
                    if self.uniqueIDlong in logFileInChI:
                        InChIMatch = True
                    else:
                        logging.warning(
                            "InChI in log file ({0}) didn't match that in geometry ({1})."
                            .format(logFileInChI, self.uniqueIDlong))
                        # Use only up to first 80 characters to match due to MOPAC bug which deletes 81st character of InChI string
                        if self.uniqueIDlong.startswith(logFileInChI[:80]):
                            logging.warning(
                                "but the beginning matches so it's probably just a truncation problem."
                            )
                            InChIMatch = True
        # Check that ALL 'success' keywords were found in the file.
        if not all(successKeysFound.values()):
            logging.error(
                'Not all of the required keywords for success were found in the output file!'
            )
            return False

        if not InChIFound:
            logging.error(
                "No InChI was found in the MOPAC output file {0}".format(
                    self.outputFilePath))
            return False

        if InChIMatch:
            # Compare the optimized geometry to the original molecule
            parser = cclib.parser.Mopac(self.outputFilePath)
            parser.logger.setLevel(
                logging.ERROR
            )  #cf. http://cclib.sourceforge.net/wiki/index.php/Using_cclib#Additional_information
            cclibData = parser.parse()
            cclibMol = Molecule()
            cclibMol.fromXYZ(cclibData.atomnos, cclibData.atomcoords[-1])
            testMol = self.molecule.toSingleBonds()

            if cclibMol.isIsomorphic(testMol):
                logging.info(
                    "Successful MOPAC quantum result found in {0}".format(
                        self.outputFilePath))
                # " + self.molfile.name + " ("+self.molfile.InChIAug+") has been found. This log file will be used.")
                return True
            else:
                logging.info(
                    "Incorrect connectivity for optimized geometry in file {0}"
                    .format(self.outputFilePath))
                # " + self.molfile.name + " ("+self.molfile.InChIAug+") has been found. This log file will be used.")
                return False

        #InChIs do not match (most likely due to limited name length mirrored in log file (240 characters), but possibly due to a collision)
        return self.checkForInChiKeyCollision(
            logFileInChI)  # Not yet implemented!
示例#7
0
    def validate_irc(self, calc=None):
        """
        A method to verify an IRC calc
        """
        assert "irc" in calc.label, "The calculator provided is not an IRC calculator"

        reaction_label = calc.label.split("_irc")[0]

        logging.info("Validating IRC file...")
        irc_path = os.path.join(calc.scratch, calc.label + ".log")

        if not os.path.exists(irc_path):
            logging.info("It seems that the IRC claculation has not been run.")
            return False

        f = open(irc_path, "r")
        file_lines = f.readlines()[-5:]

        completed = False
        for file_line in file_lines:
            if "Normal termination" in file_line:
                logging.info("IRC successfully ran")
                completed = True
        if not completed:
            logging.info("IRC failed... could not be validated...")
            return False

        pth1 = list()
        steps = list()
        with open(irc_path) as outputFile:
            for line in outputFile:
                line = line.strip()

                if line.startswith('Point Number:'):
                    if int(line.split()[2]) > 0:
                        if int(line.split()[-1]) == 1:
                            ptNum = int(line.split()[2])
                            pth1.append(ptNum)
                        else:
                            pass
                elif line.startswith('# OF STEPS ='):
                    numStp = int(line.split()[-1])
                    steps.append(numStp)
        # This indexes the coordinate to be used from the parsing
        if steps == []:
            logging.error('No steps taken in the IRC calculation!')
            return False
        else:
            pth1End = sum(steps[:pth1[-1]])
            # Compare the reactants and products
            ircParse = ccread(irc_path)
            # cf.
            # http://cclib.sourceforge.net/wiki/index.php/Using_cclib#Additional_information

            atomcoords = ircParse.atomcoords
            atomnos = ircParse.atomnos
            # Convert the IRC geometries into RMG molecules
            # We don't know which is reactant or product, so take the two at the end of the
            # paths and compare to the reactants and products
            mol1 = RMGMolecule()
            mol1.fromXYZ(atomnos, atomcoords[pth1End])
            mol2 = RMGMolecule()
            mol2.fromXYZ(atomnos, atomcoords[-1])

            testReaction = RMGReaction(
                reactants=mol1.split(),
                products=mol2.split(),
            )

            r, p = reaction_label.split("_")

            reactants = []
            products = []

            for react in r.split("+"):
                react = RMGMolecule(SMILES=react)
                reactants.append(react)

            for prod in p.split("+"):
                prod = RMGMolecule(SMILES=prod)
                products.append(prod)

            possible_reactants = []
            possible_products = []
            for reactant in reactants:
                possible_reactants.append(
                    reactant.generate_resonance_structures())

            for product in products:
                possible_products.append(
                    product.generate_resonance_structures())

            possible_reactants = list(itertools.product(*possible_reactants))
            possible_products = list(itertools.product(*possible_products))

            for possible_reactant in possible_reactants:
                reactant_list = []
                for react in possible_reactant:
                    reactant_list.append(react.toSingleBonds())

                for possible_product in possible_products:
                    product_list = []
                    for prod in possible_product:
                        product_list.append(prod.toSingleBonds())

                    targetReaction = RMGReaction(reactants=list(reactant_list),
                                                 products=list(product_list))

                    if targetReaction.isIsomorphic(testReaction):
                        logging.info("IRC calculation was successful!")
                        return True
            logging.info("IRC calculation failed for {} :(".format(calc.label))
            return False
示例#8
0
    def verifyOutputFile(self):
        """
        Check's that an output file exists and was successful.
        
        Returns a boolean flag that states whether a successful GAUSSIAN simulation already exists for the molecule with the 
        given (augmented) InChI Key.
        
        The definition of finding a successful simulation is based on these criteria:
        1) finding an output file with the file name equal to the InChI Key
        2) NOT finding any of the keywords that are denote a calculation failure
        3) finding all the keywords that denote a calculation success.
        4) finding a match between the InChI of the given molecule and the InchI found in the calculation files
        5) checking that the optimized geometry, when connected by single bonds, is isomorphic with self.molecule (converted to single bonds)

        If any of the above criteria is not matched, False will be returned.
        If all are satisfied, it will return True.
        """
        if not os.path.exists(self.outputFilePath):
            logging.info("Output file {0} does not exist.".format(
                self.outputFilePath))
            return False

        InChIMatch = False  #flag (1 or 0) indicating whether the InChI in the file matches InChIaug this can only be 1 if InChIFound is also 1
        InChIFound = False  #flag (1 or 0) indicating whether an InChI was found in the log file

        # Initialize dictionary with "False"s
        successKeysFound = dict([(key, False) for key in self.successKeys])

        with open(self.outputFilePath) as outputFile:
            for line in outputFile:
                line = line.strip()

                for element in self.failureKeys:  #search for failure keywords
                    if element in line:
                        logging.error(
                            "Gaussian output file contains the following error: {0}"
                            .format(element))
                        return False

                for element in self.successKeys:  #search for success keywords
                    if element in line:
                        successKeysFound[element] = True

                if line.startswith("InChI="):
                    logFileInChI = line  #output files should take up to 240 characters of the name in the input file
                    InChIFound = True
                    if logFileInChI == self.geometry.uniqueIDlong:
                        InChIMatch = True
                    elif self.geometry.uniqueIDlong.startswith(logFileInChI):
                        logging.info(
                            "InChI too long to check, but beginning matches so assuming OK."
                        )
                        InChIMatch = True
                    else:
                        logging.warning(
                            "InChI in log file ({0}) didn't match that in geometry ({1})."
                            .format(logFileInChI, self.geometry.uniqueIDlong))
                        if self.geometry.uniqueIDlong.startswith(logFileInChI):
                            logging.warning(
                                "but the beginning matches so it's probably just a truncation problem."
                            )
                            InChIMatch = True
        # Check that ALL 'success' keywords were found in the file.
        if not all(successKeysFound.values()):
            logging.error(
                'Not all of the required keywords for success were found in the output file!'
            )
            return False

        if not InChIFound:
            logging.error(
                "No InChI was found in the Gaussian output file {0}".format(
                    self.outputFilePath))
            return False

        if not InChIMatch:
            #InChIs do not match (most likely due to limited name length mirrored in log file (240 characters), but possibly due to a collision)
            return self.checkForInChiKeyCollision(
                logFileInChI)  # Not yet implemented!

        # Compare the optimized geometry to the original molecule
        qmData = self.parse()
        cclibMol = Molecule()
        cclibMol.fromXYZ(qmData.atomicNumbers, qmData.atomCoords.value)
        testMol = self.molecule.toSingleBonds()
        if not cclibMol.isIsomorphic(testMol):
            logging.info(
                "Incorrect connectivity for optimized geometry in file {0}".
                format(self.outputFilePath))
            return False

        logging.info("Successful MOPAC quantum result found in {0}".format(
            self.outputFilePath))
        return True
示例#9
0
    def validate_irc(self):  # TODO: need to add more verification here
        logging.info("Validating IRC file...")
        irc_path = os.path.join(self.irc_calc.scratch,
                                self.irc_calc.label + ".log")
        if not os.path.exists(irc_path):
            logging.info(
                "It seems that the file was `fixed`, reading in the `fixed` version.")
            irc_path = irc_path.replace("left", "(").replace("right", ")")

            if not os.path.exists(irc_path):
                logging.info(
                    "It seems that the IRC claculation has not been run.")
                return False

        f = open(irc_path, "r")
        file_lines = f.readlines()[-5:]

        completed = False
        for file_line in file_lines:
            if " Normal termination" in file_line:
                logging.info("IRC successfully ran")
                completed = True
        if completed == False:
            logging.info("IRC failed... could not be validated...")
            return False

        pth1 = list()
        steps = list()
        with open(irc_path) as outputFile:
            for line in outputFile:
                line = line.strip()

                if line.startswith('Point Number:'):
                    if int(line.split()[2]) > 0:
                        if int(line.split()[-1]) == 1:
                            ptNum = int(line.split()[2])
                            pth1.append(ptNum)
                        else:
                            pass
                elif line.startswith('# OF STEPS ='):
                    numStp = int(line.split()[-1])
                    steps.append(numStp)
        # This indexes the coordinate to be used from the parsing
        if steps == []:
            logging.error('No steps taken in the IRC calculation!')
            return False
        else:
            pth1End = sum(steps[:pth1[-1]])
            # Compare the reactants and products
            ircParse = ccread(irc_path)
            # cf. http://cclib.sourceforge.net/wiki/index.php/Using_cclib#Additional_information

            atomcoords = ircParse.atomcoords
            atomnos = ircParse.atomnos
            # Convert the IRC geometries into RMG molecules
            # We don't know which is reactant or product, so take the two at the end of the
            # paths and compare to the reactants and products
            mol1 = Molecule()
            mol1.fromXYZ(atomnos, atomcoords[pth1End])
            mol2 = Molecule()
            mol2.fromXYZ(atomnos, atomcoords[-1])

            testReaction = Reaction(
                reactants=mol1.split(),
                products=mol2.split(),
            )

            if isinstance(self.reaction.rmg_reaction.reactants[0], rmgpy.molecule.Molecule):
                targetReaction = Reaction(
                    reactants=[reactant.toSingleBonds()
                               for reactant in self.reaction.rmg_reaction.reactants],
                    products=[product.toSingleBonds()
                              for product in self.reaction.rmg_reaction.products],
                )
            elif isinstance(self.reaction.rmg_reaction.reactants[0], rmgpy.species.Species):
                targetReaction = Reaction(
                    reactants=[reactant.molecule[0].toSingleBonds()
                               for reactant in self.reaction.rmg_reaction.reactants],
                    products=[product.molecule[0].toSingleBonds()
                              for product in self.reaction.rmg_reaction.products],
                )

            if targetReaction.isIsomorphic(testReaction):
                return True
            else:
                return False
示例#10
0
    def validate_irc(self):
        """
        A method to verify an IRC calc
        """

        logging.info("Validating IRC file...")
        irc_path = os.path.join(
            self.directory, "ts", self.conformer.reaction_label, "irc",
            self.conformer.reaction_label + "_irc_" +
            self.conformer.direction + "_" + str(self.conformer.index) +
            ".log")

        complete, converged = self.verify_output_file(irc_path)
        if not complete:
            logging.info("It seems that the IRC claculation did not complete")
            return False
        if not converged:
            logging.info("The IRC calculation did not converge...")
            return False

        pth1 = list()
        steps = list()
        with open(irc_path) as outputFile:
            for line in outputFile:
                line = line.strip()

                if line.startswith('Point Number:'):
                    if int(line.split()[2]) > 0:
                        if int(line.split()[-1]) == 1:
                            ptNum = int(line.split()[2])
                            pth1.append(ptNum)
                        else:
                            pass
                elif line.startswith('# OF STEPS ='):
                    numStp = int(line.split()[-1])
                    steps.append(numStp)
        # This indexes the coordinate to be used from the parsing
        if steps == []:
            logging.error('No steps taken in the IRC calculation!')
            return False
        else:
            pth1End = sum(steps[:pth1[-1]])
            # Compare the reactants and products
            ircParse = ccread(irc_path)

            atomcoords = ircParse.atomcoords
            atomnos = ircParse.atomnos

            mol1 = RMGMolecule()
            mol1.fromXYZ(atomnos, atomcoords[pth1End])
            mol2 = RMGMolecule()
            mol2.fromXYZ(atomnos, atomcoords[-1])

            testReaction = RMGReaction(
                reactants=mol1.split(),
                products=mol2.split(),
            )

            r, p = self.conformer.reaction_label.split("_")

            reactants = []
            products = []

            for react in r.split("+"):
                react = RMGMolecule(SMILES=react)
                reactants.append(react)

            for prod in p.split("+"):
                prod = RMGMolecule(SMILES=prod)
                products.append(prod)

            possible_reactants = []
            possible_products = []
            for reactant in reactants:
                possible_reactants.append(
                    reactant.generate_resonance_structures())

            for product in products:
                possible_products.append(
                    product.generate_resonance_structures())

            possible_reactants = list(itertools.product(*possible_reactants))
            possible_products = list(itertools.product(*possible_products))

            for possible_reactant in possible_reactants:
                reactant_list = []
                for react in possible_reactant:
                    reactant_list.append(react.toSingleBonds())

                for possible_product in possible_products:
                    product_list = []
                    for prod in possible_product:
                        product_list.append(prod.toSingleBonds())

                    targetReaction = RMGReaction(reactants=list(reactant_list),
                                                 products=list(product_list))

                    if targetReaction.isIsomorphic(testReaction):
                        logging.info("IRC calculation was successful!")
                        return True
            logging.info("IRC calculation failed for {} :(".format(calc.label))
            return False