示例#1
0
 def test_from_molecule_graph(self):
     graph = MoleculeGraph.with_empty_graph(self.mol)
     adaptor = BabelMolAdaptor.from_molecule_graph(graph)
     obmol = adaptor.openbabel_mol
     self.assertEqual(obmol.NumAtoms(), 5)
     mol = adaptor.pymatgen_mol
     self.assertEqual(mol.formula, "H4 C1")
示例#2
0
 def test_from_molecule_graph(self):
     graph = MoleculeGraph.with_empty_graph(self.mol)
     adaptor = BabelMolAdaptor.from_molecule_graph(graph)
     obmol = adaptor.openbabel_mol
     self.assertEqual(obmol.NumAtoms(), 5)
     mol = adaptor.pymatgen_mol
     self.assertEqual(mol.formula, "H4 C1")
示例#3
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())
示例#4
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)
    return MoleculeGraph.with_local_env_strategy(obmol.pymatgen_mol, OpenBabelNN(), reorder=False, extend_structure=False)
示例#5
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)
    return build_MoleculeGraph(obmol.pymatgen_mol, strategy=OpenBabelNN, reorder=False, extend_structure=False)
示例#6
0
    def molecule_graph_to_smiles(
            molecule_graph: MoleculeGraph) -> Optional[str]:
        """Converts a molecule graph to SMILES string.

        Args:
            molecule_graph: A molecule graph.

        Returns:
            The SMILES representation of the molecule.
        """
        try:
            bma = BabelMolAdaptor.from_molecule_graph(molecule_graph)
            pbmol = bma.pybel_mol
            return pbmol.write(str("smi")).split()[0]
        except RuntimeError:
            warnings.warn("Molecule naming requires openbabel to be installed "
                          "with Python bindings. Please get it at "
                          "http://openbabel.org.")
            return None
