PXDesign / model /PXDesignBench /pxdbench /scripts /postprocess_monomer.py
anzhi2710gmailcom's picture
Upload folder using huggingface_hub
d766458 verified
Raw
History Blame Contribute Delete
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()