Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added versioning, HOSE codes and license details to the swagger docs #159

Merged
merged 1 commit into from
Jun 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 0 additions & 12 deletions app/config.py

This file was deleted.

53 changes: 31 additions & 22 deletions app/main.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
from fastapi import FastAPI
from fastapi.responses import RedirectResponse
from fastapi_versioning import VersionedFastAPI

# from .config import settings
from .routers import chem, converters, compose, decimer
from .routers import chem, converters, decimer
from fastapi.middleware.cors import CORSMiddleware
from fastapi.openapi.utils import get_openapi
import os

app = FastAPI()
app = FastAPI(
title="Cheminf Micro Services",
description="This set of essential and valuable microservices is designed to be accessed via API calls to support cheminformatics. Generally, it is designed to work with SMILES-based inputs and could be used to translate between different machine-readable representations, get Natural Product (NP) likeliness scores, visualize chemical structures, and generate descriptors. In addition, the microservices also host an instance of STOUT and another instance of DECIMER (two deep learning models for IUPAC name generation and optical chemical structure recognition, respectively).",
terms_of_service="https://github.com/Steinbeck-Lab",
contact={
"name": "Steinbeck Lab",
"url": "https://cheminf.uni-jena.de/",
"email": "caffeine@listserv.uni-jena.de",
},
license_info={
"name": "CC BY 4.0",
"url": "https://creativecommons.org/licenses/by/4.0/",
},
)

origins = ["*"]

Expand All @@ -21,7 +33,6 @@

app.include_router(chem.router)
app.include_router(converters.router)
app.include_router(compose.router)
app.include_router(decimer.router)


Expand All @@ -30,20 +41,18 @@ async def docs_redirect():
return RedirectResponse(url="/docs")


def custom_openapi():
if app.openapi_schema:
return app.openapi_schema
openapi_schema = get_openapi(
title="Cheminf Micro Services",
version=os.getenv("RELEASE_VERSION", "latest"),
description="This set of essential and valuable microservices is designed to be accessed via API calls to support cheminformatics. Generally, it is designed to work with SMILES-based inputs and could be used to translate between different machine-readable representations, get Natural Product (NP) likeliness scores, visualize chemical structures, and generate descriptors. In addition, the microservices also host an instance of STOUT and another instance of DECIMER (two deep learning models for IUPAC name generation and optical chemical structure recognition, respectively).",
routes=app.routes,
)
openapi_schema["info"]["x-logo"] = {
"url": "https://github.com/Steinbeck-Lab/cheminformatics-python-microservice/raw/main/public/img/logo.png"
}
app.openapi_schema = openapi_schema
return app.openapi_schema