示例#7
0
 def fragment_and_process(self, bonds):
     # Try to split the principle:
     try:
         frags = self.mol_graph.split_molecule_subgraphs(bonds,allow_reverse=True)
         frag_success = True
     except MolGraphSplitError:
         # If split is unsuccessful, then we have encountered a ring bond
         if len(bonds) == 1:
             self.ring_bonds += bonds
             # So we open the ring and make sure we haven't already encountered an identically opened fragment:
             RO_frag = open_ring(self.mol_graph, bonds, 1000)
             frag_done = False
             for done_RO_frag in self.done_RO_frags:
                 if RO_frag.isomorphic_to(done_RO_frag):
                     frag_done = True
             if not frag_done:
                 # If this is a new fragment, save the record and then search for relevant fragment entries:
                 self.done_RO_frags.append(RO_frag)
                 opened_entries = self.search_fragment_entries(RO_frag)
                 good_entries = []
                 # We will start by looking at entries with no structure change
                 for frag in opened_entries[0]: # 0 -> no structural change
                     # Since a ring opening still yields a single molecule, it should have the same charge as the principle:
                     if frag["initial_molecule"]["charge"] == self.molecule_entry["final_molecule"]["charge"]:
                         good_entries.append(frag)
                 # If we didn't find any good entries, let's also look at those that exhibit structural changes:
                 if len(good_entries) == 0:
                     for frag in opened_entries[1]: # 1 -> YES structural change
                         if frag["initial_molecule"]["charge"] == self.molecule_entry["final_molecule"]["charge"]:
                             good_entries.append(frag)
                 # If we still have no good entries, something must have gone wrong with the calculations:
                 if len(good_entries) == 0:
                     bb = BabelMolAdaptor.from_molecule_graph(RO_frag)
                     pbmol = bb.pybel_mol
                     smiles = pbmol.write(str("smi")).split()[0]
                     specie = nx.get_node_attributes(self.mol_graph.graph, "specie")
                     print("Missing ring opening fragment resulting from the breakage of " + specie[bonds[0][0]] + " " + specie[bonds[0][1]] + " bond " + str(bonds[0][0]) + " " + str(bonds[0][1]) + " which would yield a molecule with this SMILES string: " + smiles)
                 elif len(good_entries) == 1:
                     # If we have only one good entry, format it and addd it to the list that will eventually return:
                     self.bond_dissociation_energies += [self.build_new_entry(good_entries, bonds)]
                 else:
                     # We shouldn't ever encounter more than one good entry.
                     raise RuntimeError("There should only be one valid ring opening fragment! Exiting...")
         elif len(bonds) == 2:
             if not multibreak:
                 raise RuntimeError("Should only be trying to break two bonds if multibreak is true! Exiting...")
         else:
             print('No reason to try and break more than two bonds at once! Exiting...')
             raise ValueError
         frag_success = False
     if frag_success:
         # If the principle did successfully split, then we aren't dealing with a ring bond.
         # As above, we begin by making sure we haven't already encountered an identical pair of fragments:
         frags_done = False
         for frag_pair in self.done_frag_pairs:
             if frag_pair[0].isomorphic_to(frags[0]):
                 if frag_pair[1].isomorphic_to(frags[1]):
                     frags_done = True
                     break
             elif frag_pair[1].isomorphic_to(frags[0]):
                 if frag_pair[0].isomorphic_to(frags[1]):
                     frags_done = True
                     break
         if not frags_done:
             # If we haven't, we save this pair and search for the relevant fragment entries:
             self.done_frag_pairs += [frags]
             num_entries_for_this_frag_pair = 0
             frag1_entries = self.search_fragment_entries(frags[0])
             frag2_entries = self.search_fragment_entries(frags[1])
             frag1_charges_found = []
             frag2_charges_found = []
             # We then check for our expected charges of each fragment:
             for frag1 in frag1_entries[0] + frag1_entries[1]:
                 if frag1["initial_molecule"]["charge"] not in frag1_charges_found:
                     frag1_charges_found += [frag1["initial_molecule"]["charge"]]
             for frag2 in frag2_entries[0] + frag2_entries[1]:
                 if frag2["initial_molecule"]["charge"] not in frag2_charges_found:
                     frag2_charges_found += [frag2["initial_molecule"]["charge"]]
             # If we're missing some of either, tell the user:
             if len(frag1_charges_found) < len(self.expected_charges):
                 bb = BabelMolAdaptor(frags[0].molecule)
                 pbmol = bb.pybel_mol
                 smiles = pbmol.write(str("smi")).split()[0]
                 for charge in self.expected_charges:
                     if charge not in frag1_charges_found:
                         print("Missing charge " + str(charge) + " for fragment " + smiles)
             if len(frag2_charges_found) < len(self.expected_charges):
                 bb = BabelMolAdaptor(frags[1].molecule)
                 pbmol = bb.pybel_mol
                 smiles = pbmol.write(str("smi")).split()[0]
                 for charge in self.expected_charges:
                     if charge not in frag2_charges_found:
                         print("Missing charge " + str(charge) + " for fragment " + smiles)
             # Now we attempt to pair fragments with the right total charge, starting with only fragments with no structural change:
             for frag1 in frag1_entries[0]: # 0 -> no structural change
                 for frag2 in frag2_entries[0]: # 0 -> no structural change
                     if frag1["initial_molecule"]["charge"] + frag2["initial_molecule"]["charge"] == self.molecule_entry["final_molecule"]["charge"]:
                         self.bond_dissociation_energies += [self.build_new_entry([frag1, frag2], bonds)]
                         num_entries_for_this_frag_pair += 1
             # If we haven't found the number of fragment pairs that we expect, we expand our search to include fragments that do exhibit structural change:
             if num_entries_for_this_frag_pair < len(self.expected_charges):
                 for frag1 in frag1_entries[0]: # 0 -> no structural change
                     for frag2 in frag2_entries[1]: # 1 -> YES structural change
                         if frag1["initial_molecule"]["charge"] + frag2["initial_molecule"]["charge"] == self.molecule_entry["final_molecule"]["charge"]:
                             self.bond_dissociation_energies += [self.build_new_entry([frag1, frag2], bonds)]
                             num_entries_for_this_frag_pair += 1
                 for frag1 in frag1_entries[1]: # 1 -> YES structural change
                     for frag2 in frag2_entries[0]: # 0 -> no structural change
                         if frag1["initial_molecule"]["charge"] + frag2["initial_molecule"]["charge"] == self.molecule_entry["final_molecule"]["charge"]:
                             self.bond_dissociation_energies += [self.build_new_entry([frag1, frag2], bonds)]
                             num_entries_for_this_frag_pair += 1