Skip to content

Commit

Permalink
Merge pull request #69 from NFDI4Chem/development
Browse files Browse the repository at this point in the history
Development
  • Loading branch information
CS76 authored Dec 23, 2023
2 parents 6771a53 + 8e4392b commit e3157c9
Show file tree
Hide file tree
Showing 27 changed files with 9,902 additions and 124 deletions.
3 changes: 3 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[flake8]
exclude =
./app/scripts/nmr-respredict/*.py
6 changes: 4 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
FROM continuumio/miniconda3 AS nmrkit-ms

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

ARG RELEASE_VERSION
Expand All @@ -15,10 +14,13 @@ RUN apt-get update && \
apt-get install -y curl && \
conda update -n base -c defaults conda

RUN apt-get update && apt-get -y install docker.io

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 pip3 install rdkit

RUN python3 -m pip install -U pip

ENV JAVA_HOME /usr/lib/jvm/java-11-openjdk-amd64/
Expand Down
4 changes: 3 additions & 1 deletion app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from .routers import registration
from .routers import chem
from .routers import spectra
from .routers import spectra, converter, predict
from fastapi.middleware.cors import CORSMiddleware

from app.core import config, tasks
Expand All @@ -31,6 +31,8 @@
app.include_router(registration.router)
app.include_router(chem.router)
app.include_router(spectra.router)
app.include_router(converter.router)
app.include_router(predict.router)

app.add_event_handler("startup", tasks.create_start_app_handler(app))
app.add_event_handler("shutdown", tasks.create_stop_app_handler(app))
Expand Down
61 changes: 61 additions & 0 deletions app/routers/converter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import subprocess
from fastapi import APIRouter, HTTPException, status, Response
from app.schemas import HealthCheck

router = APIRouter(
prefix="/convert",
tags=["converter"],
dependencies=[],
responses={404: {"description": "Not Found"}},
)


@router.get("/", include_in_schema=False)
@router.get(
"/health",
tags=["healthcheck"],
summary="Perform a Health Check on Converter Module",
response_description="Return HTTP Status Code 200 (OK)",
status_code=status.HTTP_200_OK,
include_in_schema=False,
response_model=HealthCheck,
)
def get_health() -> HealthCheck:
"""
## Perform a Health Check
Endpoint to perform a healthcheck on. This endpoint can primarily be used by Docker
to ensure a robust container orchestration and management are in place. Other
services that rely on the proper functioning of the API service will not deploy if this
endpoint returns any other HTTP status code except 200 (OK).
Returns:
HealthCheck: Returns a JSON response with the health status
"""
return HealthCheck(status="OK")


@router.get(
"/spectra",
tags=["converter"],
summary="Load and convert NMR raw data",
# response_model=List[int],
response_description="Load and convert NMR raw data",
status_code=status.HTTP_200_OK,
)
async def nmr_load_save(url: str):
"""
## Return nmrium json
Returns:
Return nmrium json
"""
process = subprocess.Popen(
["docker exec nmr-converter nmr-cli -u " + url],
stdout=subprocess.PIPE,
shell=True,
)
(output, err) = process.communicate()
process.wait()
if err:
raise HTTPException(status_code=500, detail=err)
else:
return Response(content=output, media_type="application/json")
145 changes: 145 additions & 0 deletions app/routers/predict.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import subprocess
from fastapi import APIRouter, HTTPException, status, Response, Body
from app.schemas import HealthCheck
from app.schemas.respredict_response_schema import ResPredictModel
from app.schemas.error import ErrorResponse, BadRequestModel, NotFoundModel
import uuid
from typing import Annotated
import os

router = APIRouter(
prefix="/predict",
tags=["predict"],
dependencies=[],
responses={404: {"description": "Not Found"}},
)


@router.get("/", include_in_schema=False)
@router.get(
"/health",
tags=["healthcheck"],
summary="Perform a Health Check on Predict Module",
response_description="Return HTTP Status Code 200 (OK)",
status_code=status.HTTP_200_OK,
include_in_schema=False,
response_model=HealthCheck,
)
def get_health() -> HealthCheck:
"""
## Perform a Health Check
Endpoint to perform a healthcheck on. This endpoint can primarily be used by Docker
to ensure a robust container orchestration and management are in place. Other
services that rely on the proper functioning of the API service will not deploy if this
endpoint returns any other HTTP status code except 200 (OK).
Returns:
HealthCheck: Returns a JSON response with the health status
"""
return HealthCheck(status="OK")


@router.post(
"/respredict",
summary="",
responses={
200: {
"description": "Successful response",
"model": ResPredictModel,
},
400: {"description": "Bad Request", "model": BadRequestModel},
404: {"description": "Not Found", "model": NotFoundModel},
422: {"description": "Unprocessable Entity", "model": ErrorResponse},
},
)
async def predict_mol(
data: Annotated[
str,
Body(
embed=False,
media_type="text/plain",
openapi_examples={
"example1": {
"summary": "Example: C",
"value": """
CDK 09012310592D
1 0 0 0 0 0 0 0 0 0999 V2000
0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
M END""",
},
},
),
]
):
"""
Standardize molblock using the ChEMBL curation pipeline
and return the standardized molecule, SMILES, InChI, and InCHI-Key.
Parameters:
- **molblock**: The request body containing the "molblock" string representing the molecule to be standardized.
Returns:
- dict: A dictionary containing the following keys:
- "standardized_mol" (str): The standardized molblock of the molecule.
- "canonical_smiles" (str): The canonical SMILES representation of the molecule.
- "inchi" (str): The InChI representation of the molecule.
- "inchikey" (str): The InChI-Key of the molecule.
Raises:
- ValueError: If the SMILES string is not provided or is invalid.
"""
try:
if data:
file_name = "/shared/" + str(uuid.uuid4()) + ".mol"
f = open(file_name, "a")
f.write(data)
f.close()
process = subprocess.Popen(
[
"docker exec nmr-respredict python3 predict_standalone.py --filename "
+ file_name
],
stdout=subprocess.PIPE,
shell=True,
)
(output, err) = process.communicate()
process.wait()
if err:
raise HTTPException(status_code=500, detail=err)
else:
if os.path.exists(file_name):
os.remove(file_name)
return Response(content=output, media_type="application/json")
except Exception as e:
raise HTTPException(status_code=422, detail=str(e))


# @router.get(
# "/predict",
# tags=["predict"],
# summary="Load and convert NMR raw data",
# #response_model=List[int],
# response_description="Load and convert NMR raw data",
# status_code=status.HTTP_200_OK,
# )
# async def nmr_respredict(url: str):
# """
# ## Return nmrium json

# Returns:
# Return nmrium json
# """
# file = "/shared" + str(uuid.uuid4()) + ".mol"

# process = subprocess.Popen(
# ["docker exec nmr-respredict python3 ./predict_standalone.py --filename " + file],
# stdout=subprocess.PIPE,
# shell=True,
# )
# (output, err) = process.communicate()
# process.wait()
# if err:
# raise HTTPException(status_code=500, detail=err)
# else:
# return Response(content=output, media_type="application/json")
Loading

0 comments on commit e3157c9

Please sign in to comment.