app.openapi = custom_openapi
app = VersionedFastAPI(
app,
version_format="{major}",
prefix_format="/v{major}",
terms_of_service="https://github.com/Steinbeck-Lab",
contact={
"name": "Steinbeck Lab",
"url": "https://cheminf.uni-jena.de/",
"email": "caffeine@listserv.uni-jena.de",
},
license_info={
"name": "CC BY 4.0",
"url": "https://creativecommons.org/licenses/by/4.0/",
},
)
24 changes: 24 additions & 0 deletions app/modules/cdkmodules.py
Original file line number Diff line number Diff line change
Expand Up @@ -394,3 +394,27 @@ def getCXSMILES(smiles: str):
)
CXSMILES = SmilesGenerator.create(moleculeSDG)
return str(CXSMILES)


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.
Args:
smiles (string): SMILES string given by the user.
Returns:
mol object (string): CDK Structure Diagram Layout mol block.
"""
if any(char.isspace() for char in smiles):
smiles = smiles.replace(" ", "+")
SCOB = JClass(cdk_base + ".silent.SilentChemObjectBuilder")
SmilesParser = JClass(cdk_base + ".smiles.SmilesParser")(SCOB.getInstance())
molecule = SmilesParser.parseSmiles(smiles)
HOSECodeGenerator = JClass(cdk_base + ".tools.HOSECodeGenerator")()
HOSECodes = []
atoms = molecule.atoms()
for atom in atoms:
moleculeHOSECode = HOSECodeGenerator.getHOSECode(
molecule, atom, noOfSpheres, ringsize
)
HOSECodes.append(str(moleculeHOSECode))
return HOSECodes
1 change: 0 additions & 1 deletion app/modules/depict.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ def getCDKDepiction(
moleculeSDG = getCDKSDG(smiles)

if moleculeSDG:

# Rotate molecule
point = JClass(cdk_base + ".geometry.GeometryTools").get2DCenter(moleculeSDG)
JClass(cdk_base + ".geometry.GeometryTools").rotate(
Expand Down
13 changes: 13 additions & 0 deletions app/modules/rdkitmodules.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from rdkit import Chem, DataStructs
from rdkit.Chem import AllChem, Descriptors, QED, Lipinski, rdMolDescriptors, rdmolops
from app.modules.cdkmodules import getCDKSDGMol
from hosegen import HoseGenerator


def checkSMILES(smiles: str):
Expand Down Expand Up @@ -134,3 +135,15 @@ def getTanimotoSimilarityRDKit(smiles1, smiles2):
similarity = DataStructs.TanimotoSimilarity(fp1, fp2)

return similarity


async def getRDKitHOSECodes(smiles: str, noOfSpheres: int):
if any(char.isspace() for char in smiles):
smiles = smiles.replace(" ", "+")
mol = Chem.MolFromSmiles(smiles)
gen = HoseGenerator()
hosecodes = []
for i in range(0, len(mol.GetAtoms()) - 1):
hosecode = gen.get_Hose_codes(mol, i, noOfSpheres)
hosecodes.append(hosecode)
return hosecodes
23 changes: 21 additions & 2 deletions app/routers/chem.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,17 @@
from fastapi.responses import Response, HTMLResponse
from app.modules.npscorer import getNPScore
from app.modules.classyfire import classify, result
from app.modules.cdkmodules import getCDKSDGMol, getTanimotoSimilarityCDK
from app.modules.cdkmodules import (
getCDKSDGMol,
getTanimotoSimilarityCDK,
getCDKHOSECodes,
)
from app.modules.depict import getRDKitDepiction, getCDKDepiction
from app.modules.rdkitmodules import get3Dconformers, getTanimotoSimilarityRDKit
from app.modules.rdkitmodules import (
get3Dconformers,
getTanimotoSimilarityRDKit,
getRDKitHOSECodes,
)
from app.modules.coconutdescriptors import getCOCONUTDescriptors
from app.modules.alldescriptors import getTanimotoSimilarity
import pandas as pd
Expand Down Expand Up @@ -297,6 +305,17 @@ async def Depict3D_Molecule(
return templates.TemplateResponse("mol.html", content)


@router.get("/hosecode")
async def HOSE_Codes(framework: str, smiles: str, spheres: int, ringsize: bool = False):
if smiles:
if framework == "cdk":
return await getCDKHOSECodes(smiles, spheres, ringsize)
elif framework == "rdkit":
return await getRDKitHOSECodes(smiles, spheres)
else:
return "Error reading SMILES string, check again."


# @app.get("/molecules/", response_model=List[schemas.Molecule])
# def read_molecules(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
# molecules = crud.get_molecules(db, skip=skip, limit=limit)
Expand Down
2 changes: 1 addition & 1 deletion app/routers/decimer.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ async def DECIMER_Index():
@router.post("/process")
async def Extract_ChemicalInfo(
path: Annotated[str, Body(embed=True)] = None,
reference: Annotated[str, Body(embed=True)] = None,
reference: Annotated[str, Body(embed=True)] = None,
img: Annotated[str, Body(embed=True)] = None,
):
"""
Expand Down
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
fastapi>=0.80.0
uvicorn>=0.15.0,<0.16.0
fastapi-pagination==0.10.0
fastapi-versioning>=0.10.0
rdkit-pypi>=2022.09.4
websockets==10.4
pillow==9.4.0
Expand All @@ -18,3 +19,4 @@ pillow-heif==0.10.0
selfies>=2.1.1
jinja2
pandas
HOSE_code_generator @ git+https://github.com/Ratsemaat/HOSE_code_generator