示例#1
0
    def _in_database(self, molecule):
        """
        Check if a molecule is already present in the database, which has already been
        queried on relevant formulae and narrowed to self.all_relevant_docs.
        If no docs present, assume fragment is not present
        """
        if len(self.all_relevant_docs) == 0:
            return False

        # otherwise, look through the docs for an entry with an isomorphic molecule with
        # equivalent charge and multiplicity
        else:
            new_mol_graph = MoleculeGraph.with_local_env_strategy(
                molecule, OpenBabelNN(), reorder=False, extend_structure=False)
            for doc in self.all_relevant_docs:
                if molecule.composition.reduced_formula == doc[
                        "formula_pretty"]:
                    old_mol = Molecule.from_dict(
                        doc["input"]["initial_molecule"])
                    old_mol_graph = MoleculeGraph.with_local_env_strategy(
                        old_mol,
                        OpenBabelNN(),
                        reorder=False,
                        extend_structure=False)
                    # If such an equivalent molecule is found, return true
                    if new_mol_graph.isomorphic_to(
                            old_mol_graph
                    ) and molecule.charge == old_mol_graph.molecule.charge and molecule.spin_multiplicity == old_mol_graph.molecule.spin_multiplicity:
                        return True
            # Otherwise, return false
            return False
示例#2
0
 def test_assimilate_unstable_opt(self):
     drone = QChemDrone(
         runs=[
             "opt_0", "freq_0", "opt_1", "freq_1", "opt_2", "freq_2",
             "opt_3", "freq_3"
         ],
         additional_fields={"special_run_type": "frequency_flattener"})
     doc = drone.assimilate(path=os.path.join(module_dir, "..",
                                              "test_files",
                                              "2620_complete"),
                            input_file="mol.qin",
                            output_file="mol.qout",
                            multirun=False)
     self.assertEqual(doc["input"]["job_type"], "opt")
     self.assertEqual(doc["output"]["job_type"], "opt")
     self.assertEqual(doc["output"]["final_energy"], "unstable")
     self.assertEqual(doc["smiles"], "[S](=O)[N]S[C]")
     self.assertEqual(doc["state"], "unsuccessful")
     self.assertEqual(doc["walltime"], None)
     self.assertEqual(doc["cputime"], None)
     self.assertEqual(doc["formula_pretty"], "CS2NO")
     self.assertEqual(doc["formula_anonymous"], "ABCD2")
     self.assertEqual(doc["chemsys"], "C-N-O-S")
     self.assertEqual(doc["pointgroup"], "C1")
     self.assertEqual(doc["orig"]["rem"],
                      doc["calcs_reversed"][-1]["input"]["rem"])
     self.assertEqual(doc["orig"]["molecule"],
                      doc["calcs_reversed"][-1]["input"]["molecule"])
     orig_molgraph = MoleculeGraph.with_local_env_strategy(
         Molecule.from_dict(doc["orig"]["molecule"]), OpenBabelNN())
     initial_molgraph = MoleculeGraph.with_local_env_strategy(
         Molecule.from_dict(doc["input"]["initial_molecule"]),
         OpenBabelNN())
     self.assertEqual(orig_molgraph.isomorphic_to(initial_molgraph), True)
示例#3
0
 def _check_for_structure_changes(self):
     initial_mol_graph = MoleculeGraph.with_local_env_strategy(
         self.data["initial_molecule"],
         OpenBabelNN(),
         reorder=False,
         extend_structure=False)
     initial_graph = initial_mol_graph.graph
     last_mol_graph = MoleculeGraph.with_local_env_strategy(
         self.data["molecule_from_last_geometry"],
         OpenBabelNN(),
         reorder=False,
         extend_structure=False)
     last_graph = last_mol_graph.graph
     if initial_mol_graph.isomorphic_to(last_mol_graph):
         self.data["structure_change"] = "no_change"
     else:
         if nx.is_connected(
                 initial_graph.to_undirected()) and not nx.is_connected(
                     last_graph.to_undirected()):
             self.data["structure_change"] = "unconnected_fragments"
         elif last_graph.number_of_edges() < initial_graph.number_of_edges(
         ):
             self.data["structure_change"] = "fewer_bonds"
         elif last_graph.number_of_edges() > initial_graph.number_of_edges(
         ):
             self.data["structure_change"] = "more_bonds"
         else:
             self.data["structure_change"] = "bond_change"
示例#4
0
 def test_assimilate_opt_with_hidden_changes_from_handler(self):
     drone = QChemDrone(
         additional_fields={"special_run_type": "frequency_flattener"})
     doc = drone.assimilate(path=os.path.join(module_dir, "..",
                                              "test_files",
                                              "1746_complete"),
                            input_file="mol.qin",
                            output_file="mol.qout",
                            multirun=False)
     self.assertEqual(doc["input"]["job_type"], "opt")
     self.assertEqual(doc["output"]["job_type"], "freq")
     self.assertEqual(doc["output"]["final_energy"], -303.835532370106)
     self.assertEqual(doc["smiles"], "O1C(=CC1=O)[CH]")
     self.assertEqual(doc["state"], "successful")
     self.assertEqual(doc["num_frequencies_flattened"], 0)
     self.assertEqual(doc["walltime"], 631.54)
     self.assertEqual(doc["cputime"], 7471.17)
     self.assertEqual(doc["formula_pretty"], "HC2O")
     self.assertEqual(doc["formula_anonymous"], "ABC2")
     self.assertEqual(doc["chemsys"], "C-H-O")
     self.assertEqual(doc["pointgroup"], "C1")
     self.assertEqual(doc["orig"]["rem"],
                      doc["calcs_reversed"][-1]["input"]["rem"])
     orig_molgraph = MoleculeGraph.with_local_env_strategy(
         Molecule.from_dict(doc["orig"]["molecule"]),
         OpenBabelNN(),
         reorder=False,
         extend_structure=False)
     initial_molgraph = MoleculeGraph.with_local_env_strategy(
         Molecule.from_dict(doc["input"]["initial_molecule"]),
         OpenBabelNN(),
         reorder=False,
         extend_structure=False)
     self.assertEqual(orig_molgraph.isomorphic_to(initial_molgraph), False)
