"""Run IgFold structure prediction from antibody sequences or a FASTA file.""" import argparse import json from pathlib import Path import torch from igfold import IgFoldRunner DEFAULT_HEAVY = ( "EVQLVQSGPEVKKPGTSVKVSCKASGFTFMSSAVQWVRQARGQRLEWIGWIVIGSGNTNYAQKF" "QERVTITRDMSTSTAYMELSSLRSEDTAVYYCAAPYCSSISCNDGFDIWGQGTMVTVS" ) DEFAULT_LIGHT = ( "DVVMTQTPFSLPVSLGDQASISCRSSQSLVHSNGNTYLHWYLQKPGQSPKLLIYKVSNRFSGV" "PDRFSGSGSGTDFTLKISRVEAEDLGVYFCSQSTHVPYTFGGGTKLEIK" ) def parse_args(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--fasta", type=Path, help="Input FASTA containing H/L chains.") parser.add_argument("--heavy", help="Heavy-chain amino-acid sequence.") parser.add_argument("--light", help="Light-chain amino-acid sequence.") parser.add_argument("--output", type=Path, default=Path("output/inference/antibody.pdb")) parser.add_argument("--num-models", type=int, choices=range(1, 5), default=4) parser.add_argument("--refine", action="store_true", help="Enable structure refinement.") parser.add_argument("--openmm", action="store_true", help="Use OpenMM for refinement.") parser.add_argument("--renum", action="store_true", help="Apply Chothia numbering.") parser.add_argument("--cpu", action="store_true", help="Force CPU inference.") return parser.parse_args() def main(): args = parse_args() root = Path(__file__).resolve().parents[1] checkpoints = sorted((root / "weight" / "IgFold").glob("*.ckpt"))[: args.num_models] if len(checkpoints) != args.num_models: raise FileNotFoundError( f"Expected {args.num_models} checkpoints in {root / 'weight' / 'IgFold'}, " f"found {len(checkpoints)}." ) if args.fasta is not None: fasta_file = str(args.fasta.resolve()) sequences = None else: fasta_file = None sequences = {"H": args.heavy or DEFAULT_HEAVY} light = args.light if args.light is not None else DEFAULT_LIGHT if light: sequences["L"] = light if args.refine and not args.openmm: from igfold.refine.pyrosetta_ref import init_pyrosetta init_pyrosetta() args.output.parent.mkdir(parents=True, exist_ok=True) runner = IgFoldRunner( model_ckpts=[str(path) for path in checkpoints], try_gpu=not args.cpu, ) output = runner.fold( str(args.output), fasta_file=fasta_file, sequences=sequences, do_refine=args.refine, use_openmm=args.openmm, do_renum=args.renum, ) result = { "status": "PASS", "output_pdb": str(args.output.resolve()), "models": len(runner.models), "device": str(next(runner.models[0].parameters()).device), "torch": torch.__version__, "coords_shape": list(output.coords.shape), "prmsd_shape": list(output.prmsd.shape), } print("IGFOLD_INFERENCE_RESULT=" + json.dumps(result, sort_keys=True)) if __name__ == "__main__": main()