Skip to content

Commit

Permalink
Merge pull request #91 from Steinbeck-Lab/development
Browse files Browse the repository at this point in the history
Development
  • Loading branch information
Kohulan authored Mar 24, 2023
2 parents 8686c45 + 34174ff commit 1ab24c3
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 57 deletions.
11 changes: 11 additions & 0 deletions .github/workflows/dev-build.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@

# This worklflow will perform following actions when the code is pushed to development branch:
# - Test linting with pylint.
# - Fetch Latest release.
# - Build the latest docker image in development which needs test to pass first.
# - Push the docker image to Github Artifact Registry-Dev.
#
# Maintainers:
# - name: Nisha Sharma
# - email: nisha.sharma@uni-jena.de

name : Dev Build, Test and Publish

on:
Expand Down
43 changes: 11 additions & 32 deletions .github/workflows/prod-build.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@

# This worklflow will perform following actions when a release is published:
# - Fetch Latest release.
# - Build the latest docker image in production.
# - Push the docker image to Github Artifact Registry-Prod.
#
# Maintainers:
# - name: Nisha Sharma
# - email: nisha.sharma@uni-jena.de

name : Prod Build, Test and Publish

on:
Expand All @@ -11,40 +21,9 @@ env:
APP_IMAGE: chem-py-microservice

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10"]
steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip3 install --upgrade setuptools pip
pip3 install --no-cache-dir -r requirements.txt
python3 -m pip uninstall -y imantics
pip3 install imantics==0.1.12
pip3 install --no-deps decimer-segmentation
pip3 install --no-deps decimer>=2.2.0
pip3 install --no-deps STOUT-pypi>=2.0.5
pip install flake8 pytest
- name: Analysing the code with pylint
run: |
flake8 --ignore E501,W503 $(git ls-files '*.py')
- name: Run test
run: |
pytest -p no:warnings
setup-build-publish-prod:
name: Build & publish to prod registry
# if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
needs: test
steps:
- name: Checkout
uses: actions/checkout@v2
Expand Down Expand Up @@ -77,7 +56,7 @@ jobs:
- name: Build docker image
run: |-
docker build --build-arg RELEASE_VERSION=${{ steps.fetch-latest-release.outputs.tag_name }} --tag "europe-west3-docker.pkg.dev/$PROJECT_ID/$REPOSITORY_NAME/$APP_IMAGE:latest" .
.
# Push the Docker image to Google Container Registry
- name: Publish image to Google Artifact Registry
run: |-
Expand Down
40 changes: 40 additions & 0 deletions .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@

# This worklflow will perform following actions when the code is pushed to main branch.
# - Test linting with pylint.
# - Test the code with pytest.
# - Trigger release-please action to create release which needs test to pass first.
#
# Maintainers:
# - name: Nisha Sharma
# - email: nisha.sharma@uni-jena.de

name: release-please-action

on:
Expand All @@ -6,8 +16,38 @@ on:
- main

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10"]
steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip3 install --upgrade setuptools pip
pip3 install --no-cache-dir -r requirements.txt
python3 -m pip uninstall -y imantics
pip3 install imantics==0.1.12
pip3 install --no-deps decimer-segmentation
pip3 install --no-deps decimer>=2.2.0
pip3 install --no-deps STOUT-pypi>=2.0.5
pip install flake8 pytest
- name: Analysing the code with pylint
run: |
flake8 --ignore E501,W503 $(git ls-files '*.py')
- name: Run test
run: |
pytest -p no:warnings
release-please:
runs-on: ubuntu-latest
needs: test
steps:
- uses: google-github-actions/release-please-action@v3
with:
Expand Down
2 changes: 1 addition & 1 deletion app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def custom_openapi():
return app.openapi_schema
openapi_schema = get_openapi(
title="Cheminf Micro Services",
version=os.getenv("RELEASE_VERSION", "pre-release"),
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,
)
Expand Down
31 changes: 29 additions & 2 deletions app/modules/cdkmodules.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,33 @@ def getCDKSDGMol(smiles: str):
return mol_str


def getAromaticRingCount(mol):
"""This function is adapted from CDK to
calculate the number of Aromatic Rings
present in a given molecule.
Args (mol): CDK mol object as input.
Returns (int): Number if aromatic rings present
"""
Cycles = JClass(cdk_base + ".graph.Cycles")
ElectronDonation = JClass(cdk_base + ".aromaticity.ElectronDonation")