示例#5
0
    def test_generate(self):
        autots_input = TSInput([self.reactant_1, self.reactant_2],
                                   [self.product],
                                   self.autots_variables,
                                   self.gen_variables)

        self.assertEqual(
            metal_edge_extender(
                MoleculeGraph.with_local_env_strategy(
                    self.reactant_1, OpenBabelNN()
                )
            ),
            autots_input.reactants[0])
        self.assertEqual(
            metal_edge_extender(
                MoleculeGraph.with_local_env_strategy(
                    self.reactant_2, OpenBabelNN()
                )
            ),
            autots_input.reactants[1])
        self.assertEqual(
            metal_edge_extender(
                MoleculeGraph.with_local_env_strategy(
                    self.product, OpenBabelNN()
                )
            ),
            autots_input.products[0])
        self.assertDictEqual(self.autots_variables, autots_input.autots_variables)
        self.assertDictEqual(self.gen_variables, autots_input.gen_variables)
示例#6
0
    def setUpClass(cls):
        if ob:
            EC_mg = MoleculeGraph.with_local_env_strategy(
                Molecule.from_file(os.path.join(test_dir, "EC.xyz")),
                OpenBabelNN())
            cls.EC_mg = metal_edge_extender(EC_mg)

            LiEC_mg = MoleculeGraph.with_local_env_strategy(
                Molecule.from_file(os.path.join(test_dir, "LiEC.xyz")),
                OpenBabelNN())
            cls.LiEC_mg = metal_edge_extender(LiEC_mg)

            LEDC_mg = MoleculeGraph.with_local_env_strategy(
                Molecule.from_file(os.path.join(test_dir, "LEDC.xyz")),
                OpenBabelNN())
            cls.LEDC_mg = metal_edge_extender(LEDC_mg)

            LEMC_mg = MoleculeGraph.with_local_env_strategy(
                Molecule.from_file(os.path.join(test_dir, "LEMC.xyz")),
                OpenBabelNN())
            cls.LEMC_mg = metal_edge_extender(LEMC_mg)

            cls.LiEC_reextended_entries = []
            entries = loadfn(
                os.path.join(test_dir, "LiEC_reextended_entries.json"))
            for entry in entries:
                if "optimized_molecule" in entry["output"]:
                    mol = entry["output"]["optimized_molecule"]
                else:
                    mol = entry["output"]["initial_molecule"]
                E = float(entry["output"]["final_energy"])
                H = float(entry["output"]["enthalpy"])
                S = float(entry["output"]["entropy"])
                mol_entry = MoleculeEntry(
                    molecule=mol,
                    energy=E,
                    enthalpy=H,
                    entropy=S,
                    entry_id=entry["task_id"],
                )
                if mol_entry.formula == "Li1":
                    if mol_entry.charge == 1:
                        cls.LiEC_reextended_entries.append(mol_entry)
                else:
                    cls.LiEC_reextended_entries.append(mol_entry)

            # dumpfn(cls.LiEC_reextended_entries, "unittest_input_molentries.json")

            with open(os.path.join(test_dir, "unittest_RN_build.pkl"),
                      "rb") as input:
                cls.RN_build = pickle.load(input)

            with open(os.path.join(test_dir, "unittest_RN_pr_solved.pkl"),
                      "rb") as input:
                cls.RN_pr_solved = pickle.load(input)
示例#7
0
    def run_task(self, fw_spec):
        input_file = os.path.join(self.get("write_to_dir", ""),
                                  self.get("input_file", "mol.qin"))

        # if a full QChemDictSet object was provided
        if hasattr(self["qchem_input_set"], "write_file"):
            qcin = self["qchem_input_set"]
        # if a molecule is being passed through fw_spec
        elif fw_spec.get("prev_calc_molecule"):
            prev_calc_mol = fw_spec.get("prev_calc_molecule")
            # if a molecule is also passed as an optional parameter
            if self.get("molecule"):
                mol = self.get("molecule")
                # check if mol and prev_calc_mol are isomorphic
                mol_graph = MoleculeGraph.with_local_env_strategy(
                    mol, OpenBabelNN(), reorder=False, extend_structure=False)
                prev_mol_graph = MoleculeGraph.with_local_env_strategy(
                    prev_calc_molecule,
                    OpenBabelNN(),
                    reorder=False,
                    extend_structure=False,
                )
                # If they are isomorphic, aka a previous FW has not changed bonding,
                # then we will use prev_calc_mol. If bonding has changed, we will use mol.
                if mol_graph.isomorphic_to(prev_mol_graph):
                    mol = prev_calc_mol
                elif self["qchem_input_set"] != "OptSet":
                    print(
                        "WARNING: Molecule from spec is not isomorphic to passed molecule!"
                    )
                    mol = prev_calc_mol
                else:
                    print(
                        "Not using prev_calc_mol as it is not isomorphic to passed molecule!"
                    )
            else:
                mol = prev_calc_mol

            qcin_cls = load_class("pymatgen.io.qchem.sets",
                                  self["qchem_input_set"])
            qcin = qcin_cls(mol, **self.get("qchem_input_params", {}))
        # if a molecule is only included as an optional parameter
        elif self.get("molecule"):
            qcin_cls = load_class("pymatgen.io.qchem.sets",
                                  self["qchem_input_set"])
            qcin = qcin_cls(self.get("molecule"),
                            **self.get("qchem_input_params", {}))
        # if no molecule is present raise an error
        else:
            raise KeyError(
                "No molecule present, add as an optional param or check fw_spec"
            )
        qcin.write(input_file)
