| | import argparse |
| | import concurrent.futures |
| | import subprocess |
| | from pathlib import Path |
| |
|
| | from tqdm import tqdm |
| |
|
| | OST_COMPARE_STRUCTURE = r""" |
| | #!/bin/bash |
| | # https://openstructure.org/docs/2.7/actions/#ost-compare-structures |
| | |
| | IMAGE_NAME=openstructure-0.2.8 |
| | |
| | command="compare-structures \ |
| | -m {model_file} \ |
| | -r {reference_file} \ |
| | --fault-tolerant \ |
| | --min-pep-length 4 \ |
| | --min-nuc-length 4 \ |
| | -o {output_path} \ |
| | --lddt --bb-lddt --qs-score --dockq \ |
| | --ics --ips --rigid-scores --patch-scores --tm-score" |
| | |
| | sudo docker run -u $(id -u):$(id -g) --rm --volume {mount}:{mount} $IMAGE_NAME $command |
| | """ |
| |
|
| |
|
| | OST_COMPARE_LIGAND = r""" |
| | #!/bin/bash |
| | # https://openstructure.org/docs/2.7/actions/#ost-compare-structures |
| | |
| | IMAGE_NAME=openstructure-0.2.8 |
| | |
| | command="compare-ligand-structures \ |
| | -m {model_file} \ |
| | -r {reference_file} \ |
| | --fault-tolerant \ |
| | --lddt-pli --rmsd \ |
| | --substructure-match \ |
| | -o {output_path}" |
| | |
| | sudo docker run -u $(id -u):$(id -g) --rm --volume {mount}:{mount} $IMAGE_NAME $command |
| | """ |
| |
|
| |
|
| | def evaluate_structure( |
| | name: str, |
| | pred: Path, |
| | reference: Path, |
| | outdir: str, |
| | mount: str, |
| | executable: str = "/bin/bash", |
| | ) -> None: |
| | """Evaluate the structure.""" |
| | |
| | out_path = Path(outdir) / f"{name}.json" |
| |
|
| | if out_path.exists(): |
| | print( |
| | f"Skipping recomputation of {name} as protein json file already exists" |
| | ) |
| | else: |
| | subprocess.run( |
| | OST_COMPARE_STRUCTURE.format( |
| | model_file=str(pred), |
| | reference_file=str(reference), |
| | output_path=str(out_path), |
| | mount=mount, |
| | ), |
| | shell=True, |
| | check=False, |
| | executable=executable, |
| | capture_output=True, |
| | ) |
| |
|
| | |
| | out_path = Path(outdir) / f"{name}_ligand.json" |
| | if out_path.exists(): |
| | print(f"Skipping recomputation of {name} as ligand json file already exists") |
| | else: |
| | subprocess.run( |
| | OST_COMPARE_LIGAND.format( |
| | model_file=str(pred), |
| | reference_file=str(reference), |
| | output_path=str(out_path), |
| | mount=mount, |
| | ), |
| | shell=True, |
| | check=False, |
| | executable=executable, |
| | capture_output=True, |
| | ) |
| |
|
| |
|
| | def main(args): |
| | |
| | files = list(args.data.iterdir()) |
| | names = {f.stem.lower(): f for f in files} |
| |
|
| | |
| | args.outdir.mkdir(parents=True, exist_ok=True) |
| |
|
| | first_item = True |
| | with concurrent.futures.ThreadPoolExecutor(args.max_workers) as executor: |
| | futures = [] |
| | for name, folder in names.items(): |
| | for model_id in range(5): |
| | |
| | if args.format == "af3": |
| | pred_path = folder / f"seed-1_sample-{model_id}" / "model.cif" |
| | elif args.format == "chai": |
| | pred_path = folder / f"pred.model_idx_{model_id}.cif" |
| | elif args.format == "boltz": |
| | name_file = ( |
| | f"{name[0].upper()}{name[1:]}" |
| | if args.testset == "casp" |
| | else name.lower() |
| | ) |
| | pred_path = folder / f"{name_file}_model_{model_id}.cif" |
| |
|
| | if args.testset == "casp": |
| | ref_path = args.pdb / f"{name[0].upper()}{name[1:]}.cif" |
| | elif args.testset == "test": |
| | ref_path = args.pdb / f"{name.lower()}.cif.gz" |
| |
|
| | if first_item: |
| | |
| | |
| | evaluate_structure( |
| | name=f"{name}_model_{model_id}", |
| | pred=str(pred_path), |
| | reference=str(ref_path), |
| | outdir=str(args.outdir), |
| | mount=args.mount, |
| | executable=args.executable, |
| | ) |
| | first_item = False |
| | else: |
| | future = executor.submit( |
| | evaluate_structure, |
| | name=f"{name}_model_{model_id}", |
| | pred=str(pred_path), |
| | reference=str(ref_path), |
| | outdir=str(args.outdir), |
| | mount=args.mount, |
| | executable=args.executable, |
| | ) |
| | futures.append(future) |
| |
|
| | |
| | with tqdm(total=len(futures)) as pbar: |
| | for _ in concurrent.futures.as_completed(futures): |
| | pbar.update(1) |
| |
|
| |
|
| | if __name__ == "__main__": |
| | parser = argparse.ArgumentParser() |
| | parser.add_argument("data", type=Path) |
| | parser.add_argument("pdb", type=Path) |
| | parser.add_argument("outdir", type=Path) |
| | parser.add_argument("--format", type=str, default="af3") |
| | parser.add_argument("--testset", type=str, default="casp") |
| | parser.add_argument("--mount", type=str) |
| | parser.add_argument("--executable", type=str, default="/bin/bash") |
| | parser.add_argument("--max-workers", type=int, default=32) |
| | args = parser.parse_args() |
| | main(args) |
| |
|