Aromaticity = JClass(cdk_base + ".aromaticity.Aromaticity")(
ElectronDonation.daylight(), Cycles.cdkAromaticSet()
)
Aromaticity.apply(mol)
MCBRings = Cycles.mcb(mol).toRingSet()
NumberOfAromaticRings = 0
for RingContainer in MCBRings.atomContainers():
AreAllRingBondsAromatic = True
for Bond in RingContainer.bonds():
if not Bond.isAromatic():
AreAllRingBondsAromatic = False
break
if AreAllRingBondsAromatic:
NumberOfAromaticRings += 1
return NumberOfAromaticRings


def getCDKDescriptors(smiles: str):
"""Take an input SMILES and generate a selected set of molecular
descriptors generated using CDK as a list.
Expand Down Expand Up @@ -172,7 +199,7 @@ def getCDKDescriptors(smiles: str):
.calculate(Mol)
.getValue()
)
AromaticRings = None
AromaticRings = getAromaticRingCount(Mol)
QEDWeighted = None
FormalCharge = JClass(
cdk_base + ".tools.manipulator.AtomContainerManipulator"
Expand All @@ -198,7 +225,7 @@ def getCDKDescriptors(smiles: str):
str(HBondAcceptorCountDescriptor),
str(HBondDonorCountDescriptor),
str(RuleOfFiveDescriptor),
str(AromaticRings),
AromaticRings,
str(QEDWeighted),
FormalCharge,
"{:.2f}".format(float(str(FractionalCSP3Descriptor))),
Expand Down
7 changes: 3 additions & 4 deletions app/routers/chem.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from fastapi import Request, APIRouter
from fastapi import Body, Request, APIRouter
from typing import Optional
from typing_extensions import Annotated
from rdkit import Chem
from rdkit.Chem.EnumerateStereoisomers import (
EnumerateStereoisomers,
Expand Down Expand Up @@ -49,14 +50,12 @@ async def SMILES_stereoisomers(smiles: str):


@router.post("/standardize")
async def standardize_mol(request: Request):
async def standardize_mol(mol: Annotated[str, Body(embed=True)]):
"""
Standardize molblock using the ChEMBL curation pipeline routine:
- **mol**: required
"""
body = await request.json()
mol = body["mol"]
if mol:
standardized_mol = standardizer.standardize_molblock(mol)
rdkit_mol = Chem.MolFromMolBlock(standardized_mol)
Expand Down
32 changes: 14 additions & 18 deletions app/routers/decimer.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
from fastapi.responses import JSONResponse
from urllib.request import urlopen
from urllib.parse import urlsplit
from fastapi import Request, APIRouter
from fastapi import Body, APIRouter
from typing_extensions import Annotated
from app.modules.decimermodules import getPredictedSegments

router = APIRouter(
Expand All @@ -21,25 +22,20 @@ async def decimer_index():


@router.post("/process")
async def extract_chemicalinfo(request: Request):
body = await request.json()
image_path = body["path"]
reference = body["reference"]
split = urlsplit(image_path)
async def extract_chemicalinfo(path: Annotated[str, Body(embed=True)], reference: Annotated[str, Body(embed=True)], img: Annotated[str, Body(embed=True)]):
split = urlsplit(path)
filename = "/tmp/" + split.path.split("/")[-1]
if "img" in body:
imgDataURI = body["img"]
if imgDataURI:
response = urlopen(imgDataURI)
with open(filename, "wb") as f:
f.write(response.file.read())
smiles = getPredictedSegments(filename)
os.remove(filename)
return JSONResponse(
content={"reference": reference, "smiles": smiles.split(".")}
)
if img:
response = urlopen(img)
with open(filename, "wb") as f:
f.write(response.file.read())
smiles = getPredictedSegments(filename)
os.remove(filename)
return JSONResponse(
content={"reference": reference, "smiles": smiles.split(".")}
)
else:
response = requests.get(image_path)
response = requests.get(path)
if response.status_code == 200:
with open(filename, "wb") as f:
f.write(response.content)
Expand Down

0 comments on commit 1ab24c3

Please sign in to comment.