ynuozhang commited on
Commit Β·
8cf0b21
1
Parent(s): adff1ee
update more test code for inference
Browse files- README.md +12 -4
- inference.py +163 -54
- requirements.txt +16 -10
README.md
CHANGED
|
@@ -82,13 +82,13 @@ pip install -r requirements.txt
|
|
| 82 |
```
|
| 83 |
### Full Setup
|
| 84 |
- Additional access to trained SVM and ElastNet models requires installation of `RAPIDS cuML`, with instructions available from their official [github page](https://github.com/rapidsai/cuml) (**CUDA-capable GPU required**).
|
| 85 |
-
- Optional: pre-compiled Singularity/Apptainer environment (
|
| 86 |
```
|
| 87 |
# test
|
| 88 |
apptainer exec peptiverse.sif python -c "import sys; print(sys.executable)"
|
| 89 |
|
| 90 |
# run inference (see below)
|
| 91 |
-
apptainer exec peptiverse.sif python inference.py
|
| 92 |
```
|
| 93 |
## Repository Structure π
|
| 94 |
This repo contains important large files for [PeptiVerse](https://huggingface.co/spaces/ChatterjeeLab/PeptiVerse), an interactive app for peptide property prediction. [Paper link.](https://www.biorxiv.org/content/10.64898/2025.12.31.697180v1)
|
|
@@ -112,6 +112,14 @@ PeptiVerse/
|
|
| 112 |
```
|
| 113 |
For full data access, please download the corresponding `training_data_cleaned` and `training_classifiers` from [HuggingFace Dataset](https://huggingface.co/datasets/ChatterjeeLab/PeptiVerse_data) and [Zenodo](https://zenodo.org/records/19989009). The current Huggingface repo only hosts best model weights and meta data with splits labels.
|
| 114 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 115 |
## Training Data Collection π
|
| 116 |
|
| 117 |
<table>
|
|
@@ -241,7 +249,7 @@ python app.py
|
|
| 241 |
Under the `training_data_cleaned`, we provided the generated embeddings in huggingface dataset format. The following scripts are the steps used to generate the data.
|
| 242 |
|
| 243 |
### Dataset integration
|
| 244 |
-
- All processed training datasets are available at [ChatterjeeLab/
|
| 245 |
- Selective download the data you need with `huggingface-cli`
|
| 246 |
```bash
|
| 247 |
huggingface-cli download ChatterjeeLab/PeptiVerse_data \
|
|
@@ -681,4 +689,4 @@ If you find this repository helpful for your publications, please consider citin
|
|
| 681 |
journal = {bioRxiv}
|
| 682 |
}
|
| 683 |
```
|
| 684 |
-
To use this repository, you agree to abide by the MIT License.
|
|
|
|
| 82 |
```
|
| 83 |
### Full Setup
|
| 84 |
- Additional access to trained SVM and ElastNet models requires installation of `RAPIDS cuML`, with instructions available from their official [github page](https://github.com/rapidsai/cuml) (**CUDA-capable GPU required**).
|
| 85 |
+
- Optional: pre-compiled Singularity/Apptainer environment (5.68G) is available at [Google drive](https://drive.google.com/file/d/1ybLJNTC3BITIqBd8IO09nOOm4PKwD4iS/view?usp=sharing) with everything you need (still need CUDA/GPU to load cuML models). The SHA256 for checking is `48619796ef0adc81bc420021821e5ee3d9b2176bf1f564104e06dc1ce56b3498`, check via `shasum -a 256 peptiverse.sif`.
|
| 86 |
```
|
| 87 |
# test
|
| 88 |
apptainer exec peptiverse.sif python -c "import sys; print(sys.executable)"
|
| 89 |
|
| 90 |
# run inference (see below)
|
| 91 |
+
apptainer exec --nv peptiverse.sif python inference.py
|
| 92 |
```
|
| 93 |
## Repository Structure π
|
| 94 |
This repo contains important large files for [PeptiVerse](https://huggingface.co/spaces/ChatterjeeLab/PeptiVerse), an interactive app for peptide property prediction. [Paper link.](https://www.biorxiv.org/content/10.64898/2025.12.31.697180v1)
|
|
|
|
| 112 |
```
|
| 113 |
For full data access, please download the corresponding `training_data_cleaned` and `training_classifiers` from [HuggingFace Dataset](https://huggingface.co/datasets/ChatterjeeLab/PeptiVerse_data) and [Zenodo](https://zenodo.org/records/19989009). The current Huggingface repo only hosts best model weights and meta data with splits labels.
|
| 114 |
|
| 115 |
+
```
|
| 116 |
+
1. Download and extract the Zenodo archive.
|
| 117 |
+
2. Download or clone this repository.
|
| 118 |
+
3. Copy/merge the repository `training_classifiers/` contents into the extracted Zenodo `training_classifiers/` directory, preserving the folder structure.
|
| 119 |
+
`rsync -av --ignore-existing training_classifiers/ /path/to/zenodo_extracted/training_classifiers/`
|
| 120 |
+
4. Do not replace the entire Zenodo folder blindly; merge files so that large training outputs from Zenodo and updated best-model weights from this repository coexist.
|
| 121 |
+
```
|
| 122 |
+
|
| 123 |
## Training Data Collection π
|
| 124 |
|
| 125 |
<table>
|
|
|
|
| 249 |
Under the `training_data_cleaned`, we provided the generated embeddings in huggingface dataset format. The following scripts are the steps used to generate the data.
|
| 250 |
|
| 251 |
### Dataset integration
|
| 252 |
+
- All processed training datasets are available at [ChatterjeeLab/PeptiVerse\_data](https://huggingface.co/datasets/ChatterjeeLab/PeptiVerse_data).
|
| 253 |
- Selective download the data you need with `huggingface-cli`
|
| 254 |
```bash
|
| 255 |
huggingface-cli download ChatterjeeLab/PeptiVerse_data \
|
|
|
|
| 689 |
journal = {bioRxiv}
|
| 690 |
}
|
| 691 |
```
|
| 692 |
+
To use this repository, you agree to abide by the MIT License.
|
inference.py
CHANGED
|
@@ -13,10 +13,6 @@ from tokenizer.my_tokenizers import SMILES_SPE_Tokenizer
|
|
| 13 |
from lightning.pytorch import seed_everything
|
| 14 |
seed_everything(1986)
|
| 15 |
|
| 16 |
-
# -----------------------------
|
| 17 |
-
# Manifest
|
| 18 |
-
# -----------------------------
|
| 19 |
-
|
| 20 |
EMB_TAG_TO_FOLDER_SUFFIX = {
|
| 21 |
"wt": "wt",
|
| 22 |
"peptideclm": "peptideclm",
|
|
@@ -372,17 +368,10 @@ def _mapie_uncertainty(mapie_bundle: dict, score: float,
|
|
| 372 |
if "quantile" in mapie_bundle:
|
| 373 |
q = float(mapie_bundle["quantile"])
|
| 374 |
return float(score - q), float(score + q)
|
| 375 |
-
|
| 376 |
-
X_dummy = np.zeros((1, 1))
|
| 377 |
-
result = mapie.predict(X_dummy)
|
| 378 |
-
if isinstance(result, tuple):
|
| 379 |
-
intervals = np.asarray(result[1])
|
| 380 |
-
if intervals.ndim == 3:
|
| 381 |
-
return float(intervals[0, 0, 0]), float(intervals[0, 1, 0])
|
| 382 |
-
return float(intervals[0, 0]), float(intervals[0, 1])
|
| 383 |
raise RuntimeError(
|
| 384 |
-
f"
|
| 385 |
-
f"
|
| 386 |
)
|
| 387 |
|
| 388 |
def affinity_to_class(y: float) -> int:
|
|
@@ -870,8 +859,11 @@ class PeptiVersePredictor:
|
|
| 870 |
mapie_bundle = self.mapie.get((prop_key, col))
|
| 871 |
if mapie_bundle:
|
| 872 |
emb = get_pooled_emb() if mapie_bundle.get("adaptive") else None
|
| 873 |
-
|
| 874 |
-
|
|
|
|
|
|
|
|
|
|
| 875 |
# Fall back to seed ensemble std
|
| 876 |
ens = self.ensembles.get((prop_key, col))
|
| 877 |
if ens:
|
|
@@ -892,8 +884,11 @@ class PeptiVersePredictor:
|
|
| 892 |
mapie_bundle = self.mapie.get((prop_key, col))
|
| 893 |
if mapie_bundle:
|
| 894 |
emb = get_pooled_emb() if mapie_bundle.get("adaptive") else None
|
| 895 |
-
|
| 896 |
-
|
|
|
|
|
|
|
|
|
|
| 897 |
return None, "unavailable (no MAPIE bundle for XGBoost regression)"
|
| 898 |
|
| 899 |
# SVR / ElasticNet regression: MAPIE
|
|
@@ -901,8 +896,11 @@ class PeptiVersePredictor:
|
|
| 901 |
mapie_bundle = self.mapie.get((prop_key, col))
|
| 902 |
if mapie_bundle:
|
| 903 |
emb = get_pooled_emb() if mapie_bundle.get("adaptive") else None
|
| 904 |
-
|
| 905 |
-
|
|
|
|
|
|
|
|
|
|
| 906 |
return None, "unavailable (MAPIE bundle not found)"
|
| 907 |
|
| 908 |
# joblib classifiers (SVM, ElasticNet used as classifier)
|
|
@@ -1035,9 +1033,13 @@ class PeptiVersePredictor:
|
|
| 1035 |
emb = np.concatenate([t_vec, b_vec], axis=1)
|
| 1036 |
else:
|
| 1037 |
emb = None
|
| 1038 |
-
|
| 1039 |
-
|
| 1040 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1041 |
else:
|
| 1042 |
out["uncertainty"] = None
|
| 1043 |
out["uncertainty_type"] = "unavailable (no MAPIE bundle found)"
|
|
@@ -1045,35 +1047,142 @@ class PeptiVersePredictor:
|
|
| 1045 |
return out
|
| 1046 |
|
| 1047 |
if __name__ == "__main__":
|
| 1048 |
-
|
| 1049 |
|
| 1050 |
-
|
| 1051 |
-
|
| 1052 |
-
|
| 1053 |
-
|
| 1054 |
-
|
| 1055 |
-
|
| 1056 |
-
|
| 1057 |
-
|
| 1058 |
-
|
| 1059 |
-
|
| 1060 |
-
|
| 1061 |
-
|
| 1062 |
-
|
| 1063 |
-
|
| 1064 |
-
|
| 1065 |
-
|
| 1066 |
-
|
| 1067 |
-
|
| 1068 |
-
|
| 1069 |
-
|
| 1070 |
-
|
| 1071 |
-
|
| 1072 |
-
|
| 1073 |
-
|
| 1074 |
-
|
| 1075 |
-
|
| 1076 |
-
|
| 1077 |
-
|
| 1078 |
-
|
| 1079 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
from lightning.pytorch import seed_everything
|
| 14 |
seed_everything(1986)
|
| 15 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
EMB_TAG_TO_FOLDER_SUFFIX = {
|
| 17 |
"wt": "wt",
|
| 18 |
"peptideclm": "peptideclm",
|
|
|
|
| 368 |
if "quantile" in mapie_bundle:
|
| 369 |
q = float(mapie_bundle["quantile"])
|
| 370 |
return float(score - q), float(score + q)
|
| 371 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 372 |
raise RuntimeError(
|
| 373 |
+
f"Unrecognised MAPIE bundle (keys={list(mapie_bundle.keys()) if isinstance(mapie_bundle, dict) else type(mapie_bundle).__name__}). "
|
| 374 |
+
f"Run repair_mapie_bundles.py to convert."
|
| 375 |
)
|
| 376 |
|
| 377 |
def affinity_to_class(y: float) -> int:
|
|
|
|
| 859 |
mapie_bundle = self.mapie.get((prop_key, col))
|
| 860 |
if mapie_bundle:
|
| 861 |
emb = get_pooled_emb() if mapie_bundle.get("adaptive") else None
|
| 862 |
+
try:
|
| 863 |
+
lo, hi = _mapie_uncertainty(mapie_bundle, score, emb)
|
| 864 |
+
return (lo, hi), "conformal_prediction_interval"
|
| 865 |
+
except RuntimeError as _e:
|
| 866 |
+
return None, f"unavailable (legacy bundle: {_e})"
|
| 867 |
# Fall back to seed ensemble std
|
| 868 |
ens = self.ensembles.get((prop_key, col))
|
| 869 |
if ens:
|
|
|
|
| 884 |
mapie_bundle = self.mapie.get((prop_key, col))
|
| 885 |
if mapie_bundle:
|
| 886 |
emb = get_pooled_emb() if mapie_bundle.get("adaptive") else None
|
| 887 |
+
try:
|
| 888 |
+
lo, hi = _mapie_uncertainty(mapie_bundle, score, emb)
|
| 889 |
+
return (lo, hi), "conformal_prediction_interval"
|
| 890 |
+
except RuntimeError as _e:
|
| 891 |
+
return None, f"unavailable (legacy bundle: {_e})"
|
| 892 |
return None, "unavailable (no MAPIE bundle for XGBoost regression)"
|
| 893 |
|
| 894 |
# SVR / ElasticNet regression: MAPIE
|
|
|
|
| 896 |
mapie_bundle = self.mapie.get((prop_key, col))
|
| 897 |
if mapie_bundle:
|
| 898 |
emb = get_pooled_emb() if mapie_bundle.get("adaptive") else None
|
| 899 |
+
try:
|
| 900 |
+
lo, hi = _mapie_uncertainty(mapie_bundle, score, emb)
|
| 901 |
+
return (lo, hi), "conformal_prediction_interval"
|
| 902 |
+
except RuntimeError as _e:
|
| 903 |
+
return None, f"unavailable (legacy bundle: {_e})"
|
| 904 |
return None, "unavailable (MAPIE bundle not found)"
|
| 905 |
|
| 906 |
# joblib classifiers (SVM, ElasticNet used as classifier)
|
|
|
|
| 1033 |
emb = np.concatenate([t_vec, b_vec], axis=1)
|
| 1034 |
else:
|
| 1035 |
emb = None
|
| 1036 |
+
try:
|
| 1037 |
+
lo, hi = _mapie_uncertainty(mapie_bundle, affinity, emb)
|
| 1038 |
+
out["uncertainty"] = (lo, hi)
|
| 1039 |
+
out["uncertainty_type"] = "conformal_prediction_interval"
|
| 1040 |
+
except RuntimeError as _e:
|
| 1041 |
+
out["uncertainty"] = None
|
| 1042 |
+
out["uncertainty_type"] = f"unavailable (legacy bundle: {_e})"
|
| 1043 |
else:
|
| 1044 |
out["uncertainty"] = None
|
| 1045 |
out["uncertainty_type"] = "unavailable (no MAPIE bundle found)"
|
|
|
|
| 1047 |
return out
|
| 1048 |
|
| 1049 |
if __name__ == "__main__":
|
| 1050 |
+
import traceback, time
|
| 1051 |
|
| 1052 |
+
root = Path(__file__).resolve().parent
|
| 1053 |
+
|
| 1054 |
+
SEQ = "GIGAVLKVLTTGLPALISWIKRKRQQ"
|
| 1055 |
+
SEQ2 = "ACDEFGHIKLMNPQRSTVWY"
|
| 1056 |
+
BINDER = "GIGAVLKVLT"
|
| 1057 |
+
SMILES = ("C(C)C[C@@H]1NC(=O)[C@@H]2CCCN2C(=O)[C@@H](CC(C)C)"
|
| 1058 |
+
"NC(=O)[C@@H](CC(C)C)N(C)C(=O)[C@H](C)NC(=O)"
|
| 1059 |
+
"[C@H](Cc2ccccc2)NC1=O")
|
| 1060 |
+
|
| 1061 |
+
COL_INPUT = {"wt": SEQ, "smiles": SMILES}
|
| 1062 |
+
BINDING_BINDER = {"wt": BINDER, "smiles": SMILES}
|
| 1063 |
+
|
| 1064 |
+
MANIFESTS = [
|
| 1065 |
+
("best_models.txt", "best"),
|
| 1066 |
+
("basic_models.txt", "basic"),
|
| 1067 |
+
]
|
| 1068 |
+
|
| 1069 |
+
all_results: List[Tuple[str, str, str]] = [] # (label, status, detail)
|
| 1070 |
+
|
| 1071 |
+
for manifest_file, label in MANIFESTS:
|
| 1072 |
+
sep = "=" * 72
|
| 1073 |
+
print(f"\n{sep}")
|
| 1074 |
+
print(f" MANIFEST: {manifest_file} [{label}]")
|
| 1075 |
+
print(sep)
|
| 1076 |
+
|
| 1077 |
+
predictor = PeptiVersePredictor(
|
| 1078 |
+
manifest_path=root / manifest_file,
|
| 1079 |
+
classifier_weight_root=root,
|
| 1080 |
+
)
|
| 1081 |
+
|
| 1082 |
+
print(f"\n Models loaded : {len(predictor.models)}")
|
| 1083 |
+
print(f" MAPIE keys : {sorted(predictor.mapie.keys())}")
|
| 1084 |
+
print(f" Ensemble keys : {sorted(predictor.ensembles.keys())}")
|
| 1085 |
+
print()
|
| 1086 |
+
|
| 1087 |
+
# ββ Regular properties βββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 1088 |
+
for prop_key, row in predictor.manifest.items():
|
| 1089 |
+
if prop_key == "binding_affinity":
|
| 1090 |
+
continue
|
| 1091 |
+
|
| 1092 |
+
for col in ("wt", "smiles"):
|
| 1093 |
+
if (prop_key, col) not in predictor.models:
|
| 1094 |
+
continue
|
| 1095 |
+
|
| 1096 |
+
input_str = COL_INPUT[col]
|
| 1097 |
+
has_mapie = (prop_key, col) in predictor.mapie
|
| 1098 |
+
|
| 1099 |
+
for uncertainty in (False, True):
|
| 1100 |
+
tag = f"{label}/{prop_key}/{col}/unc={uncertainty}"
|
| 1101 |
+
try:
|
| 1102 |
+
t0 = time.time()
|
| 1103 |
+
r = predictor.predict_property(
|
| 1104 |
+
prop_key, col, input_str, uncertainty=uncertainty
|
| 1105 |
+
)
|
| 1106 |
+
dt = time.time() - t0
|
| 1107 |
+
|
| 1108 |
+
score_str = f"score={r['score']:.4f}"
|
| 1109 |
+
if uncertainty:
|
| 1110 |
+
u = r.get("uncertainty")
|
| 1111 |
+
u_type = r.get("uncertainty_type", "")
|
| 1112 |
+
u_str = (f" unc={u[0]:.3f}..{u[1]:.3f}" if isinstance(u, tuple)
|
| 1113 |
+
else f" unc={u:.4f}" if u is not None
|
| 1114 |
+
else f" unc=None")
|
| 1115 |
+
mapie_flag = " [MAPIE]" if has_mapie else ""
|
| 1116 |
+
print(f" [PASS] {tag:<60} {dt:5.2f}s {score_str}{u_str} "
|
| 1117 |
+
f"({u_type}){mapie_flag}")
|
| 1118 |
+
else:
|
| 1119 |
+
print(f" [PASS] {tag:<60} {dt:5.2f}s {score_str}")
|
| 1120 |
+
|
| 1121 |
+
all_results.append((tag, "PASS", ""))
|
| 1122 |
+
except Exception as e:
|
| 1123 |
+
print(f" [FAIL] {tag}")
|
| 1124 |
+
traceback.print_exc()
|
| 1125 |
+
all_results.append((tag, "FAIL", str(e)))
|
| 1126 |
+
|
| 1127 |
+
# ββ Binding affinity βββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 1128 |
+
prop_key = "binding_affinity"
|
| 1129 |
+
for col in ("wt", "smiles"):
|
| 1130 |
+
if (prop_key, col) not in predictor.models:
|
| 1131 |
+
continue
|
| 1132 |
+
|
| 1133 |
+
binder_str = BINDING_BINDER[col]
|
| 1134 |
+
has_mapie = (prop_key, col) in predictor.mapie
|
| 1135 |
+
|
| 1136 |
+
for uncertainty in (False, True):
|
| 1137 |
+
tag = f"{label}/{prop_key}/{col}/unc={uncertainty}"
|
| 1138 |
+
try:
|
| 1139 |
+
t0 = time.time()
|
| 1140 |
+
r = predictor.predict_binding_affinity(
|
| 1141 |
+
col, target_seq=SEQ2, binder_str=binder_str, uncertainty=uncertainty
|
| 1142 |
+
)
|
| 1143 |
+
dt = time.time() - t0
|
| 1144 |
+
|
| 1145 |
+
aff_str = f"affinity={r['affinity']:.3f}"
|
| 1146 |
+
if uncertainty:
|
| 1147 |
+
u = r.get("uncertainty")
|
| 1148 |
+
u_type = r.get("uncertainty_type", "")
|
| 1149 |
+
u_str = (f" unc={u[0]:.3f}..{u[1]:.3f}" if isinstance(u, tuple)
|
| 1150 |
+
else f" unc=None")
|
| 1151 |
+
mapie_flag = " [MAPIE]" if has_mapie else ""
|
| 1152 |
+
print(f" [PASS] {tag:<60} {dt:5.2f}s {aff_str}{u_str} "
|
| 1153 |
+
f"({u_type}){mapie_flag}")
|
| 1154 |
+
else:
|
| 1155 |
+
print(f" [PASS] {tag:<60} {dt:5.2f}s {aff_str} "
|
| 1156 |
+
f"cls={r['class_by_threshold']}")
|
| 1157 |
+
|
| 1158 |
+
all_results.append((tag, "PASS", ""))
|
| 1159 |
+
except Exception as e:
|
| 1160 |
+
print(f" [FAIL] {tag}")
|
| 1161 |
+
traceback.print_exc()
|
| 1162 |
+
all_results.append((tag, "FAIL", str(e)))
|
| 1163 |
+
|
| 1164 |
+
# ββ MAPIE bundle inventory βββββββββββββββββββββββββββββββββββββββββββββ
|
| 1165 |
+
print(f"\n --- MAPIE bundle inventory [{label}] ---")
|
| 1166 |
+
if not predictor.mapie:
|
| 1167 |
+
print(" (none)")
|
| 1168 |
+
for (pk, col), bundle in sorted(predictor.mapie.items()):
|
| 1169 |
+
fmt = "adaptive" if bundle.get("adaptive") else "plain_quantile"
|
| 1170 |
+
q = bundle.get("quantile", "?")
|
| 1171 |
+
sigma = "sigma_model=" + type(bundle["sigma_model"]).__name__ if "sigma_model" in bundle else ""
|
| 1172 |
+
print(f" {label}/{pk}/{col:<30} format={fmt} q={q} {sigma}")
|
| 1173 |
+
|
| 1174 |
+
# ββ Summary ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 1175 |
+
sep = "=" * 72
|
| 1176 |
+
print(f"\n{sep}")
|
| 1177 |
+
print(" SUMMARY")
|
| 1178 |
+
print(sep)
|
| 1179 |
+
passed = [r for r in all_results if r[1] == "PASS"]
|
| 1180 |
+
failed = [r for r in all_results if r[1] == "FAIL"]
|
| 1181 |
+
print(f" PASSED : {len(passed)} / {len(all_results)}")
|
| 1182 |
+
if failed:
|
| 1183 |
+
print(f" FAILED : {len(failed)}")
|
| 1184 |
+
for tag, _, err in failed:
|
| 1185 |
+
print(f" β {tag}")
|
| 1186 |
+
print(f" {err}")
|
| 1187 |
+
else:
|
| 1188 |
+
print(" All tests passed.")
|
requirements.txt
CHANGED
|
@@ -1,14 +1,20 @@
|
|
| 1 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
pandas>=2.0.0
|
| 3 |
-
|
|
|
|
|
|
|
| 4 |
plotly>=5.14.0
|
| 5 |
-
torch>=2.0.0
|
| 6 |
-
transformers==4.46.0
|
| 7 |
-
scikit-learn>=1.3.0
|
| 8 |
-
biopython>=1.81
|
| 9 |
-
lightning==2.5.5
|
| 10 |
-
rdkit>=2023.3.1
|
| 11 |
seaborn
|
| 12 |
-
|
| 13 |
-
|
| 14 |
ipython
|
|
|
|
| 1 |
+
# ββ Core inference ββββββββββββββββββββββββββββββββ
|
| 2 |
+
numpy>=2.0.0 # cupy 14.x (RAPIDS 25.x dep) requires numpy >= 2.0
|
| 3 |
+
torch>=2.1.0
|
| 4 |
+
transformers==4.46.0
|
| 5 |
+
scikit-learn>=1.3.0
|
| 6 |
+
lightning==2.5.5
|
| 7 |
+
joblib>=1.3.0
|
| 8 |
+
xgboost>=2.0.0
|
| 9 |
+
SmilesPE
|
| 10 |
+
mapie>=0.6.0 # conformal prediction (fit_mapie_adaptive.py)
|
| 11 |
+
tqdm
|
| 12 |
pandas>=2.0.0
|
| 13 |
+
|
| 14 |
+
# ββ App ββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 15 |
+
gradio>=4.0.0
|
| 16 |
plotly>=5.14.0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
seaborn
|
| 18 |
+
rdkit>=2023.3.1
|
| 19 |
+
biopython>=1.81
|
| 20 |
ipython
|