示例#8
0
    def test_nn_orders(self):
        strat = OpenBabelNN()

        acetylene = strat.get_nn_info(self.acetylene, 0)
        self.assertEqual(acetylene[0]["weight"], 3)
        self.assertEqual(acetylene[1]["weight"], 1)

        # Currently, benzene bonds register either as double or single,
        # not aromatic
        # Instead of searching for aromatic bonds, we check that bonds are
        # detected in the same way from both sides
        self.assertEqual(strat.get_nn_info(self.benzene, 0)[0]["weight"],
                         strat.get_nn_info(self.benzene, 1)[0]["weight"])
示例#9
0
    def test_nn_orders(self):
        strat = OpenBabelNN()

        acetylene = strat.get_nn_info(self.acetylene, 0)
        self.assertEqual(acetylene[0]["weight"], 3)
        self.assertEqual(acetylene[1]["weight"], 1)

        # Currently, benzene bonds register either as double or single,
        # not aromatic
        # Instead of searching for aromatic bonds, we check that bonds are
        # detected in the same way from both sides
        self.assertEqual(strat.get_nn_info(self.benzene, 0)[0]["weight"],
                         strat.get_nn_info(self.benzene, 1)[0]["weight"])
示例#10
0
    def test_nn_length(self):
        strat = OpenBabelNN(order=False)

        benzene_bonds = strat.get_nn_info(self.benzene, 0)

        c_bonds = [b for b in benzene_bonds if str(b["site"].specie) == "C"]
        h_bonds = [b for b in benzene_bonds if str(b["site"].specie) == "H"]

        self.assertAlmostEqual(c_bonds[0]["weight"], 1.41, 2)
        self.assertAlmostEqual(h_bonds[0]["weight"], 1.02, 2)

        self.assertAlmostEqual(
            strat.get_nn_info(self.acetylene, 0)[0]["weight"], 1.19, 2)
示例#11
0
    def test_nn_length(self):
        strat = OpenBabelNN(order=False)

        benzene_bonds = strat.get_nn_info(self.benzene, 0)

        c_bonds = [b for b in benzene_bonds if str(b["site"].specie) == "C"]
        h_bonds = [b for b in benzene_bonds if str(b["site"].specie) == "H"]

        self.assertAlmostEqual(c_bonds[0]["weight"], 1.41, 2)
        self.assertAlmostEqual(h_bonds[0]["weight"], 1.02, 2)

        self.assertAlmostEqual(strat.get_nn_info(self.acetylene, 0)[0]["weight"],
                               1.19,
                               2)
示例#12
0
    def setUpClass(cls) -> None:
        if ob:
            cls.LiEC_reextended_entries = []
            entries = loadfn(
                os.path.join(test_dir, "LiEC_reextended_entries.json"))
            for entry in entries:
                if "optimized_molecule" in entry["output"]:
                    mol = entry["output"]["optimized_molecule"]
                else:
                    mol = entry["output"]["initial_molecule"]
                E = float(entry["output"]["final_energy"])
                H = float(entry["output"]["enthalpy"])
                S = float(entry["output"]["entropy"])
                mol_entry = MoleculeEntry(
                    molecule=mol,
                    energy=E,
                    enthalpy=H,
                    entropy=S,
                    entry_id=entry["task_id"],
                )
                if mol_entry.formula == "Li1":
                    if mol_entry.charge == 1:
                        cls.LiEC_reextended_entries.append(mol_entry)
                else:
                    cls.LiEC_reextended_entries.append(mol_entry)

            LiEC_mg = MoleculeGraph.with_local_env_strategy(
                Molecule.from_file(os.path.join(test_dir, "LiEC.xyz")),
                OpenBabelNN())
            cls.LiEC_mg = metal_edge_extender(LiEC_mg)

            LiEC_RO_mg = MoleculeGraph.with_local_env_strategy(
                Molecule.from_file(os.path.join(test_dir, "LiEC_RO.xyz")),
                OpenBabelNN())
            cls.LiEC_RO_mg = metal_edge_extender(LiEC_RO_mg)

            cls.LiEC_entry = None
            cls.LiEC_RO_entry = None

            for entry in cls.LiEC_reextended_entries:
                if (entry.formula == "C3 H4 Li1 O3" and entry.charge == 0
                        and entry.num_bonds == 12
                        and cls.LiEC_mg.isomorphic_to(entry.mol_graph)):
                    cls.LiEC_entry = entry
                elif (entry.formula == "C3 H4 Li1 O3" and entry.charge == 0
                      and entry.num_bonds == 11
                      and cls.LiEC_RO_mg.isomorphic_to(entry.mol_graph)):
                    cls.LiEC_RO_entry = entry
                if cls.LiEC_entry is not None and cls.LiEC_RO_entry is not None:
                    break
