Esempio n. 1
0
    def verify_output_file(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.output_file_path):
            logging.debug("Output file {0} does not (yet) exist.".format(
                self.output_file_path))
            return False

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

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

        with open(self.output_file_path) 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:
                        success_keys_found[element] = True

                if "InChI=" in line:
                    log_file_inchi = line  # output files should take up to 240 characters of the name in the input file
                    inchi_found = True
                    if self.unique_id_long in log_file_inchi:
                        pass
                    elif self.unique_id_long.startswith(log_file_inchi):
                        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(log_file_inchi,
                                            self.unique_id_long))
                        # Use only up to first 80 characters to match due to MOPAC bug which deletes 81st character of InChI string
                        if self.unique_id_long.startswith(log_file_inchi[: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(success_keys_found.values()):
            logging.error(
                'Not all of the required keywords for success were found in the output file!'
            )
            return False

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

        # Compare the optimized geometry to the original molecule
        qm_data = self.parse()
        cclib_mol = Molecule()
        cclib_mol.from_xyz(qm_data.atomicNumbers, qm_data.atomCoords.value)
        test_mol = self.molecule.to_single_bonds()
        if not cclib_mol.is_isomorphic(test_mol):
            logging.info(
                "Incorrect connectivity for optimized geometry in file {0}".
                format(self.output_file_path))
            return False

        logging.info("Successful {1} quantum result in {0}".format(
            self.output_file_path, self.__class__.__name__))
        return True