Download model/PXDesignBench/pxdbench/scripts/postprocess_monomer.py from OneScience-Group/PXDesign: direct link, hf CLI and curl.
- Browser
- Download file 6.09 kB
-
https://huggingface.co/OneScience-Group/PXDesign/resolve/main/model/PXDesignBench/pxdbench/scripts/postprocess_monomer.py
- Command line
-
hf download hf://OneScience-Group/PXDesign/model/PXDesignBench/pxdbench/scripts/postprocess_monomer.py
-
curl -L -o postprocess_monomer.py https://huggingface.co/OneScience-Group/PXDesign/resolve/main/model/PXDesignBench/pxdbench/scripts/postprocess_monomer.py
6.09 kB
| import argparse | |
| import shutil | |
| import subprocess | |
| from pathlib import Path | |
| import numpy as np | |
| from pxdbench.metrics.diversity import compute_diversity | |
| from pxdbench.utils import str2bool | |
| FOLDSEEK_BIN = "your_foldseek_dir/bin/foldseek" | |
| FOLDSEEK_DB = "your_foldseek_dir/foldseek_db/pdb/pdb" | |
| def compute_fs_diversity(input_dir: Path, num_threads=32): | |
| num_pdbs = sum(1 for f in input_dir.glob("*.pdb") if f.is_file()) | |
| cluster_out = input_dir / "fs_diversity" / "res" | |
| tmp_dir = input_dir / "fs_diversity_tmp" | |
| cluster_out.parent.mkdir(parents=True, exist_ok=True) | |
| cluster_tsv = cluster_out.with_name(cluster_out.stem + "_cluster.tsv") | |
| if tmp_dir.exists(): | |
| shutil.rmtree(tmp_dir) | |
| tmp_dir.mkdir(parents=True, exist_ok=True) | |
| if not cluster_tsv.exists(): | |
| subprocess.run( | |
| [ | |
| FOLDSEEK_BIN, | |
| "easy-cluster", | |
| str(input_dir), | |
| str(cluster_out), | |
| str(tmp_dir), | |
| "--alignment-type", | |
| "1", | |
| "--cov-mode", | |
| "0", | |
| "--min-seq-id", | |
| "0", | |
| "--tmscore-threshold", | |
| "0.5", | |
| "--threads", | |
| f"{num_threads}", | |
| ], | |
| check=True, | |
| ) | |
| # Count clusters and samples | |
| num_clusters = 0 | |
| seen_clusters = set() | |
| if cluster_tsv.exists(): | |
| with open(cluster_tsv) as f: | |
| for line in f: | |
| cluster_name, member = line.strip().split("\t") | |
| if cluster_name not in seen_clusters: | |
| seen_clusters.add(cluster_name) | |
| num_clusters += 1 | |
| diversity_cluster = num_clusters / max(num_pdbs, 1) | |
| shutil.rmtree(tmp_dir) | |
| return diversity_cluster | |
| def compute_fs_novelty(input_dir: Path, use_gpu=True, num_threads=32): | |
| tmp_dir = input_dir / "fs_novelty_tmp" | |
| if tmp_dir.exists(): | |
| shutil.rmtree(tmp_dir) | |
| novelty_out = input_dir / "fs_novelty" / "novelty.tsv" | |
| novelty_out.parent.mkdir(parents=True, exist_ok=True) | |
| if not novelty_out.exists(): | |
| cmd = [ | |
| FOLDSEEK_BIN, | |
| "easy-search", | |
| str(input_dir), | |
| FOLDSEEK_DB, | |
| str(novelty_out), | |
| str(tmp_dir), | |
| "--alignment-type", | |
| "1", | |
| "--exhaustive-search", | |
| "--tmscore-threshold", | |
| "0.0", | |
| "--max-seqs", | |
| "10000000000", | |
| "--format-output", | |
| "query,target,alntmscore,lddt", | |
| "--threads", | |
| f"{num_threads}", | |
| ] | |
| if use_gpu: | |
| cmd.extend(["--gpu", "1", "--prefilter-mode", "1"]) | |
| subprocess.run( | |
| cmd, | |
| check=True, | |
| ) | |
| max_scores = {} | |
| if novelty_out.exists(): | |
| with open(novelty_out) as f: | |
| for line in f: | |
| query, _, tmscore, _ = line.strip().split("\t") | |
| tmscore = float(tmscore) | |
| if query not in max_scores or tmscore > max_scores[query]: | |
| max_scores[query] = tmscore | |
| novelty_score = np.mean(list(max_scores.values())) | |
| shutil.rmtree(tmp_dir) | |
| return novelty_score | |
| def main(): | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument("--input_dir", type=str) | |
| parser.add_argument("--output_dir", type=str, default=None) | |
| parser.add_argument("--eval_novelty", action="store_true", default=False) | |
| parser.add_argument("--use_gpu", type=str2bool, default=True) | |
| parser.add_argument("--num_threads", type=int, default=32) | |
| args = parser.parse_args() | |
| input_dir = Path(args.input_dir) | |
| if not input_dir.exists(): | |
| print(f"Input dir does not exist! {input_dir}") | |
| return | |
| if args.output_dir is None: | |
| output_dir = input_dir / "postprocess" | |
| else: | |
| output_dir = Path(args.output_dir) | |
| output_dir.mkdir(parents=True, exist_ok=True) | |
| output_csv_path = output_dir / "diversity_and_novelty.csv" | |
| fieldnames = ["num_samples", "diversity_tm", "diversity_cluster", "novelty"] | |
| # scan PDBs | |
| pdb_paths = sorted(input_dir.glob("*.pdb")) | |
| pdb_paths = [p for p in pdb_paths if p.is_file()] | |
| if len(pdb_paths) == 0: | |
| print(f"No PDB files found in {input_dir}") | |
| # wrtie an empty file | |
| with open(output_csv_path, "w") as f: | |
| f.write(",".join(fieldnames) + "\n") | |
| f.write("0,,,\n") | |
| return | |
| # Diversity (TM) | |
| try: | |
| diversity_tm = compute_diversity(pdb_paths) if len(pdb_paths) >= 2 else np.nan | |
| except Exception as e: | |
| print(f"compute_diversity failed: {e}") | |
| diversity_tm = np.nan | |
| # Diversity (Cluster, Foldseek) | |
| try: | |
| diversity_cluster = compute_fs_diversity( | |
| input_dir, num_threads=args.num_threads | |
| ) | |
| except Exception as e: | |
| print(f"compute_fs_diversity failed: {e}") | |
| diversity_cluster = np.nan | |
| novelty = np.nan | |
| if args.eval_novelty: | |
| if not Path(FOLDSEEK_BIN).exists(): | |
| print(f"Foldseek binary not found: {FOLDSEEK_BIN}, skip novelty.") | |
| elif ( | |
| not Path(FOLDSEEK_DB + ".dbtype").exists() | |
| and not Path(FOLDSEEK_DB).exists() | |
| ): | |
| print(f"Foldseek DB not found: {FOLDSEEK_DB}, skip novelty.") | |
| else: | |
| try: | |
| novelty = compute_fs_novelty( | |
| input_dir, args.use_gpu, num_threads=args.num_threads | |
| ) | |
| except Exception as e: | |
| print(f"compute_fs_novelty failed: {e}") | |
| novelty = np.nan | |
| with open(output_csv_path, "w") as f: | |
| f.write(",".join(fieldnames) + "\n") | |
| f.write(f"{len(pdb_paths)},{diversity_tm},{diversity_cluster},{novelty}\n") | |
| print(f"Wrote results to {output_csv_path}") | |
| if __name__ == "__main__": | |
| main() | |