示例#13
0
def find_mol_entry_from_xyz_and_charge(mol_entries, xyz_file_path, charge):
    """
    given a file 'molecule.xyz', find the mol_entry corresponding to the
    molecule graph with given charge
    """
    target_mol_graph = MoleculeGraph.with_local_env_strategy(
        Molecule.from_file(xyz_file_path), OpenBabelNN())

    # correction to the molecule graph
    target_mol_graph = metal_edge_extender(target_mol_graph)

    match = False
    index = -1
    while not match:
        index += 1
        mol_entry = mol_entries[index]
        species_mol_graph = mol_entry.mol_graph

        if mol_entry.charge == charge:
            match = target_mol_graph.isomorphic_to(species_mol_graph)

    if match:
        return mol_entry
    else:
        return None
    def test_mol_graph_to_schrodinger_struct(self):
        self.molecule.set_charge_and_spin(charge=-1)
        mg = MoleculeGraph.with_local_env_strategy(self.molecule,
                                                   OpenBabelNN())

        struct = mol_graph_to_schrodinger_struct(mg)

        self.assertListEqual([a.element for a in struct.molecule[1].atom],
                             [str(s) for s in mg.molecule.species])

        self.assertEqual(struct.formal_charge, -1)

        for ii in range(len(mg.molecule)):
            self.assertListEqual(list(mg.molecule.cart_coords[ii]),
                                 list(struct.molecule[1].atom[ii + 1].xyz))

        struct_bonds = set()
        for bond in struct.bond:
            struct_bonds.add(
                tuple(sorted([bond.atom1.index - 1, bond.atom2.index - 1])))

        mg_bonds = set()
        for bond in mg.graph.edges():
            mg_bonds.add(tuple(sorted([bond[0], bond[1]])))

        self.assertSetEqual(struct_bonds, mg_bonds)
示例#15
0
    def __init__(
        self,
        molecule: Molecule,
        energy: float,
        correction: float = 0.0,
        enthalpy: Optional[float] = None,
        entropy: Optional[float] = None,
        parameters: Optional[Dict] = None,
        entry_id: Optional[Any] = None,
        attribute=None,
        mol_graph: Optional[MoleculeGraph] = None,
    ):
        self.uncorrected_energy = energy
        self.correction = correction
        self.enthalpy = enthalpy
        self.entropy = entropy
        self.parameters = parameters if parameters else {}
        self.entry_id = entry_id
        self.attribute = attribute

        if not mol_graph:
            mol_graph = MoleculeGraph.with_local_env_strategy(
                molecule, OpenBabelNN())
            self.mol_graph = metal_edge_extender(mol_graph)
        else:
            self.mol_graph = mol_graph
示例#16
0
    def test_mol_to_mol_graph(self):
        mol = Molecule.from_file(
            (test_dir / "molecules" / "li2co3_1.xyz").as_posix())
        mg = MoleculeGraph.with_local_env_strategy(mol, OpenBabelNN())
        mg = metal_edge_extender(mg)

        self.assertEqual(mg, mol_to_mol_graph(mol))
示例#17
0
    def test_construction(self):
        edges_frag = {(e[0], e[1]): {"weight":1.0} for e in self.pc_frag1_edges}
        mol_graph = MoleculeGraph.with_edges(self.pc_frag1, edges_frag)
        #dumpfn(mol_graph.as_dict(), os.path.join(module_dir,"pc_frag1_mg.json"))
        ref_mol_graph = loadfn(os.path.join(module_dir, "pc_frag1_mg.json"))
        self.assertEqual(mol_graph, ref_mol_graph)
        self.assertEqual(mol_graph.graph.adj, ref_mol_graph.graph.adj)
        for node in mol_graph.graph.nodes:
            self.assertEqual(mol_graph.graph.node[node]["specie"],
                             ref_mol_graph.graph.node[node]["specie"])
            for ii in range(3):
                self.assertEqual(
                    mol_graph.graph.node[node]["coords"][ii],
                    ref_mol_graph.graph.node[node]["coords"][ii])

        edges_pc = {(e[0], e[1]): {"weight":1.0} for e in self.pc_edges}
        mol_graph = MoleculeGraph.with_edges(self.pc, edges_pc)
        #dumpfn(mol_graph.as_dict(), os.path.join(module_dir,"pc_mg.json"))
        ref_mol_graph = loadfn(os.path.join(module_dir, "pc_mg.json"))
        self.assertEqual(mol_graph, ref_mol_graph)
        self.assertEqual(mol_graph.graph.adj, ref_mol_graph.graph.adj)
        for node in mol_graph.graph:
            self.assertEqual(mol_graph.graph.node[node]["specie"],
                             ref_mol_graph.graph.node[node]["specie"])
            for ii in range(3):
                self.assertEqual(
                    mol_graph.graph.node[node]["coords"][ii],
                    ref_mol_graph.graph.node[node]["coords"][ii])

        mol_graph_edges = MoleculeGraph.with_edges(self.pc, edges=edges_pc)
        mol_graph_strat = MoleculeGraph.with_local_env_strategy(self.pc, OpenBabelNN(), reorder=False, extend_structure=False)
        self.assertTrue(mol_graph_edges.isomorphic_to(mol_graph_strat))
示例#18
0
    def __init__(self, db_entry, use_metal_edge_extender=True, optimized=True):

        # id
        identifier = str(db_entry["_id"])

        # pymatgen mol
        if optimized:
            if db_entry["state"] != "successful":
                raise UnsuccessfulEntryError
            try:
                pymatgen_mol = pymatgen.Molecule.from_dict(
                    db_entry["output"]["optimized_molecule"])
            except KeyError:
                pymatgen_mol = pymatgen.Molecule.from_dict(
                    db_entry["output"]["initial_molecule"])
                print("use initial_molecule for id: {}; job type:{} ".format(
                    db_entry["_id"], db_entry["output"]["job_type"]))
        else:
            pymatgen_mol = pymatgen.Molecule.from_dict(
                db_entry["input"]["initial_molecule"])

        # mol graph
        mol_graph = MoleculeGraph.with_local_env_strategy(
            pymatgen_mol, OpenBabelNN(order=True))
        if use_metal_edge_extender:
            mol_graph = metal_edge_extender(self.mol_graph)

        # free energy
        free_energy = self._get_free_energy(db_entry, self.id, self.formula)

        # init superclass
        super(MoleculeWrapperTaskCollection,
              self).__init__(mol_graph, free_energy, identifier)
