Skip to content

Commit

Permalink
Add resource for basic and acid PKA calculations
Browse files Browse the repository at this point in the history
  • Loading branch information
khyurri committed Jul 19, 2022
1 parent 869db9c commit 49e965a
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 68 deletions.
13 changes: 10 additions & 3 deletions api/http/.pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,15 @@ repos:
language: system
types: [ python ]


- repo: https://github.com/pre-commit/mirrors-mypy
rev: "v0.910"
- repo: local
hooks:
- id: mypy
name: mypy
language: system
entry: mypy
args:
[
"--config-file",
"api/http/mypy.ini"
]
types: [ python ]
2 changes: 1 addition & 1 deletion api/http/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
# limitations under the License.

# For test purposes
FROM python:3.9-slim-buster as indigo_service_dev
FROM python:3.10-slim-buster as indigo_service_dev

RUN mkdir -p /opt/indigo
WORKDIR /opt/indigo
Expand Down
81 changes: 23 additions & 58 deletions api/http/indigo_service/indigo_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ def compounds(
jsonapi.ValidationRequest,
jsonapi.CompoundConvertRequest,
jsonapi.RenderRequest,
jsonapi.PKARequest,
],
) -> List[Tuple[str, jsonapi.CompoundFormat]]:
return service.extract_pairs(request.data.attributes.compound)
Expand Down Expand Up @@ -190,6 +191,27 @@ def descriptors(
return jsonapi.make_descriptor_response(results)


@app.post(f"{BASE_URL_INDIGO}/pka", response_model=jsonapi.PKAResponse)
def pka(request: jsonapi.PKARequest) -> jsonapi.PKAResponse:
compound, *_ = service.extract_compounds(compounds(request))
if request.data.attributes.pka_model == jsonapi.PKAModel.ADVANCED:
indigo().setOption("pKa-model", jsonapi.PKAModel.ADVANCED.value)
pka_model_level = request.data.attributes.pka_model_level
pka_model_min_level = request.data.attributes.pka_model_min_level
pka_values = jsonapi.AtomToValueContainer()
for atom in compound.iterateAtoms():
pka_values.mappings.append(
jsonapi.AtomToValueMapping(
index=atom.index(),
symbol=atom.symbol(),
value=compound.getAcidPkaValue(
atom, pka_model_level, pka_model_min_level
),
)
)
return jsonapi.make_pka_response(pka_values)


@app.post(
f"{BASE_URL_INDIGO}/commonBits",
response_model=jsonapi.CommonBitsResponse,
Expand All @@ -209,9 +231,7 @@ def common_bits(


@app.post(f"{BASE_URL_INDIGO}/render", response_model=jsonapi.RenderResponse)
def render(
request: jsonapi.RenderRequest,
) -> jsonapi.RenderResponse:
def render(request: jsonapi.RenderRequest,) -> jsonapi.RenderResponse:
compound, *_ = service.extract_compounds(compounds(request))
output_format = request.data.attributes.outputFormat
indigo_renderer = IndigoRenderer(indigo())
Expand Down Expand Up @@ -245,58 +265,3 @@ def run_debug() -> None:

if __name__ == "__main__":
run_debug()


# TODO: /indigo/render with alternative responses types
# @app.post(f"{BASE_URL_INDIGO}/render")
# def render(
# request: jsonapi.RenderRequest,
# ) -> Union[Response, FileResponse]:
# compound, *_ = service.extract_compounds(compounds(request))
# output_format = request.data.attributes.outputFormat
# indigo_renderer = IndigoRenderer(indigo())
# indigo().setOption(
# "render-output-format", jsonapi.rendering_formats.get(output_format)
# )
# options = request.data.attributes.options
# if options:
# for option, value in options.items():
# if option == "render-output-format":
# raise HTTPException(
# status_code=400, detail="Choose only one output format"
# )
# indigo().setOption(option, value)
# if output_format == "image/png":
# result = indigo_renderer.renderToBuffer(compound).tobytes()
# response = Response(
# result,
# headers={"Content-Type": "image/png"}
# )
# elif output_format == "image/png;base64":
# result = indigo_renderer.renderToBuffer(compound).tobytes()
# decoded_image = base64.b64encode(result).decode("utf-8")
# image_base64 = f"data:image/png;base64,{decoded_image}"
# response = Response(
# image_base64,
# headers={"Content-Type": "image/png"}
# )
# elif output_format == "image/svg+xml":
# result = indigo_renderer.renderToString(compound)
# response = Response(
# result,
# headers={"Content-Type": "image/svg+xml"}
# )
# elif output_format == "application/pdf":
# result = indigo_renderer.renderToBuffer(compound).tobytes()
# response = Response(
# result, headers={
# "Content-Type": "application/pdf",
# "Content-Disposition": "attachment; filename=mol.pdf"
# }
# )
# else:
# raise HTTPException(
# status_code=400,
# detail=f"Incorrect output format {output_format}"
# )
# return response
56 changes: 50 additions & 6 deletions api/http/indigo_service/jsonapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -515,8 +515,6 @@ class Descriptors(str, Enum):
MONOISOTOPIC_MASS = "monoisotopicMass"
MOST_ABUNDANT_MASS = "mostAbundantMass"
NAME = "name"
GET_ACID_PKA_VALUE = "acidPkaValue"
GET_BASIC_PKA_VALUE = "basicPkaValue"
GROSS_FORMULA = "grossFormula"


Expand Down Expand Up @@ -563,8 +561,6 @@ class DescriptorResultModel(BaseModel):
monoisotopicMass: Optional[str]
mostAbundantMass: Optional[str]
name: Optional[str]
getAcidPkaValue: Optional[str]
getBasicPkaValue: Optional[str]
grossFormula: Optional[str]


Expand All @@ -585,6 +581,55 @@ def make_descriptor_response(
]


# PKA models


class PKAType(str, Enum):
ACID = "acid"
BASIC = "basic"


class PKAModel(str, Enum):
SIMPLE = "simple"
ADVANCED = "advanced"


class PKARequestModel(BaseModel):
compound: CompoundObject
pka_model: PKAModel
pka_type: PKAType = PKAType.ACID
pka_model_level: int = 0
pka_model_min_level: int = 0


class PKARequestModelType(BaseModel):
__root__ = "pka"


class AtomToValueMapping(BaseModel):
index: int
symbol: str
value: float


class AtomToValueContainer(BaseModel):
mappings: list[AtomToValueMapping] = []


class PKAResultModelType(BaseModel):
__root__ = "pkaResult"


PKARequest = Request[PKARequestModelType, PKARequestModel]
PKAResponse = Response[PKAResultModelType, AtomToValueContainer]


def make_pka_response(mappings: AtomToValueContainer) -> PKAResponse:
return PKAResponse(
**{"data": {"type": "pkaResult", "attributes": mappings}}
)


# Render


Expand Down Expand Up @@ -618,8 +663,7 @@ class RenderResultModel(BaseModel):


def make_render_response(
raw_image: bytes,
output_format: str,
raw_image: bytes, output_format: str
) -> RenderResponse:
if output_format == "image/svg+xml":
str_image = raw_image.decode("utf-8")
Expand Down
1 change: 1 addition & 0 deletions api/http/mypy.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
python_version = 3.9
strict = True
plugins = pydantic.mypy
exclude = dist

[mypy-indigo.*]
ignore_missing_imports = True
Expand Down
1 change: 1 addition & 0 deletions api/http/requirements_dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ types-requests==2.26.3
urllib3==1.26.7
isort==5.9.3
pylint==2.11.1
mypy==0.910

0 comments on commit 49e965a

Please sign in to comment.