import enum from datetime import datetime from typing import List import requests from django.conf import settings as s # Once stable these will be exposed by enviPy-plugins lib from envipy_additional_information import EnviPyModel, UIConfig, WidgetType # noqa: I001 from envipy_additional_information import register # noqa: I001 from bridge.contracts import Classifier # noqa: I001 from bridge.dto import ( BuildResult, EnviPyDTO, EvaluationResult, RunResult, TransformationProductPrediction, ) # noqa: I001 class BiotransformerEnvType(enum.Enum): CYP450 = "CYP450" ALLHUMAN = "ALLHUMAN" ECBASED = "ECBASED" HGUT = "HGUT" PHASEII = "PHASEII" ENV = "ENV" @register("biotransformerconfig") class BiotransformerConfig(EnviPyModel): env_type: BiotransformerEnvType class UI: title = "Biotransformer Type" env_type = UIConfig(widget=WidgetType.SELECT, label="Biotransformer Type", order=1) class Biotransformer(Classifier): Config = BiotransformerConfig def __init__(self, config: BiotransformerConfig | None = None): super().__init__(config) self.url = f"{s.BIOTRANSFORMER_URL}/biotransformer" @classmethod def requires_rule_packages(cls) -> bool: return False @classmethod def requires_data_packages(cls) -> bool: return False @classmethod def identifier(cls) -> str: return "biotransformer3" @classmethod def name(cls) -> str: return "Biotransformer 3.0" @classmethod def display(cls) -> str: return "Biotransformer 3.0" def build(self, eP: EnviPyDTO, *args, **kwargs) -> BuildResult | None: return def run(self, eP: EnviPyDTO, *args, **kwargs) -> RunResult: smiles = [c.smiles for c in eP.get_compounds()] preds = self._post(smiles) results = [] for substrate in preds.keys(): results.append( TransformationProductPrediction( substrate=substrate, products=preds[substrate], ) ) return RunResult( producer=eP.get_context().url, description=f"Generated at {datetime.now()}", result=results, ) def evaluate(self, eP: EnviPyDTO, *args, **kwargs) -> EvaluationResult: pass def build_and_evaluate(self, eP: EnviPyDTO, *args, **kwargs) -> EvaluationResult: pass def _post(self, smiles: List[str]) -> dict[str, dict[str, float]]: data = {"substrates": smiles, "mode": self.config.env_type.value} res = requests.post(self.url, json=data) res.raise_for_status() # Example Response JSON: # { # 'products': { # 'CN1C=NC2=C1C(=O)N(C(=O)N2C)C': { # 'CN1C2=C(C(=O)N(C)C1=O)NC=N2': 0.5, # 'CN1C=NC2=C1C(=O)N(C)C(=O)N2.CN1C=NC2=C1C(=O)NC(=O)N2C.CO': 0.5 # } # } # } return res.json()["products"]