示例#19
0
 def test_babel_PC_defaults(self):
     pytest.importorskip("openbabel", reason="OpenBabel not installed")
     fragmenter = Fragmenter(molecule=self.pc)
     self.assertEqual(fragmenter.open_rings, False)
     self.assertEqual(fragmenter.opt_steps, 10000)
     default_mol_graph = MoleculeGraph.with_local_env_strategy(self.pc, OpenBabelNN())
     self.assertEqual(fragmenter.mol_graph, default_mol_graph)
     self.assertEqual(fragmenter.total_unique_fragments, 8)
示例#20
0
 def test_babel_PC_defaults(self):
     fragmenter = Fragmenter(molecule=self.pc)
     self.assertEqual(fragmenter.open_rings, False)
     self.assertEqual(fragmenter.opt_steps, 10000)
     default_mol_graph = MoleculeGraph.with_local_env_strategy(
         self.pc, OpenBabelNN(), reorder=False, extend_structure=False)
     self.assertEqual(fragmenter.mol_graph, default_mol_graph)
     self.assertEqual(fragmenter.total_unique_fragments, 8)
示例#21
0
    def setUp(self):
        warnings.simplefilter("ignore")

        self.file = os.path.join(test_dir, "func_group_test.mol")
        self.mol = Molecule.from_file(self.file)
        self.strat = OpenBabelNN()
        self.mg = MoleculeGraph.with_local_env_strategy(self.mol, self.strat)
        self.extractor = FunctionalGroupExtractor(self.mg)
示例#22
0
 def test_babel_PC_old_defaults(self):
     fragmenter = Fragmenter(molecule=self.pc, open_rings=True)
     self.assertEqual(fragmenter.open_rings, True)
     self.assertEqual(fragmenter.opt_steps, 10000)
     default_mol_graph = MoleculeGraph.with_local_env_strategy(
         self.pc, OpenBabelNN())
     self.assertEqual(fragmenter.mol_graph, default_mol_graph)
     self.assertEqual(fragmenter.total_unique_fragments, 13)
示例#23
0
    def from_molecule_document(
        cls,
        mol_doc: Dict,
        correction: float = 0.0,
        parameters: Optional[Dict] = None,
        attribute=None,
    ):
        """
        Initialize a MoleculeEntry from a molecule document.

        Args:
            mol_doc: MongoDB molecule document (nested dictionary) that contains the
                molecule information.
            correction: A correction to be applied to the energy. This is used to modify
                the energy for certain analyses. Defaults to 0.0.
            parameters: An optional dict of parameters associated with
                the molecule. Defaults to None.
            attribute: Optional attribute of the entry. This can be used to
                specify that the entry is a newly found compound, or to specify
                a particular label for the entry, or else ... Used for further
                analysis and plotting purposes. An attribute can be anything
                but must be MSONable.
        """
        try:
            if isinstance(mol_doc["molecule"], Molecule):
                molecule = mol_doc["molecule"]
            else:
                molecule = Molecule.from_dict(mol_doc["molecule"])
            energy = mol_doc["energy_Ha"]
            enthalpy = mol_doc["enthalpy_kcal/mol"]
            entropy = mol_doc["entropy_cal/molK"]
            entry_id = mol_doc["task_id"]
        except KeyError as e:
            raise MoleculeEntryError(
                "Unable to construct molecule entry from molecule document; missing "
                f"attribute {e} in `mol_doc`.")

        if "mol_graph" in mol_doc:
            if isinstance(mol_doc["mol_graph"], MoleculeGraph):
                mol_graph = mol_doc["mol_graph"]
            else:
                mol_graph = MoleculeGraph.from_dict(mol_doc["mol_graph"])
        else:
            mol_graph = MoleculeGraph.with_local_env_strategy(
                molecule, OpenBabelNN())
            mol_graph = metal_edge_extender(mol_graph)

        return cls(
            molecule=molecule,
            energy=energy,
            correction=correction,
            enthalpy=enthalpy,
            entropy=entropy,
            parameters=parameters,
            entry_id=entry_id,
            attribute=attribute,
            mol_graph=mol_graph,
        )
