Пример #1
0
    def from_file(cls, filename: Union[str, Path], read_molecules: bool = True):
        """
        Parse an AutoTS workflow input file and store its data into an
            TSInput object.

        Args:
            filename (str): Path to an existing AutoTS input file.
            read_molecules (bool): If True, also process all reactant and
                product files

        Returns:
            autots_input: TSInput object
        """

        if isinstance(filename, Path):
            fn = filename.as_posix()
        else:
            fn = filename

        input_file = AutoTSInput()
        input_file.read(fn)

        keywords = input_file._keywords.keys()
        autots_variables = dict()

        for keyword in keywords:
            autots_variables[keyword] = input_file[keyword]

        gen_variables = copy.deepcopy(input_file._jaguar_user_keys)

        if read_molecules:
            base_dir = Path(filename).parent

            reactants = input_file.getValue("reactant")
            products = input_file.getValue("product")

            rct_mols = [maestro_file_to_molecule(base_dir / r)[0]
                        for r in reactants]
            pro_mols = [maestro_file_to_molecule(base_dir / p)[0]
                        for p in products]
        else:
            rct_mols = list()
            pro_mols = list()

        return cls(rct_mols, pro_mols, autots_variables, gen_variables)
Пример #2
0
    def test_to_from_file(self):
        writing = TSInput([self.reactant_1, self.reactant_2],
                              [self.product],
                              self.autots_variables,
                              self.gen_variables)
        writing.write("test.in", write_molecules=True)

        self.assertEqual(self.reactant_1, maestro_file_to_molecule("rct_0.mae")[0])
        self.assertEqual(self.reactant_2, maestro_file_to_molecule("rct_1.mae")[0])
        self.assertEqual(self.product, maestro_file_to_molecule("pro_0.mae")[0])

        reading = TSInput.from_file("test.in", read_molecules=True)
        self.assertEqual(reading.reactants[0], writing.reactants[0])
        self.assertEqual(reading.reactants[1], writing.reactants[1])
        self.assertEqual(reading.products[0], writing.products[0])

        for k, v in writing.autots_variables.items():
            self.assertEqual(v, reading.autots_variables[k])
        for k, v in writing.gen_variables.items():
            self.assertEqual(v, reading.gen_variables[k])
Пример #3
0
    def setUp(self) -> None:
        self.reactant_1 = maestro_file_to_molecule(
            test_dir / "autots_success_partial" / "rct1.mae")[0]

        self.reactant_2 = maestro_file_to_molecule(
            test_dir / "autots_success_partial" / "rct2.mae")[0]

        self.product = maestro_file_to_molecule(
            test_dir / "autots_success_partial" / "pro.mae")[0]

        self.autots_variables = {"free_energy": True,
                                 "require_irc_success": True,
                                 "ts_vet_max_freq": -40.0,
                                 "units": "ev",
                                 "flexible_metal_coordination": True}

        self.gen_variables = {"dftname": "wb97x-d",
                              "basis": "def2-tzvpd",
                              "babel": "xyz",
                              "ip472": 2,  # Output all steps of geometry optimization in *.mae
                              # "ip172": 2,  # Print RESP file
                              "ip175": 2,  # Print XYZ files
                              # "ifreq": 1,  # Frequency calculation
                              # "irder": 1,  # IR vibrational modes calculated
                              # "nmder": 2,  # Numerical second derivatives
                              "nogas": 2,  # Skip gas-phase optimization, if PCM is used
                              "maxitg": 250,  # Maximum number of geometry optimization iterations
                              # "intopt_switch": 0,  # Do not switch from internal to Cartesian coordinates
                              # "optcoord_update": 0,  # Do not run checks to change coordinate system
                              # "props_each_step": 1,  # Calculate properties at each optimization step
                              # "iaccg": 5  # Tight convergence criteria for optimization
                              # "mulken": 1,  # Calculate Mulliken properties by atom
                              "maxit": 400,  # Maximum number of SCF iterations
                              "iacc": 2,  # Use "accurate" SCF convergence criteria
                              # "noauto": 3  # All calculations done on fine grid
                              "isymm": 0,  # Do not use symmetry
                              # "espunit": 6  # Electrostatic potential in units of eV
                              }
    def test_maestro_file_to_molecule(self):
        molecules = maestro_file_to_molecule(molecule_dir / "ec.01.mae")
        self.assertEqual(len(molecules), 1)

        elements = [str(s) for s in molecules[0].species]
        self.assertSequenceEqual(
            elements, ["O", "C", "C", "O", "O", "C", "H", "H", "H", "H"])

        positions = [[0.292719, -1.186596, -0.240504],
                     [-0.708427, -0.361958, 0.069717],
                     [1.542315, -0.497739, -0.080547],
                     [-1.855122, -0.696497, 0.151131],
                     [-0.274057, 0.881704, 0.277870],
                     [1.116388, 0.963738, -0.070584],
                     [2.189227, -0.755905, -0.912950],
                     [1.987489, -0.814710, 0.861406],
                     [1.194818, 1.433330, -1.050016],
                     [1.626845, 1.559988, 0.679031]]

        for ii, line in enumerate(positions):
            self.assertListEqual(line, list(molecules[0].cart_coords[ii]))
