Skip to content

Commit 6677be0

Browse files
committed
Merge catpred integration
2 parents 9c8ccbd + a6edb33 commit 6677be0

9 files changed

Lines changed: 124 additions & 2 deletions

File tree

Dockerfile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,15 @@ RUN --mount=type=cache,target=/opt/conda/pkgs,sharing=locked \
106106
&& mamba install -n catapro_env -c conda-forge rdkit=2024.03.6 -y \
107107
&& conda run -n catapro_env pip install -r docker-requirements/catapro_requirements.txt
108108

109+
# ── CatPred ───────────────────────────────────────────────────────────────────
110+
FROM base AS env-catpred
111+
COPY docker-requirements/catpred_requirements.txt ./docker-requirements/
112+
RUN --mount=type=cache,target=/opt/conda/pkgs,sharing=locked \
113+
--mount=type=cache,id=webkinpred-pip-py310,target=/root/.cache/pip,sharing=locked \
114+
mamba create -n catpred_env python=3.10.15 -c conda-forge -y \
115+
&& mamba install -n catpred_env -c conda-forge rdkit=2024.03.6 -y \
116+
&& conda run -n catpred_env pip install -r docker-requirements/catpred_requirements.txt
117+
109118
# ── pseq2sites ────────────────────────────────────────────────────────────────
110119
FROM base AS env-pseq2sites
111120
RUN --mount=type=cache,target=/opt/conda/pkgs,sharing=locked \
@@ -155,6 +164,7 @@ COPY --from=env-eitlem /opt/conda/envs/eitlem_env /opt/conda/envs/eitlem_en
155164
COPY --from=env-turnup /opt/conda/envs/turnup_env /opt/conda/envs/turnup_env
156165
COPY --from=env-unikp /opt/conda/envs/unikp /opt/conda/envs/unikp
157166
COPY --from=env-catapro /opt/conda/envs/catapro_env /opt/conda/envs/catapro_env
167+
COPY --from=env-catpred /opt/conda/envs/catpred_env /opt/conda/envs/catpred_env
158168
COPY --from=env-pseq2sites /opt/conda/envs/pseq2sites /opt/conda/envs/pseq2sites
159169
COPY --from=env-esm /opt/conda/envs/esm /opt/conda/envs/esm
160170
COPY --from=env-esmc /opt/conda/envs/esmc /opt/conda/envs/esmc
@@ -174,6 +184,7 @@ RUN find /opt/conda -name "*.pyc" -delete \
174184
COPY . .
175185

176186
RUN mkdir -p /app/models/EITLEM/Weights \
187+
/app/models/CatPred \
177188
/app/models/TurNup/data/saved_models \
178189
/app/models/UniKP-main/models \
179190
/app/media/sequence_info \

api/embeddings/registry.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,13 @@
3434
"implemented": True,
3535
"conda_env": "esm",
3636
"python_path_key": "esm2", # key in config PYTHON_PATHS
37-
"used_by": ["KinForm-H", "KinForm-L"],
37+
"used_by": ["KinForm-H", "KinForm-L", "CatPred"],
3838
"notes": (
3939
"Invoked as a subprocess by KinForm. The python path is passed via "
4040
"the KINFORM_ESM_PATH environment variable. Multi-layer embeddings "
41-
"are extracted in a single model-load pass."
41+
"are extracted in a single model-load pass. CatPred uses per-residue "
42+
"ESM2 features, so it bridges into a method-specific cache format "
43+
"rather than reusing the shared mean-vector cache directly."
4244
),
4345
},
4446

api/methods/catpred.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# api/methods/catpred.py
2+
#
3+
# Method descriptor for CatPred.
4+
5+
from api.methods.base import MethodDescriptor, SubprocessEngineConfig
6+
7+
8+
descriptor = MethodDescriptor(
9+
key="CatPred",
10+
display_name="CatPred",
11+
authors=(
12+
"Veda Sheersh Boorla, Somtirtha Santra, Costas D. Maranas"
13+
),
14+
publication_title=(
15+
"CatPred: A comprehensive framework for deep learning in vitro enzyme kinetic parameters"
16+
),
17+
citation_url="https://www.nature.com/articles/s41467-025-57215-9",
18+
repo_url="https://github.com/maranasgroup/CatPred",
19+
more_info=(
20+
"CatPred currently integrates kcat and Km through a local CPU inference "
21+
"adapter. Ki remains outside the current webKinPred target model."
22+
),
23+
24+
supports=["kcat", "Km"],
25+
input_format="single",
26+
output_cols={
27+
"kcat": "kcat (1/s)",
28+
"Km": "KM (mM)",
29+
},
30+
max_seq_len=2048,
31+
col_to_kwarg={"Substrate": "substrates"},
32+
target_kwargs={
33+
"kcat": {"kinetics_type": "KCAT"},
34+
"Km": {"kinetics_type": "KM"},
35+
},
36+
subprocess=SubprocessEngineConfig(
37+
python_path_key="CatPred",
38+
script_key="CatPred",
39+
data_path_env={
40+
"CATPRED_REPO_ROOT": "CatPred",
41+
"CATPRED_MEDIA_PATH": "media",
42+
"CATPRED_TOOLS_PATH": "tools",
43+
"PYTHONPATH": "CatPred",
44+
},
45+
extra_env={
46+
"PROTEIN_EMBED_USE_CPU": "1",
47+
},
48+
),
49+
embeddings_used=["esm2"],
50+
)