示例#24
0
 def filter_fragment_entries(self,fragment_entries):
     self.filtered_entries = []
     for entry in fragment_entries:
         # Check and make sure that PCM dielectric is consistent with principle:
         if "pcm_dielectric" in self.molecule_entry:
             if "pcm_dielectric" not in entry:
                 raise RuntimeError("Principle molecule has a PCM dielectric of " + str(self.molecule_entry["pcm_dielectric"]) + " but a fragment entry has no PCM dielectric! Please only pass fragment entries with PCM details consistent with the principle entry. Exiting...")
             elif entry["pcm_dielectric"] != self.molecule_entry["pcm_dielectric"]:
                 raise RuntimeError("Principle molecule has a PCM dielectric of " + str(self.molecule_entry["pcm_dielectric"]) + " but a fragment entry has a different PCM dielectric! Please only pass fragment entries with PCM details consistent with the principle entry. Exiting...")
         # Build initial and final molgraphs:
         entry["initial_molgraph"] = MoleculeGraph.with_local_env_strategy(Molecule.from_dict(entry["initial_molecule"]),
                                       OpenBabelNN(),
                                       reorder=False,
                                       extend_structure=False)
         entry["final_molgraph"] = MoleculeGraph.with_local_env_strategy(Molecule.from_dict(entry["final_molecule"]),
                                     OpenBabelNN(),
                                     reorder=False,
                                     extend_structure=False)
         # Classify any potential structural change that occured during optimization:
         if entry["initial_molgraph"].isomorphic_to(entry["final_molgraph"]):
             entry["structure_change"] = "no_change"
         else:
             initial_graph = entry["initial_molgraph"].graph
             final_graph = entry["final_molgraph"].graph
             if nx.is_connected(initial_graph.to_undirected()) and not nx.is_connected(final_graph.to_undirected()):
                 entry["structure_change"] = "unconnected_fragments"
             elif final_graph.number_of_edges() < initial_graph.number_of_edges():
                 entry["structure_change"] = "fewer_bonds"
             elif final_graph.number_of_edges() > initial_graph.number_of_edges():
                 entry["structure_change"] = "more_bonds"
             else:
                 entry["structure_change"] = "bond_change"
         found_similar_entry = False
         # Check for uniqueness
         for ii,filtered_entry in enumerate(self.filtered_entries):
             if filtered_entry["formula_pretty"] == entry["formula_pretty"]:
                 if filtered_entry["initial_molgraph"].isomorphic_to(entry["initial_molgraph"]) and filtered_entry["final_molgraph"].isomorphic_to(entry["final_molgraph"]) and filtered_entry["initial_molecule"]["charge"] == entry["initial_molecule"]["charge"]:
                     found_similar_entry = True
                     # If two entries are found that pass the above similarity check, take the one with the lower energy:
                     if entry["final_energy"] < filtered_entry["final_energy"]:
                         self.filtered_entries[ii] = entry
                     # Note that this will essentially choose between singlet and triplet entries assuming both have the same structural details
                     break
         if not found_similar_entry:
             self.filtered_entries += [entry]
示例#25
0
    def run_task(self, fw_spec):
        input_file = os.path.join(self.get("write_to_dir", ""),
                                  self.get("input_file", "mol.qin"))
        # if a molecule is being passed through fw_spec
        if fw_spec.get("prev_calc_molecule"):
            prev_calc_mol = fw_spec.get("prev_calc_molecule")
            # if a molecule is also passed as an optional parameter
            if self.get("molecule"):
                mol = self.get("molecule")
                # check if mol and prev_calc_mol are isomorphic
                mol_graph = MoleculeGraph.with_local_env_strategy(
                    mol, OpenBabelNN(), reorder=False, extend_structure=False)
                prev_mol_graph = MoleculeGraph.with_local_env_strategy(
                    prev_calc_molecule,
                    OpenBabelNN(),
                    reorder=False,
                    extend_structure=False,
                )
                if mol_graph.isomorphic_to(prev_mol_graph):
                    mol = prev_calc_mol
                else:
                    print(
                        "WARNING: Molecule from spec is not isomorphic to passed molecule!"
                    )
            else:
                mol = prev_calc_mol
        elif self.get("molecule"):
            mol = self.get("molecule")
        else:
            raise KeyError(
                "No molecule present, add as an optional param or check fw_spec"
            )
        # in the current structure there needs to be a statement for every optional QChem section
        # the code below defaults the section to None if the variable is not passed
        opt = self.get("opt", None)
        pcm = self.get("pcm", None)
        solvent = self.get("solvent", None)

        qcin = QCInput(molecule=mol,
                       rem=self["rem"],
                       opt=opt,
                       pcm=pcm,
                       solvent=solvent)
        qcin.write_file(input_file)
示例#26
0
    def __init__(
        self,
        molecule: Molecule,
        energy: float,
        correction: float = 0.0,
        enthalpy: Optional[float] = None,
        entropy: Optional[float] = None,
        parameters: Optional[Dict] = None,
        entry_id: Optional[Any] = None,
        attribute=None,
        mol_doc: Optional[Dict] = None,
        mol_graph: Optional[MoleculeGraph] = None,
    ):

        self.uncorrected_energy = energy
        self.correction = correction
        self.enthalpy = enthalpy
        self.entropy = entropy
        self.parameters = parameters if parameters else {}
        self.entry_id = entry_id
        self.attribute = attribute
        self.mol_doc = mol_doc if mol_doc else {}
        self.mol_graph = mol_graph

        if self.mol_doc != {}:

            self.enthalpy = self.mol_doc["enthalpy_kcal/mol"]
            self.entropy = self.mol_doc["entropy_cal/molK"]
            self.entry_id = self.mol_doc["task_id"]
            if "mol_graph" in self.mol_doc:
                if isinstance(self.mol_doc["mol_graph"], MoleculeGraph):
                    self.mol_graph = self.mol_doc["mol_graph"]
                else:
                    self.mol_graph = MoleculeGraph.from_dict(
                        self.mol_doc["mol_graph"])
            else:
                mol_graph = MoleculeGraph.with_local_env_strategy(
                    molecule, OpenBabelNN())
                self.mol_graph = metal_edge_extender(mol_graph)
        else:
            if self.mol_graph is None:
                mol_graph = MoleculeGraph.with_local_env_strategy(
                    molecule, OpenBabelNN())
                self.mol_graph = metal_edge_extender(mol_graph)
示例#27
0
def open_ring(mol_graph, bond, opt_steps):
    """
    Function to actually open a ring using OpenBabel's local opt. Given a molecule
    graph and a bond, convert the molecule graph into an OpenBabel molecule, remove
    the given bond, perform the local opt with the number of steps determined by
    self.steps, and then convert the resulting structure back into a molecule graph
    to be returned.
    """
    obmol = BabelMolAdaptor.from_molecule_graph(mol_graph)
    obmol.remove_bond(bond[0][0] + 1, bond[0][1] + 1)
    obmol.localopt(steps=opt_steps, forcefield='uff')
    return MoleculeGraph.with_local_env_strategy(obmol.pymatgen_mol, OpenBabelNN())