Пример #5
0
    def __init__(self, filename: str, allow_failure: Optional[bool] = False,
                 parse_molecules: Optional[bool] = True):
        """
        Args:
            filename (str): Path to Jaguar output file to be parsed
            allow_failure (bool): If True (default False), do not raise an
                exception if parsing fails. Capture what information can be
                parsed.
            parse_molecules (bool): If True (default), then in addition to
                parsing the Jaguar output file provided by filename, any
                molecule (*.mae) files referenced in this output file will be
                parsed.

        Returns:
            None
        """

        self.filename = filename
        self.data = dict()
        if self.filename != "":
            base_dir = Path(self.filename).resolve().parent
            try:
                jag_out = JaguarOutput(output=filename, partial_ok=allow_failure)
            except StopIteration:
                raise JaguarOutputParseError

            self.data["job_name"] = jag_out.name
            self.data["full_filename"] = jag_out.filename
            self.data["job_id"] = jag_out.job_id
            self.data["parsing_error"] = jag_out.parsing_error
            self.data["fatal_error"] = jag_out.fatal_error
            self.data["point_group"] = jag_out.point_group

            if jag_out.status == 1:
                self.data["success"] = True
            else:
                self.data["success"] = False

            self.data["start_time"] = jag_out.start_time
            self.data["end_time"] = jag_out.end_time

            if self.data["start_time"] is not None and self.data["end_time"] is not None:
                self.data["walltime"] = (self.data["end_time"] - self.data["start_time"]).total_seconds()
            else:
                self.data["walltime"] = None

            self.data["input"] = dict()
            self.data["input"]["basis"] = jag_out.basis
            self.data["input"]["functional"] = jag_out.functional
            self.data["input"]["method"] = jag_out.method
            self.data["input"]["canonical_orbitals"] = jag_out.canonical_orbitals
            self.data["input"]["charge"] = jag_out.charge
            self.data["input"]["multiplicity"] = jag_out.multiplicity
            self.data["input"]["basis_functions"] = jag_out.nbasis
            self.data["input"]["num_electrons"] = jag_out.nelectron
            self.data["input"]["input_file"] = jag_out.mae_in
            self.data["input"]["solvation"] = jag_out.opts.solvation

            self.data["energy_trajectory"] = list()
            for opt_step in jag_out.geopt_step:
                parsed = parse_jaguar_results(opt_step)
                self.data["energy_trajectory"].append(parsed["scf_energy"])

            self.data["output"] = parse_jaguar_results(jag_out._results)
            self.data["output"]["irc"] = [parse_jaguar_results(j) for j in jag_out.irc_step]
            self.data["output"]["scan"] = [parse_jaguar_results(j) for j in jag_out.scan_step]
            self.data["output"]["output_file"] = jag_out.mae_out

            if parse_molecules:
                self.data["input"]["molecule"] = maestro_file_to_molecule(
                    base_dir / self.data["input"]["input_file"])[0]
                self.data["molecule_trajectory"] = maestro_file_to_molecule(
                    base_dir / self.data["output"]["output_file"])
                self.data["output"]["molecule"] = self.data["molecule_trajectory"][-1]

            else:
                self.data["input"]["molecule"] = None
                self.data["output"]["molecule"] = None
                self.data["molecule_trajectory"] = None
