Skip to content

Instantly share code, notes, and snippets.

@rkakamilan
Forked from bannanc/OE_toandfrom_RDK.ipynb
Created June 20, 2023 23:36
Show Gist options
  • Save rkakamilan/ebae7558ced393417b27752d0278ac50 to your computer and use it in GitHub Desktop.
Save rkakamilan/ebae7558ced393417b27752d0278ac50 to your computer and use it in GitHub Desktop.
This is a jupyter notebook explaining how to convert molecules in OpenEye toolkits to the equivalent molecule in RDKit going both directions between toolkits.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"from openeye import oechem, oeomega\n",
"from rdkit import Chem, Geometry\n",
"import oenotebook as oenb"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## OEBond Stereochemistry Details\n",
"\n",
"In order to make bond stereochemistry work for either toolkit, it required knowing information about the atoms around the bond. I thought it would be instructive to show how this works before moving to the conversion between rdmol and oemols."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<IPython.core.display.Image object>"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"mol = oechem.OEMol()\n",
"oechem.OESmilesToMol(mol, 'F\\\\C(I)=C\\\\(Cl)C')\n",
"oenb.draw_mol(mol)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Relative Stereochemistry\n",
"\n",
"In both toolkits stereochemistry is specified based on relatively positions. \n",
"In Chemistry, we usually think of stereochemistry based on the atoms with highest priority so we would say this bond \n",
"is cis (or Z) because the iodine and chlorine are on the same side of the double bond. \n",
"However we can also think of this relatively so the double bond is cis or trans depending on which atoms you are \n",
"currently using as a reference. \n",
"\n",
"Therefore the double bond is \n",
"* Trans with Cl and F as reference\n",
"* Cis with C and F as reference\n",
"* Cis with Cl and I as reference\n",
"* Trans with C and I as a reference\n",
"\n",
"This point is illustrated with the example function below, which was only slightly adapted from the [OpenEye Stereochemistry Documentation Examples](https://docs.eyesopen.com/toolkits/python/oechemtk/stereochemistry.html).\n",
"The general conclusion from this is that you don't actually need to know the absolute stereochemistry of a bond, you just need two reference atoms and know what the stereochemistry is in that direction. "
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Atoms: 0 (#9) and 4 (#17) are trans\n",
"Atoms: 0 (#9) and 5 (#6) are cis\n",
"Atoms: 2 (#53) and 4 (#17) are cis\n",
"Atoms: 2 (#53) and 5 (#6) are trans\n"
]
}
],
"source": [
"def print_bond_stereo(oe_mol):\n",
" \"\"\"\n",
" This function prints all pairs of atoms that could be used to specify bond stereochemistry\n",
" OpenEye allows you to query for bond stereochemistry with any comination of neighboring atoms so\n",
" there are a total of 4 combinations of atoms for every bond.\n",
" \"\"\"\n",
" for bond in oe_mol.GetBonds():\n",
" if bond.HasStereoSpecified(oechem.OEBondStereo_CisTrans):\n",
" for atomB in bond.GetBgn().GetAtoms():\n",
" if atomB == bond.GetEnd():\n",
" continue\n",
" for atomE in bond.GetEnd().GetAtoms():\n",
" if atomE == bond.GetBgn():\n",
" continue\n",
" v = []\n",
" v.append(atomB)\n",
" v.append(atomE)\n",
" stereo = bond.GetStereo(v, oechem.OEBondStereo_CisTrans)\n",
" print(\"Atoms: %i (#%i)\" %( atomB.GetIdx(), atomB.GetAtomicNum()), end=' ')\n",
" print(\"and %i (#%i)\" % (atomE.GetIdx(), atomE.GetAtomicNum()), \"are\", end=\" \")\n",
"\n",
" if stereo == oechem.OEBondStereo_Cis:\n",
" print(\"cis\")\n",
" elif stereo == oechem.OEBondStereo_Trans:\n",
" print(\"trans\")\n",
"\n",
"# show all atom combinations you could use to specify stereochemistry\n",
"print_bond_stereo(mol)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# RDMol to OEMol\n",
"\n",
"The function below converts a molecule from RDMol to OEMol.\n",
"Currently this includes \n",
"\n",
"Atoms: \n",
"* formal charge\n",
"* aromaticity\n",
"* atomic number\n",
"* chirality\n",
"\n",
"Bonds:\n",
"* connecting atoms\n",
"* order\n",
"* aromaticity\n",
"* stereochemistry\n",
"\n",
"**Not Included:**\n",
"* Coordinates\n",
"* Arbitrary data\n",
" - both OpenEye and RDKit allow arbitrary data to be stored on atoms, bonds, and molecules. This function does nothing to make sure that information is extracted as it seemed outside the scope of this project."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"def oemol_from_rdmol(rdmol):\n",
" \"\"\"\n",
" Creates an openeye molecule object that is identical to the input rdkit molecule\n",
" \"\"\"\n",
" # RDK automatically includes explicit hydrogens in its SMILES patterns\n",
" print(\"Starting molecule: \", Chem.MolToSmiles(Chem.RemoveHs(rdmol))) \n",
" \n",
" # openeye stores bond orders as integers regardless of aromaticity\n",
" # in order to properly extract these, we need to have the \"Kekulized\" version of the rdkit mol\n",
" kekul_mol = Chem.Mol(rdmol)\n",
" Chem.Kekulize(kekul_mol, True)\n",
" \n",
" oemol = oechem.OEMol()\n",
" map_atoms = dict() # {rd_idx: oe_atom}\n",
" \n",
" # setting chirality in openey requires using neighbor atoms\n",
" # therefore we can't do it until after the atoms and bonds are all added\n",
" chiral_atoms = dict() # {rd_idx: openeye chirality}\n",
" for rda in rdmol.GetAtoms():\n",
" rd_idx = rda.GetIdx()\n",
" \n",
" # create a new atom\n",
" oe_a = oemol.NewAtom(rda.GetAtomicNum())\n",
" map_atoms[rd_idx] = oe_a\n",
" oe_a.SetFormalCharge(rda.GetFormalCharge())\n",
" oe_a.SetAromatic(rda.GetIsAromatic())\n",
"\n",
" # If chiral, store the chirality to be set later\n",
" tag = rda.GetChiralTag() \n",
" if tag == Chem.CHI_TETRAHEDRAL_CCW:\n",
" chiral_atoms[rd_idx] = oechem.OECIPAtomStereo_R\n",
" if tag == Chem.CHI_TETRAHEDRAL_CW:\n",
" chiral_atoms[rd_idx] = oechem.OECIPAtomStereo_S\n",
"\n",
" # Similar to chirality, stereochemistry of bonds in OE is set relative to their neighbors\n",
" stereo_bonds = list()\n",
" # stereo_bonds stores tuples in the form (oe_bond, rd_idx1, rd_idx2, OE stereo specification)\n",
" # where rd_idx1 and 2 are the atoms on the outside of the bond\n",
" # i.e. Cl and F in the example above\n",
" aro_bond = 0\n",
" for rdb in rdmol.GetBonds():\n",
" a1 = rdb.GetBeginAtomIdx()\n",
" a2 = rdb.GetEndAtomIdx()\n",
" \n",
" # create a new bond\n",
" newbond = oemol.NewBond(map_atoms[a1], map_atoms[a2])\n",
" \n",
" order = rdb.GetBondTypeAsDouble()\n",
" if order == 1.5: \n",
" # get the bond order for this bond in the kekulized molecule\n",
" order = kekul_mol.GetBondWithIdx(rdb.GetIdx()).GetBondTypeAsDouble()\n",
" newbond.SetAromatic(True)\n",
" else:\n",
" newbond.SetAromatic(False)\n",
" newbond.SetOrder(int(order))\n",
"\n",
" # determine if stereochemistry is needed\n",
" tag = rdb.GetStereo()\n",
" if tag == Chem.BondStereo.STEREOCIS or tag == Chem.BondStereo.STEREOZ:\n",
" stereo_atoms = rdb.GetStereoAtoms()\n",
" stereo_bonds.append((newbond, stereo_atoms[0], stereo_atoms[1], oechem.OEBondStereo_Cis))\n",
" \n",
" bond2 = rdmol.GetBondBetweenAtoms(stereo_atoms[0], a1)\n",
" bond4 = rdmol.GetBondBetweenAtoms(stereo_atoms[1], a2)\n",
" print(tag, bond2.GetBondDir(), bond4.GetBondDir())\n",
" if tag == Chem.BondStereo.STEREOTRANS or tag == Chem.BondStereo.STEREOE:\n",
" stereo_atoms = rdb.GetStereoAtoms()\n",
" stereo_bonds.append((newbond, stereo_atoms[0], stereo_atoms[1], oechem.OEBondStereo_Trans))\n",
" bond2 = rdmol.GetBondBetweenAtoms(stereo_atoms[0], a1)\n",
" bond4 = rdmol.GetBondBetweenAtoms(stereo_atoms[1], a2)\n",
" print(tag, bond2.GetBondDir(), bond4.GetBondDir())\n",
" \n",
" # Now that all of the atoms are connected we can set stereochemistry\n",
" # starting with atom chirality\n",
" for rd_idx, chirality in chiral_atoms.items():\n",
" # chirality is set relative to neighbors, so we will get neighboring atoms\n",
" # assign Right handed direction, check the cip stereochemistry\n",
" # if the cip stereochemistry isn't correct then we'll set left and double check\n",
" \n",
" oea = map_atoms[rd_idx]\n",
" neighs = [n for n in oea.GetAtoms()]\n",
" # incase you look at the documentation oe has two options for handedness for example:\n",
" # oechem.OEAtomStereo_Left == oechem.OEAtomStereo_LeftHanded\n",
" oea.SetStereo(neighs, oechem.OEAtomStereo_Tetra, oechem.OEAtomStereo_Right)\n",
" cip = oechem.OEPerceiveCIPStereo(oemol, oea)\n",
" if cip != chirality:\n",
" oea.SetStereo(neighs, oechem.OEAtomStereo_Tetra, oechem.OEAtomStereo_Left)\n",
" new_cip = oechem.OEPerceiveCIPStereo(oemol, oea)\n",
" if new_cip != chirality:\n",
" # Note, I haven't seen this happen yet, but it shouldn't be a problem since there \n",
" # is only 2 directions for handedness and we're only running this for chiral atoms\n",
" print(\"PANIC!\")\n",
"\n",
" # Set stereochemistry using the reference atoms extracted above\n",
" for oeb, idx1, idx2, oestereo in stereo_bonds:\n",
" oeb.SetStereo([map_atoms[idx1], map_atoms[idx2]], oechem.OEBondStereo_CisTrans, oestereo)\n",
"\n",
" # If the rdmol has a conformer, add its coordinates to the oemol\n",
" # Note, this currently only adds the first conformer, it will need to be adjusted if the\n",
" # you wanted to convert multiple sets of coordinates\n",
" if rdmol.GetConformers():\n",
" print(\"found an rdmol conformer\")\n",
" conf = rdmol.GetConformer()\n",
" for rd_idx, oeatom in map_atoms.items():\n",
" coords = conf.GetAtomPosition(rd_idx)\n",
" oemol.SetCoords(oeatom, oechem.OEFloatArray(coords))\n",
" \n",
" # If RDMol has a title save it\n",
" if rdmol.HasProp(\"_Name\"):\n",
" oemol.SetTitle(rdmol.GetProp(\"_Name\"))\n",
" \n",
" # Clean Up phase\n",
" # The only feature of a molecule that wasn't perceived above seemed to be ring connectivity, better to run it\n",
" # here then for someone to inquire about ring sizes and get 0 when it shouldn't be\n",
" oechem.OEFindRingAtomsAndBonds(oemol)\n",
" \n",
" print('Final Molecule: ', oechem.OEMolToSmiles(oemol))\n",
" return oemol"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# RDMol from OEMol\n",
"\n",
"The function below converts a molecule from RDMol to OEMol. \n",
"This example was built from Shuzhe Wang's\n",
"[example for openforcefiel](https://github.com/openforcefield/openforcefield/blob/swang/openforcefield/utils/utils.py#L512).\n",
"I skipped the coordinates part as it seemed outside the scope of my current needs, but you should know you can set coordinates by individual atom with \n",
"```\n",
"oemol.SetCoords( oeatom, oechem.OEFloatArray( (x, y, z) ) )\n",
"```\n",
"\n",
"Currently the method below includes:\n",
"\n",
"Atoms: \n",
"* formal charge\n",
"* aromaticity\n",
"* atomic number\n",
"* chirality\n",
"\n",
"Bonds:\n",
"* connecting atoms\n",
"* order\n",
"* aromaticity\n",
"* stereochemistry\n",
"\n",
"**Not Included:**\n",
"* Coordinates\n",
"* Arbitrary data\n",
" - both OpenEye and RDKit allow arbitrary data to be stored on atoms, bonds, and molecules. This function does nothing to make sure that information is extracted as it seemed outside the scope of this project.\n",
"\n",
"### More Notes on Bond Stereochemistry \n",
"\n",
"Initially I tried setting stereochemistry with the `Bond.SetStereo` function which wasn't working. \n",
"A [Source Forge](https://sourceforge.net/p/rdkit/mailman/message/19111378/) post from 2008 (a decade old?!) said that the `SetStereo` should not be accessed from python, a.k.a doesn't work. \n",
"It was NOT clear from documentation why that would be the case and there seemed to be more recent python examples on GitHub that do use this function. \n",
"However, following the suggestion in that [Source Forge](https://sourceforge.net/p/rdkit/mailman/message/19111378/) \n",
"post to set stereochemistry using the neighboring bond directions did work. \n",
"\n",
"This is actually fairly convenient as OpenEye also works best when using relative positions to set the stereochemistry. \n",
"\n",
"The nomenclature/API point around these settings was a bit unintuitive to me. \n",
"They use the API points `Chem.BondDir.ENDUPRIGHT` and `Chem.BondDir.ENDDOWNRIGHT`.\n",
"I thought it was directionally refering to where the bonds were, meaning trans bonds would be opposite and cis bonds would be the same words. \n",
"However, it actually refers to the `\"/\"` and `\"\\\"` in SMILES strings, that is `ENDUPRIGHT` is `\"/\"` and `ENDDOWNRIGHT` is `\"\\\"`. \n",
"Therefore, a cis bond would have opposite slashs as / then \\ ( or in this API up then down).\n",
"Where trans bonds use / then / (up then up)."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"def rdmol_from_oemol(oemol):\n",
" \"\"\"\n",
" Creates an openeye molecule object that is identical to the input rdkit molecule\n",
" \"\"\"\n",
" print(\"Starting molecule: \", oechem.OEMolToSmiles(oemol))\n",
"\n",
" # start function\n",
" rdmol = Chem.RWMol()\n",
"\n",
" # RDKit keeps bond order as a type instead using these values, I don't really understand 7, \n",
" # I took them from Shuzhe's example linked above\n",
" _bondtypes = {1: Chem.BondType.SINGLE,\n",
" 1.5: Chem.BondType.AROMATIC,\n",
" 2: Chem.BondType.DOUBLE,\n",
" 3: Chem.BondType.TRIPLE,\n",
" 4: Chem.BondType.QUADRUPLE,\n",
" 5: Chem.BondType.QUINTUPLE,\n",
" 6: Chem.BondType.HEXTUPLE,\n",
" 7: Chem.BondType.ONEANDAHALF,}\n",
"\n",
" # atom map lets you find atoms again\n",
" map_atoms = dict() # {oe_idx: rd_idx}\n",
" for oea in oemol.GetAtoms():\n",
" oe_idx = oea.GetIdx()\n",
" rda = Chem.Atom(oea.GetAtomicNum())\n",
" rda.SetFormalCharge(oea.GetFormalCharge())\n",
" rda.SetIsAromatic(oea.IsAromatic())\n",
"\n",
" # unlike OE, RDK lets you set chirality directly\n",
" cip = oechem.OEPerceiveCIPStereo(oemol, oea)\n",
" if cip == oechem.OECIPAtomStereo_S:\n",
" rda.SetChiralTag(Chem.CHI_TETRAHEDRAL_CW)\n",
" if cip == oechem.OECIPAtomStereo_R:\n",
" rda.SetChiralTag(Chem.CHI_TETRAHEDRAL_CCW)\n",
"\n",
" map_atoms[oe_idx] = rdmol.AddAtom(rda)\n",
"\n",
" # As discussed above, setting bond stereochemistry requires neighboring bonds \n",
" # so we will store that information by atom index in this list \n",
" stereo_bonds = list()\n",
" # stereo_bonds will have tuples with the form (rda1, rda2, rda3, rda4, is_cis)\n",
" # where rda[n] is an atom index for a double bond of form 1-2=3-4 \n",
" # and is_cis is a Boolean is True then onds 1-2 and 3-4 are cis to each other\n",
"\n",
" aro_bond = 0\n",
" for oeb in oemol.GetBonds():\n",
" # get neighboring rd atoms\n",
" rd_a1 = map_atoms[oeb.GetBgnIdx()]\n",
" rd_a2 = map_atoms[oeb.GetEndIdx()]\n",
"\n",
" # AddBond returns the total number of bonds, so addbond and then get it\n",
" rdmol.AddBond(rd_a1, rd_a2)\n",
" rdbond = rdmol.GetBondBetweenAtoms(rd_a1, rd_a2)\n",
"\n",
" # Assign bond type, which is based on order unless it is aromatic\n",
" order = oeb.GetOrder()\n",
" if oeb.IsAromatic():\n",
" rdbond.SetBondType(_bondtypes[1.5])\n",
" rdbond.SetIsAromatic(True)\n",
" else:\n",
" rdbond.SetBondType(_bondtypes[order])\n",
" rdbond.SetIsAromatic(False)\n",
"\n",
" # If the bond has specified stereo add the required information to stereo_bonds\n",
" if oeb.HasStereoSpecified(oechem.OEBondStereo_CisTrans):\n",
" # OpenEye determined stereo based on neighboring atoms so get two outside atoms\n",
" n1 = [n for n in oeb.GetBgn().GetAtoms() if n != oeb.GetEnd()][0]\n",
" n2 = [n for n in oeb.GetEnd().GetAtoms() if n != oeb.GetBgn()][0]\n",
"\n",
" rd_n1 = map_atoms[n1.GetIdx()]\n",
" rd_n2 = map_atoms[n2.GetIdx()]\n",
" \n",
" stereo = oeb.GetStereo([n1,n2], oechem.OEBondStereo_CisTrans)\n",
" if stereo == oechem.OEBondStereo_Cis:\n",
" print('cis')\n",
" stereo_bonds.append((rd_n1, rd_a1, rd_a2, rd_n2, True))\n",
" elif stereo == oechem.OEBondStereo_Trans:\n",
" print('trans')\n",
" stereo_bonds.append((rd_n1, rd_a1, rd_a2, rd_n2, False)) \n",
" \n",
" # add bond stereochemistry:\n",
" for (rda1, rda2, rda3, rda4, is_cis) in stereo_bonds:\n",
" # get neighbor bonds\n",
" bond1 = rdmol.GetBondBetweenAtoms(rda1, rda2)\n",
" bond2 = rdmol.GetBondBetweenAtoms(rda3, rda4)\n",
" \n",
" # Since this is relative, the first bond always goes up\n",
" # as explained above these names come from SMILES slashes so UP/UP is Trans and Up/Down is cis\n",
" bond1.SetBondDir(Chem.BondDir.ENDUPRIGHT)\n",
" if is_cis:\n",
" bond2.SetBondDir(Chem.BondDir.ENDDOWNRIGHT)\n",
" else:\n",
" bond2.SetBondDir(Chem.BondDir.ENDUPRIGHT)\n",
" \n",
" # if oemol has coordinates (The dimension is non-zero)\n",
" # add those coordinates to the rdmol\n",
" if oechem.OEGetDimensionFromCoords(oemol) > 0:\n",
" print(\"oemol has 3D coords\")\n",
" conformer = Chem.Conformer()\n",
" oecoords = oemol.GetCoords()\n",
" for oe_idx, rd_idx in map_atoms.items():\n",
" (x,y,z) = oecoords[oe_idx]\n",
" conformer.SetAtomPosition(rd_idx, Geometry.Point3D(x,y,z))\n",
" rdmol.AddConformer(conformer) \n",
" \n",
" # Save the molecule title\n",
" rdmol.SetProp(\"_Name\", oemol.GetTitle())\n",
" \n",
" # Cleanup the rdmol\n",
" # Note I copied UpdatePropertyCache and GetSSSR from Shuzhe's code to convert oemol to rdmol here:\n",
" rdmol.UpdatePropertyCache(strict=False)\n",
" Chem.GetSSSR(rdmol)\n",
" # I added AssignStereochemistry which takes the directions of the bond set \n",
" # and assigns the stereochemistry tags on the double bonds\n",
" Chem.AssignStereochemistry(rdmol, force=False) \n",
" \n",
" print(\"Final Molecule: \", Chem.MolToSmiles(Chem.RemoveHs(rdmol), isomericSmiles=True))\n",
" return rdmol.GetMol()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Check performance\n",
"\n",
"Start by making a list of SMILES for example molecules:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"smiles_list = ['C/C(=C(\\\\F)/I)/Cl', 'C/C(=C(/F)\\\\I)/Cl', 'F[C@H](Cl)\\\\C=C/C', 'F[C@H](Cl)\\\\C=C\\\\C', \n",
" 'c1ccccc1', 'C1=CNC=C1']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Round Trip Starting with OEMol"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"scrolled": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"oe: C/C(=C(\\F)/I)/Cl rd: C/C(Cl)=C(\\F)I\n",
"--------------------------------------------------------------------------------\n",
"Round Trip From OEMol\n",
"--------------------------------------------------------------------------------\n",
"Starting molecule: C/C(=C(\\F)/I)/Cl\n",
"cis\n",
"Final Molecule: C/C(Cl)=C(\\F)I\n",
"Starting molecule: C/C(Cl)=C(\\F)I\n",
"STEREOZ NONE NONE\n",
"Final Molecule: C/C(=C(\\F)/I)/Cl\n",
"--------------------------------------------------------------------------------\n",
"Round Trip From RDMol\n",
"--------------------------------------------------------------------------------\n",
"Starting molecule: C/C(Cl)=C(\\F)I\n",
"STEREOZ ENDUPRIGHT ENDUPRIGHT\n",
"Final Molecule: C/C(=C(\\F)/I)/Cl\n",
"Starting molecule: C/C(=C(\\F)/I)/Cl\n",
"cis\n",
"Final Molecule: C/C(Cl)=C(\\F)I\n",
"\n",
"\n",
"\n",
"\n",
"oe: C/C(=C(/F)\\I)/Cl rd: C/C(Cl)=C(/F)I\n",
"--------------------------------------------------------------------------------\n",
"Round Trip From OEMol\n",
"--------------------------------------------------------------------------------\n",
"Starting molecule: C/C(=C(/F)\\I)/Cl\n",
"trans\n",
"Final Molecule: C/C(Cl)=C(/F)I\n",
"Starting molecule: C/C(Cl)=C(/F)I\n",
"STEREOE NONE NONE\n",
"Final Molecule: C/C(=C(/F)\\I)/Cl\n",
"--------------------------------------------------------------------------------\n",
"Round Trip From RDMol\n",
"--------------------------------------------------------------------------------\n",
"Starting molecule: C/C(Cl)=C(/F)I\n",
"STEREOE ENDUPRIGHT ENDDOWNRIGHT\n",
"Final Molecule: C/C(=C(/F)\\I)/Cl\n",
"Starting molecule: C/C(=C(/F)\\I)/Cl\n",
"trans\n",
"Final Molecule: C/C(Cl)=C(/F)I\n",
"\n",
"\n",
"\n",
"\n",
"oe: C/C=C\\[C@H](F)Cl rd: C/C=C\\[C@H](F)Cl\n",
"--------------------------------------------------------------------------------\n",
"Round Trip From OEMol\n",
"--------------------------------------------------------------------------------\n",
"Starting molecule: C/C=C\\[C@H](F)Cl\n",
"cis\n",
"Final Molecule: C/C=C\\[C@H](F)Cl\n",
"Starting molecule: C/C=C\\[C@H](F)Cl\n",
"STEREOZ ENDUPRIGHT ENDDOWNRIGHT\n",
"Final Molecule: C/C=C\\[C@H](F)Cl\n",
"--------------------------------------------------------------------------------\n",
"Round Trip From RDMol\n",
"--------------------------------------------------------------------------------\n",
"Starting molecule: C/C=C\\[C@H](F)Cl\n",
"STEREOZ ENDDOWNRIGHT ENDUPRIGHT\n",
"Final Molecule: C/C=C\\[C@H](F)Cl\n",
"Starting molecule: C/C=C\\[C@H](F)Cl\n",
"cis\n",
"Final Molecule: C/C=C\\[C@H](F)Cl\n",
"\n",
"\n",
"\n",
"\n",
"oe: C/C=C/[C@H](F)Cl rd: C/C=C/[C@H](F)Cl\n",
"--------------------------------------------------------------------------------\n",
"Round Trip From OEMol\n",
"--------------------------------------------------------------------------------\n",
"Starting molecule: C/C=C/[C@H](F)Cl\n",
"trans\n",
"Final Molecule: C/C=C/[C@H](F)Cl\n",
"Starting molecule: C/C=C/[C@H](F)Cl\n",
"STEREOE ENDUPRIGHT ENDUPRIGHT\n",
"Final Molecule: C/C=C/[C@H](F)Cl\n",
"--------------------------------------------------------------------------------\n",
"Round Trip From RDMol\n",
"--------------------------------------------------------------------------------\n",
"Starting molecule: C/C=C/[C@H](F)Cl\n",
"STEREOE ENDDOWNRIGHT ENDDOWNRIGHT\n",
"Final Molecule: C/C=C/[C@H](F)Cl\n",
"Starting molecule: C/C=C/[C@H](F)Cl\n",
"trans\n",
"Final Molecule: C/C=C/[C@H](F)Cl\n",
"\n",
"\n",
"\n",
"\n",
"oe: c1ccccc1 rd: c1ccccc1\n",
"--------------------------------------------------------------------------------\n",
"Round Trip From OEMol\n",
"--------------------------------------------------------------------------------\n",
"Starting molecule: c1ccccc1\n",
"Final Molecule: c1ccccc1\n",
"Starting molecule: c1ccccc1\n",
"Final Molecule: c1ccccc1\n",
"--------------------------------------------------------------------------------\n",
"Round Trip From RDMol\n",
"--------------------------------------------------------------------------------\n",
"Starting molecule: c1ccccc1\n",
"Final Molecule: c1ccccc1\n",
"Starting molecule: c1ccccc1\n",
"Final Molecule: c1ccccc1\n",
"\n",
"\n",
"\n",
"\n",
"oe: c1cc[nH]c1 rd: c1cc[nH]c1\n",
"--------------------------------------------------------------------------------\n",
"Round Trip From OEMol\n",
"--------------------------------------------------------------------------------\n",
"Starting molecule: c1cc[nH]c1\n",
"Final Molecule: c1cc[nH]c1\n",
"Starting molecule: c1cc[nH]c1\n",
"Final Molecule: c1cc[nH]c1\n",
"--------------------------------------------------------------------------------\n",
"Round Trip From RDMol\n",
"--------------------------------------------------------------------------------\n",
"Starting molecule: c1cc[nH]c1\n",
"Final Molecule: c1cc[nH]c1\n",
"Starting molecule: c1cc[nH]c1\n",
"Final Molecule: c1cc[nH]c1\n",
"\n",
"\n",
"\n",
"\n"
]
}
],
"source": [
"for smiles in smiles_list:\n",
" oemol = oechem.OEMol()\n",
" if not oechem.OESmilesToMol(oemol, smiles):\n",
" print(\"couldn't process SMILES \", smiles, end='\\n\\n')\n",
" continue\n",
" oechem.OEAddExplicitHydrogens(oemol)\n",
" print(\"oe: %s\" % (oechem.OEMolToSmiles(oemol)), end=' ')\n",
" rdmol = Chem.MolFromSmiles(smiles)\n",
" if rdmol is None:\n",
" print(\"couldn't process \", smiles, end='\\n\\n')\n",
" continue\n",
" rdmol = Chem.AddHs(rdmol)\n",
" \n",
" print(\"rd: %s\" % (Chem.MolToSmiles(Chem.RemoveHs(rdmol), isomericSmiles=True)))\n",
"\n",
" print('-'*80)\n",
" print(\"Round Trip From OEMol\")\n",
" print('-'*80)\n",
" rdmol2 = rdmol_from_oemol(oemol)\n",
" new_oemol = oemol_from_rdmol(rdmol2)\n",
" \n",
" print('-'*80)\n",
" print(\"Round Trip From RDMol\")\n",
" print('-'*80)\n",
" oemol2 = oemol_from_rdmol(rdmol)\n",
" new_rdmol = rdmol_from_oemol(oemol2) \n",
" print('\\n\\n\\n')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# What you need to store\n",
"\n",
"Just for completeness, I thought I would add a list of what information I think you must keep in order to retain the chemical identity of a molecule:\n",
"\n",
"Atoms:\n",
"\n",
"* atomic number\n",
"* formal charge\n",
"* aromaticity (may not be as necessary here as it is for bonds)\n",
"* R/S/None Chirality\n",
"\n",
"Bonds:\n",
"\n",
"* connected atoms\n",
"* order (integer)\n",
" * if double - cis/trans/none based on reference atoms one bond away\n",
"* aromaticity"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Try with 3D Coordinates\n",
"\n",
"Start with using oemage to create 3D coordinates on an OEMol and then go to and from RDK"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"omega = oeomega.OEOmega()\n",
"omega.SetMaxConfs(1)\n",
"omega.SetIncludeInput(False)"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--------------------------------------------------------------------------------\n",
"Round Trip From OEMol\n",
"--------------------------------------------------------------------------------\n",
"Starting molecule: C/C(=C(\\F)/I)/Cl\n",
"cis\n",
"oemol has 3D coords\n",
"Final Molecule: C/C(Cl)=C(/F)I\n",
"Starting molecule: C/C(Cl)=C(/F)I\n",
"STEREOE NONE NONE\n",
"found an rdmol conformer\n",
"Final Molecule: C/C(=C(/F)\\I)/Cl\n",
"\n",
"\n",
"\n",
"--------------------------------------------------------------------------------\n",
"Round Trip From OEMol\n",
"--------------------------------------------------------------------------------\n",
"Starting molecule: C/C(=C(/F)\\I)/Cl\n",
"trans\n",
"oemol has 3D coords\n",
"Final Molecule: C/C(Cl)=C(\\F)I\n",
"Starting molecule: C/C(Cl)=C(\\F)I\n",
"STEREOZ NONE NONE\n",
"found an rdmol conformer\n",
"Final Molecule: C/C(=C(\\F)/I)/Cl\n",
"\n",
"\n",
"\n",
"--------------------------------------------------------------------------------\n",
"Round Trip From OEMol\n",
"--------------------------------------------------------------------------------\n",
"Starting molecule: C/C=C\\[C@H](F)Cl\n",
"cis\n",
"oemol has 3D coords\n",
"Final Molecule: C/C=C/[C@H](F)Cl\n",
"Starting molecule: C/C=C/[C@H](F)Cl\n",
"STEREOE NONE NONE\n",
"found an rdmol conformer\n",
"Final Molecule: C/C=C/[C@H](F)Cl\n",
"\n",
"\n",
"\n",
"--------------------------------------------------------------------------------\n",
"Round Trip From OEMol\n",
"--------------------------------------------------------------------------------\n",
"Starting molecule: C/C=C/[C@H](F)Cl\n",
"trans\n",
"oemol has 3D coords\n",
"Final Molecule: C/C=C\\[C@H](F)Cl\n",
"Starting molecule: C/C=C\\[C@H](F)Cl\n",
"STEREOZ NONE NONE\n",
"found an rdmol conformer\n",
"Final Molecule: C/C=C\\[C@H](F)Cl\n",
"\n",
"\n",
"\n",
"--------------------------------------------------------------------------------\n",
"Round Trip From OEMol\n",
"--------------------------------------------------------------------------------\n",
"Starting molecule: c1ccccc1\n",
"oemol has 3D coords\n",
"Final Molecule: c1ccccc1\n",
"Starting molecule: c1ccccc1\n",
"found an rdmol conformer\n",
"Final Molecule: c1ccccc1\n",
"\n",
"\n",
"\n",
"--------------------------------------------------------------------------------\n",
"Round Trip From OEMol\n",
"--------------------------------------------------------------------------------\n",
"Starting molecule: c1cc[nH]c1\n",
"oemol has 3D coords\n",
"Final Molecule: c1cc[nH]c1\n",
"Starting molecule: c1cc[nH]c1\n",
"found an rdmol conformer\n",
"Final Molecule: c1cc[nH]c1\n",
"\n",
"\n",
"\n"
]
}
],
"source": [
"for smiles in smiles_list:\n",
" oemol = oechem.OEMol()\n",
" if not oechem.OESmilesToMol(oemol, smiles):\n",
" print(\"couldn't process SMILES \", smiles, end='\\n\\n')\n",
" continue\n",
" oechem.OEAddExplicitHydrogens(oemol)\n",
" if not omega(oemol):\n",
" print(\"couldn't use omega on %s\" % smiles, end='\\n\\n')\n",
" continue\n",
" \n",
" print('-'*80)\n",
" print(\"Round Trip From OEMol\")\n",
" print('-'*80)\n",
" rdmol2 = rdmol_from_oemol(oemol)\n",
" new_oemol = oemol_from_rdmol(rdmol2)\n",
" print('\\n\\n')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.5"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment