Skip to content

Commit

Permalink
Merge pull request #197 from Steinbeck-Lab/dev-kohulan
Browse files Browse the repository at this point in the history
feat: Add openbabel modules #185,#186 and #195
  • Loading branch information
CS76 authored Jun 12, 2023
2 parents 04dbec6 + b5f5265 commit b16dfaa
Show file tree
Hide file tree
Showing 6 changed files with 252 additions and 71 deletions.
4 changes: 3 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ FROM continuumio/miniconda3 AS cheminf-python-ms

ENV PYTHON_VERSION=3.10
ENV RDKIT_VERSION=2023.03.1
ENV OPENBABEL_VERSION=v3.1

ARG RELEASE_VERSION
ENV RELEASE_VERSION=${RELEASE_VERSION}
Expand All @@ -12,8 +13,9 @@ RUN apt-get update && \
apt-get update -y && \
apt-get install -y openjdk-11-jre

RUN conda install -c conda-forge python>=$PYTHON_VERSION
RUN conda install -c conda-forge python>=PYTHON_VERSION
RUN conda install -c conda-forge rdkit>=RDKIT_VERSION
RUN conda install -c conda-forge openbabel>=OPENBABEL_VERSION

RUN python3 -m pip install -U pip

Expand Down
40 changes: 40 additions & 0 deletions app/modules/toolkits/cdkmodules.py
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,46 @@ def getCXSMILES(smiles: str):
return str(CXSMILES)


def getCanonSMILES(smiles: str):
"""This function takes the user input SMILES and creates a
Canonical SMILES string with 2D atom coordinates
Args:
smiles (string): SMILES string given by the user.
Returns:
smiles (string): Canonical SMILES string.
"""
moleculeSDG = getCDKSDG(smiles)
SmiFlavor = JClass(cdk_base + ".smiles.SmiFlavor")
SmilesGenerator = JClass(cdk_base + ".smiles.SmilesGenerator")(SmiFlavor.Absolute)
CanonicalSMILES = SmilesGenerator.create(moleculeSDG)
return str(CanonicalSMILES)


def getInChI(smiles: str, InChIKey=False):
"""This function takes the user input SMILES and creates a
InChI string
Args:
smiles (string): SMILES string given by the user.
Returns:
smiles (string): InChI/InChIKey string.
"""
moleculeSDG = getCDKSDG(smiles)
InChIGeneratorFactory = JClass(cdk_base + ".inchi.InChIGeneratorFactory")
InChI = (
InChIGeneratorFactory.getInstance().getInChIGenerator(moleculeSDG).getInchi()
)
if InChIKey:
InChIKey = (
InChIGeneratorFactory.getInstance()
.getInChIGenerator(moleculeSDG)
.getInchiKey()
)
return InChIKey
return InChI


async def getCDKHOSECodes(smiles: str, noOfSpheres: int, ringsize: bool):
"""This function takes the user input SMILES and returns a mol
block as a string with Structure Diagram Layout.
Expand Down
82 changes: 82 additions & 0 deletions app/modules/toolkits/openbabelmodules.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
from openbabel import openbabel as ob
from openbabel import pybel

def getOBCanonicalSMILES(smiles:str):
"""This function takes an input as a SMILES string and
returns a Canonical SMILES.
Args (str): SMILES string.
Returns (str): Canonical SMILES string.
"""
if any(char.isspace() for char in smiles):
smiles = smiles.replace(" ", "+")

# Create an Open Babel molecule object
mol = ob.OBMol()

conv = ob.OBConversion()
conv.SetInAndOutFormats("smi", "can")
conv.ReadString(mol, smiles)

canSMILES = conv.WriteString(mol)
canSMILES = canSMILES.strip() # Remove leading/trailing whitespace
return canSMILES


def getOBInChI(smiles:str,InChIKey:bool=False):
"""This function takes an input as a SMILES string and
returns a InChI
Args (str): SMILES string.
Returns (str): InChI string.
"""
if any(char.isspace() for char in smiles):
smiles = smiles.replace(" ", "+")

# Create an Open Babel molecule object
mol = ob.OBMol()

# Create OBConversion
conv = ob.OBConversion()
conv.SetInAndOutFormats("smi", "inchi")
conv.ReadString(mol, smiles)

inchi = conv.WriteString(mol)
inchi = inchi.strip() # Remove leading/trailing whitespace
if InChIKey:
conv.SetOptions("K", conv.OUTOPTIONS)
inchikey_ = conv.WriteString(mol).rstrip()
return inchikey_
return inchi

def getOBMol(smiles:str, threeD:bool=False):
"""This function takes an input as a SMILES string and
returns a 2D/3D mol block.
Args (str): SMILES string.
Returns (str): Mol block (2D/3D).
"""
if any(char.isspace() for char in smiles):
smiles = smiles.replace(" ", "+")

if threeD:
mol = pybel.readstring("smi", smiles)
mol.addh()
mol.make3D()
mol.removeh()
return mol.write("mol")

# Create an Open Babel molecule object
mol = ob.OBMol()

conv = ob.OBConversion()
conv.SetInAndOutFormats("smi", "mol")
conv.ReadString(mol, smiles)

# Generate 2D coordinates
obBuilder = ob.OBBuilder()
obBuilder.Build(mol)

mol_block = conv.WriteString(mol)
mol_block = mol_block.strip() # Remove leading/trailing whitespace
return mol_block



18 changes: 18 additions & 0 deletions app/modules/toolkits/rdkitmodules.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,3 +194,21 @@ def has_stereochemistry(smiles: str):
return True

return False


def get2Dmol(smiles: str):
"""This function takes an input as a SMILES string and
returns a 2D mol block.
Args (str): SMILES string.
Returns (str): 2D Mol block.
"""
if any(char.isspace() for char in smiles):
smiles = smiles.replace(" ", "+")
mol = Chem.MolFromSmiles(smiles)

if mol:
AllChem.Compute2DCoords(mol)
molfile = Chem.MolToMolBlock(mol)
return molfile
else:
return "Error reading SMILES string, check again."
19 changes: 0 additions & 19 deletions app/routers/chem.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
from app.modules.npscorer import getNPScore
from app.modules.classyfire import classify, result
from app.modules.toolkits.cdkmodules import (
getCDKSDGMol,
getTanimotoSimilarityCDK,
getCDKHOSECodes,
)
Expand Down Expand Up @@ -149,24 +148,6 @@ async def ClassyFire_result(id: str):
return data


@router.get("/cdk2d")
async def CDK2D_Coordinates(smiles: str):
"""
Generate 2D Coordinates using the CDK Structure diagram generator and return the mol block.
- **SMILES**: required (query)
"""
if smiles:
mol = Chem.MolFromSmiles(smiles)
if mol:
return Response(
content=getCDKSDGMol(smiles).replace("$$$$\n", ""),
media_type="text/plain",
)
else:
return "Error reading SMILES string, check again."


@router.get("/rdkit3d")
async def RDKit3D_Mol(smiles: str):
"""
Expand Down
Loading

0 comments on commit b16dfaa

Please sign in to comment.