Пример #6
0
    def generate_doc(self):
        """
        Generate a dictionary from the inputs and outputs of the various
        Jaguar calculations involved in the AutoTS calculation.

        Args:
            None

        Returns:
            d (dict): The compiled results from the calculation.
        """

        if "autots.in" not in self.file_names:
            raise ValueError("Input file is not in path!")

        d = dict()
        d["schema"] = {"code": "mpcat", "version": version}
        d["path"] = self.path.as_posix()
        d["hash"] = compute_state_hash(self.documents)

        calc_data = dict()
        for document in self.documents:
            if document.name == "calc.json":
                calc_data = loads(open(document.as_posix()).read())
                break

        d["rxnid"] = calc_data.get("rxnid")
        d["tags"] = calc_data.get("tags")
        d["additional_data"] = calc_data.get("additional_data")
        d["name"] = calc_data.get("name")
        d["charge"] = calc_data.get("charge")
        d["spin_multiplicity"] = calc_data.get("spin_multiplicity")
        d["nelectrons"] = calc_data.get("nelectrons")

        autots_input = TSInput.from_file(self.path / "autots.in",
                                         read_molecules=True)

        d["input"] = {
            "reactants": autots_input.reactants,
            "products": autots_input.products,
            "autots_variables": autots_input.autots_variables,
            "gen_variables": autots_input.gen_variables
        }

        output_document = None
        for document in self.documents:
            if document.name == "AutoTS.T9XnCsLi.out":
                output_document = document
                break
        if output_document is None:
            raise ValueError("Output file is not in path!")

        autots_output = TSOutput(output_document.as_posix())

        d["calculation_names"] = autots_output.data.get("calculations")
        if d["calculation_names"] is None:
            d["calculation_names"] = list()

        d["warnings"] = autots_output.data["warnings"]
        d["errors"] = autots_output.data["errors"]
        d["completed"] = autots_output.data["complete"]
        d["walltime"] = autots_output.data["walltime"]
        if d["completed"]:
            d["output"] = {
                "temperature":
                autots_output.data["output"]["temperature_dependence"],
                "free_energy":
                autots_output.data["output"]["gibbs_energies"],
                "separated_energies":
                autots_output.data["output"]["separated_energies"],
                "complex_energies":
                autots_output.data["output"]["complex_energies"],
                "optimized_structure_energies":
                autots_output.data["output"]["struct_energies"]
            }
            d["diagnostic"] = autots_output.data["diagnostic"]
        else:
            d["output"] = dict()
            #TODO: could actually parse diagnostic for failed calcs; just requires tweaking of regex
            d["diagnostic"] = dict()

        d["calcs"] = list()
        for calculation in d.get("calculation_names", list()):
            found = False
            for document in self.documents:
                if (calculation + ".out") in document.name:
                    found = True
                    try:
                        jag_out = JagOutput(document.as_posix())
                        d["calcs"].append(jag_out.data)
                    except (JaguarParseError, JaguarOutputParseError):
                        print("Error parsing " + calculation + " in path " +
                              self.path.as_posix())
                        break

            if not found:
                print("Expected calculation {} missing from path {}!".format(
                    calculation, self.path.as_posix()))

        full_paths = [d for d in self.documents if "full_path.mae" in d.name]
        if len(full_paths) > 0:
            d["output"]["path_molecules"] = maestro_file_to_molecule(
                full_paths[0].as_posix())

        rct_complexes = [
            d for d in self.documents if "reactant_complex.mae" in d.name
        ]
        if len(rct_complexes) > 0:
            d["output"]["reactant_complex"] = maestro_file_to_molecule(
                rct_complexes[0].as_posix())[0]

        pro_complexes = [
            d for d in self.documents if "product_complex.mae" in d.name
        ]
        if len(pro_complexes) > 0:
            d["output"]["product_complex"] = maestro_file_to_molecule(
                pro_complexes[0].as_posix())[0]

        d["last_updated"] = datetime.now()
        return d