示例#28
0
    def test_construction(self):
        edges_frag = {(e[0], e[1]): {
            "weight": 1.0
        }
                      for e in self.pc_frag1_edges}
        mol_graph = MoleculeGraph.with_edges(self.pc_frag1, edges_frag)
        # dumpfn(mol_graph.as_dict(), os.path.join(module_dir,"pc_frag1_mg.json"))
        ref_mol_graph = loadfn(os.path.join(module_dir, "pc_frag1_mg.json"))
        self.assertEqual(mol_graph, ref_mol_graph)
        self.assertEqual(mol_graph.graph.adj, ref_mol_graph.graph.adj)
        for node in mol_graph.graph.nodes:
            self.assertEqual(
                mol_graph.graph.nodes[node]["specie"],
                ref_mol_graph.graph.nodes[node]["specie"],
            )
            for ii in range(3):
                self.assertEqual(
                    mol_graph.graph.nodes[node]["coords"][ii],
                    ref_mol_graph.graph.nodes[node]["coords"][ii],
                )

        edges_pc = {(e[0], e[1]): {"weight": 1.0} for e in self.pc_edges}
        mol_graph = MoleculeGraph.with_edges(self.pc, edges_pc)
        # dumpfn(mol_graph.as_dict(), os.path.join(module_dir,"pc_mg.json"))
        ref_mol_graph = loadfn(os.path.join(module_dir, "pc_mg.json"))
        self.assertEqual(mol_graph, ref_mol_graph)
        self.assertEqual(mol_graph.graph.adj, ref_mol_graph.graph.adj)
        for node in mol_graph.graph:
            self.assertEqual(
                mol_graph.graph.nodes[node]["specie"],
                ref_mol_graph.graph.nodes[node]["specie"],
            )
            for ii in range(3):
                self.assertEqual(
                    mol_graph.graph.nodes[node]["coords"][ii],
                    ref_mol_graph.graph.nodes[node]["coords"][ii],
                )

        mol_graph_edges = MoleculeGraph.with_edges(self.pc, edges=edges_pc)
        mol_graph_strat = MoleculeGraph.with_local_env_strategy(
            self.pc, OpenBabelNN())

        self.assertTrue(mol_graph_edges.isomorphic_to(mol_graph_strat))

        # Check inappropriate strategy
        with self.assertRaises(ValueError):
            MoleculeGraph.with_local_env_strategy(self.pc, VoronoiNN())
示例#29
0
def mol_to_mol_graph(molecule: Union[Molecule, MoleculeGraph]):
    """
    Convert a Molecule to a MoleculeGraph using a default connectivity
    algorithm.

    Args:
        molecule (Molecule): Molecule to be converted

    Returns:
        mol_graph: MoleculeGraph
    """

    if isinstance(molecule, MoleculeGraph):
        return molecule
    else:
        mol_graph = MoleculeGraph.with_local_env_strategy(molecule, OpenBabelNN())
        return metal_edge_extender(mol_graph)
示例#30
0
    def test_verify_with_graphs(self):
        ethane = Molecule.from_file(os.path.join(test_dir, "ethane.mol"))

        # Test bad bond formed
        with self.assertRaises(ValueError):
            bad_bond = GSMIsomerInput(molecule=ethane,
                                      bonds_formed=[(0, 1)],
                                      use_graph=True)

        # Test bad bond broken
        with self.assertRaises(ValueError):
            bad_bond = GSMIsomerInput(molecule=ethane,
                                      bonds_broken=[(1, 2)],
                                      use_graph=True)

        # Test bad angle
        with self.assertRaises(ValueError):
            bad_angle = GSMIsomerInput(molecule=ethane,
                                       angles=[(0, 1, 2)],
                                       use_graph=True)

        # Test bad torsion
        with self.assertRaises(ValueError):
            bad_torsion = GSMIsomerInput(molecule=ethane,
                                         torsions=[(0, 1, 2, 3)],
                                         use_graph=True)

        # Test bad out of plane bend
        with self.assertRaises(ValueError):
            bad_out_of_plane = GSMIsomerInput(molecule=ethane,
                                              out_of_planes=[(0, 1, 2, 3)],
                                              use_graph=True)

        # Test good
        good = GSMIsomerInput(molecule=ethane,
                              bonds_formed=[(0, 7)],
                              angles=[(1, 0, 4)],
                              torsions=[(2, 0, 1, 6)],
                              use_graph=True)
        mg = MoleculeGraph.with_local_env_strategy(ethane, OpenBabelNN())
        self.assertEqual(mg, good.molecule_graph)
示例#31
0
    def test_union_molgraph(self):

        with self.assertRaises(ValueError):
            _ = union_molgraph([])

        # Test "good", well-behaved case
        good_one = MoleculeGraph.with_local_env_strategy(
            Molecule.from_file((test_dir / "molecules" / "union" / "good" /
                                "1.xyz").as_posix()), OpenBabelNN())
        good_one = metal_edge_extender(good_one)
        good_two = MoleculeGraph.with_local_env_strategy(
            Molecule.from_file((test_dir / "molecules" / "union" / "good" /
                                "2.xyz").as_posix()), OpenBabelNN())
        good_two = metal_edge_extender(good_two)
        good_union = MoleculeGraph.with_local_env_strategy(
            Molecule.from_file((test_dir / "molecules" / "union" / "good" /
                                "union.xyz").as_posix()), OpenBabelNN())
        good_union = metal_edge_extender(good_union)

        good = union_molgraph([good_one, good_two])
        self.assertTrue(good_union.isomorphic_to(good))

        # Test "bad" case where proximity might be an issue
        bad_one = MoleculeGraph.with_local_env_strategy(
            Molecule.from_file((test_dir / "molecules" / "union" / "bad" /
                                "1.xyz").as_posix()), OpenBabelNN())
        bad_one = metal_edge_extender(bad_one)
        bad_two = MoleculeGraph.with_local_env_strategy(
            Molecule.from_file((test_dir / "molecules" / "union" / "bad" /
                                "2.xyz").as_posix()), OpenBabelNN())
        bad_two = metal_edge_extender(bad_two)
        bad_union = MoleculeGraph.with_local_env_strategy(
            Molecule.from_file(
                (test_dir / "molecules" / "union" / "bad" / "union.xyz")),
            OpenBabelNN())
        bad_union = metal_edge_extender(bad_union)

        bad = union_molgraph([bad_one, bad_two])
        self.assertTrue(bad_union.isomorphic_to(bad))

        with self.assertRaises(ValueError):
            _ = union_molgraph([bad_one, bad_two], validate_proximity=True)
示例#32
0
    def __init__(self, molecule, optimize=False):
        """
        Instantiation method for FunctionalGroupExtractor.

        :param molecule: Either a filename, a pymatgen.core.structure.Molecule
            object, or a pymatgen.analysis.graphs.MoleculeGraph object.
        :param optimize: Default False. If True, then the input molecule will be
            modified, adding Hydrogens, performing a simple conformer search,
            etc.
        """

        self.molgraph = None

        if isinstance(molecule, str):
            try:
                if optimize:
                    obmol = BabelMolAdaptor.from_file(molecule,
                                                      file_format="mol")
                    # OBMolecule does not contain pymatgen Molecule information
                    # So, we need to wrap the obmol in a BabelMolAdapter
                    obmol.add_hydrogen()
                    obmol.make3d()
                    obmol.localopt()
                    self.molecule = obmol.pymatgen_mol
                else:
                    self.molecule = Molecule.from_file(molecule)
            except OSError:
                raise ValueError("Input must be a valid molecule file, a "
                                 "Molecule object, or a MoleculeGraph object.")

        elif isinstance(molecule, Molecule):
            if optimize:
                obmol = BabelMolAdaptor(molecule)
                obmol.add_hydrogen()
                obmol.make3d()
                obmol.localopt()

                self.molecule = obmol.pymatgen_mol
            else:
                self.molecule = molecule

        elif isinstance(molecule, MoleculeGraph):
            if optimize:
                obmol = BabelMolAdaptor(molecule.molecule)
                obmol.add_hydrogen()
                obmol.make3d()
                obmol.localopt()

                self.molecule = obmol.pymatgen_mol

            else:
                self.molecule = molecule.molecule
                self.molgraph = molecule

        else:
            raise ValueError("Input to FunctionalGroupExtractor must be"
                             "str, Molecule, or MoleculeGraph.")

        if self.molgraph is None:
            self.molgraph = MoleculeGraph.with_local_env_strategy(
                self.molecule,
                OpenBabelNN(),
                reorder=False,
                extend_structure=False)

        # Assign a specie and coordinates to each node in the graph,
        # corresponding to the Site in the Molecule object
        self.molgraph.set_node_attributes()

        self.species = nx.get_node_attributes(self.molgraph.graph, "specie")
示例#33
0
    def get_basic_functional_groups(self, func_groups=None):
        """
        Identify functional groups that cannot be identified by the Ertl method
        of get_special_carbon and get_heteroatoms, such as benzene rings, methyl
        groups, and ethyl groups.

        TODO: Think of other functional groups that are important enough to be
        added (ex: do we need ethyl, butyl, propyl?)

        :param func_groups: List of strs representing the functional groups of
            interest. Default to None, meaning that all of the functional groups
            defined in this function will be sought.
        :return: list of sets of ints, representing groups of connected atoms
        """

        strat = OpenBabelNN()

        hydrogens = {n for n in self.molgraph.graph.nodes if
                     str(self.species[n]) == "H"}

        carbons = [n for n in self.molgraph.graph.nodes if
                   str(self.species[n]) == "C"]

        if func_groups is None:
            func_groups = ["methyl", "phenyl"]

        results = []

        if "methyl" in func_groups:
            for node in carbons:
                neighbors = strat.get_nn_info(self.molecule, node)
                hs = {n["site_index"] for n in neighbors if n["site_index"] in hydrogens}
                # Methyl group is CH3, but this will also catch methane
                if len(hs) >= 3:
                    hs.add(node)
                    results.append(hs)

        if "phenyl" in func_groups:
            rings_indices = [set(sum(ring, ())) for ring in
                             self.molgraph.find_rings()]

            possible_phenyl = [r for r in rings_indices if len(r) == 6]

            for ring in possible_phenyl:
                # Phenyl group should have only one (0 for benzene) member whose
                # neighbors are not two carbons and one hydrogen
                num_deviants = 0
                for node in ring:
                    neighbors = strat.get_nn_info(self.molecule, node)
                    neighbor_spec = sorted([str(self.species[n["site_index"]])
                                            for n in neighbors])
                    if neighbor_spec != ["C", "C", "H"]:
                        num_deviants += 1

                if num_deviants <= 1:
                    for node in ring:
                        neighbors = self.molgraph.graph[node]

                        # Add hydrogens to the functional group
                        for neighbor in neighbors.keys():
                            if neighbor in hydrogens:
                                ring.add(neighbor)

                    results.append(ring)

        return results