docker-compose.prod.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ services:
9595
- ./models/DLKcat/DeeplearningApproach:/app/models/DLKcat/DeeplearningApproach:ro
9696
- ./models/KinForm/results/trained_models:/app/models/KinForm/results/trained_models:ro
9797
- ./models/CataPro:/app/models/CataPro:ro
98+
- ./models/CatPred:/app/models/CatPred:ro
9899
environment:
99100
<<: *common-env
100101
depends_on:
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Requirements for CatPred (Python 3.10)
2+
torch==2.4.1
3+
fair-esm==2.0.0
4+
transformers==4.47.1
5+
sentencepiece==0.2.0
6+
numpy==1.26.4
7+
pandas==2.2.3
8+
pandas-flavor==0.6.0
9+
scikit-learn==1.5.2
10+
scipy==1.14.1
11+
tqdm==4.67.1
12+
typed-argument-parser==1.10.1
13+
descriptastorus==2.8.0
14+
rotary-embedding-torch==0.6.5
15+
hyperopt==0.2.7
16+
matplotlib==3.9.2
17+
tensorboardX==2.6.2.2

models/CatPred/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# CatPred
2+
3+
This directory is reserved for the CatPred integration.
4+
5+
Expected contents:
6+
- a checkout of the CatPred repository rooted at `models/CatPred/`
7+
- the adapter entrypoint at `models/CatPred/catpred/integration/webkinpred_adapter.py`
8+
9+
Local development can instead point webKinPred at an external CatPred checkout:
10+
11+
```bash
12+
export WEBKINPRED_CATPRED_ROOT="/absolute/path/to/CatPred"
13+
export WEBKINPRED_CATPRED_PYTHON="/absolute/path/to/CatPred/.venv/bin/python"
14+
```
15+
16+
Docker/runtime notes:
17+
- `webKinPred/config_docker.py` defaults to `/app/models/CatPred`
18+
- the CatPred subprocess descriptor sets `CATPRED_REPO_ROOT`, `CATPRED_MEDIA_PATH`, and `CATPRED_TOOLS_PATH`
19+
- CatPred kcat/Km use per-residue ESM2 features and cache them under
20+
`media/sequence_info/esm2_last/per_residue/{seq_id}.pt`

webKinPred/config_base.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111

1212
_DATA_PATH_REL = {
13+
"CatPred": "models/CatPred",
1314
"DLKcat": "models/DLKcat/DeeplearningApproach/Data",
1415
"DLKcat_Results": "models/DLKcat/DeeplearningApproach/Results",
1516
"EITLEM": "models/EITLEM",
@@ -23,6 +24,7 @@
2324

2425

2526
_PREDICTION_SCRIPT_REL = {
27+
"CatPred": "models/CatPred/catpred/integration/webkinpred_adapter.py",
2628
"DLKcat": "models/DLKcat/DeeplearningApproach/Code/example/prediction_for_input.py",
2729
"EITLEM": "models/EITLEM/Code/eitlem_prediction_script_batch.py",
2830
"TurNup": "models/TurNup/code/kcat_prediction_batch.py",

webKinPred/config_docker.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import os
2+
13
from webKinPred.config_base import (
24
DEFAULT_ALLOWED_FRONTEND_IPS,
35
SERVER_LIMIT,
@@ -13,6 +15,7 @@
1315
FASTAS_DIR = f"{BASE_PATH}/fastas"
1416

1517
PYTHON_PATHS = {
18+
"CatPred": "/opt/conda/envs/catpred_env/bin/python",
1619
"DLKcat": "/opt/conda/envs/dlkcat_env/bin/python",
1720
"EITLEM": "/opt/conda/envs/eitlem_env/bin/python",
1821
"TurNup": "/opt/conda/envs/turnup_env/bin/python",
@@ -28,6 +31,11 @@
2831
DATA_PATHS = build_data_paths(BASE_PATH)
2932
PREDICTION_SCRIPTS = build_prediction_scripts(BASE_PATH)
3033

34+
CATPRED_ROOT = os.environ.get("WEBKINPRED_CATPRED_ROOT")
35+
if CATPRED_ROOT:
36+
DATA_PATHS["CatPred"] = CATPRED_ROOT
37+
PREDICTION_SCRIPTS["CatPred"] = f"{CATPRED_ROOT}/catpred/integration/webkinpred_adapter.py"
38+
3139
SIMILARITY_DATASETS = build_similarity_datasets(FASTAS_DIR)
3240
TARGET_DBS = {label: item["target_db"] for label, item in SIMILARITY_DATASETS.items()}
3341

webKinPred/config_local.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ def _env_python(env_name: str) -> str:
2626

2727

2828
PYTHON_PATHS = {
29+
"CatPred": _env_python("catpred_env"),
2930
"DLKcat": _env_python("dlkcat_env"),
3031
"EITLEM": _env_python("eitlem_env"),
3132
"TurNup": _env_python("turnup_env"),
@@ -41,6 +42,16 @@ def _env_python(env_name: str) -> str:
4142
DATA_PATHS = build_data_paths(BASE_PATH)
4243
PREDICTION_SCRIPTS = build_prediction_scripts(BASE_PATH)
4344

45+
CATPRED_ROOT = os.environ.get("WEBKINPRED_CATPRED_ROOT")
46+
if CATPRED_ROOT:
47+
catpred_root = str(Path(CATPRED_ROOT).resolve())
48+
DATA_PATHS["CatPred"] = catpred_root
49+
PREDICTION_SCRIPTS["CatPred"] = str(Path(catpred_root) / "catpred" / "integration" / "webkinpred_adapter.py")
50+
PYTHON_PATHS["CatPred"] = os.environ.get(
51+
"WEBKINPRED_CATPRED_PYTHON",
52+
_env_python("catpred_env"),
53+
)
54+
4455
SIMILARITY_DATASETS = build_similarity_datasets(FASTAS_DIR)
4556
TARGET_DBS = {label: item["target_db"] for label, item in SIMILARITY_DATASETS.items()}
4657

0 commit comments

Comments
 (0)