CombFold / scripts /automatic_pipeline /libs /parse_alphafold_jobs.py
wuxing0105's picture
Upload folder using huggingface_hub
8efb4bd verified
Raw
History Blame Contribute Delete
8.14 kB
import pickle
from functools import lru_cache
import os
from typing import Dict, List
import numpy as np
from automatic_pipeline.configurable import get_scores_from_path
from automatic_pipeline.libs.get_alphafold_jobs import get_residue_diff
from automatic_pipeline.libs.utils_classes import PdbPath, AlphaFoldJobInfo, AFResultScoredPair, SubunitsInfo, \
SubunitPdbInfo, AFSubunitScores, AFInteractionScores
from automatic_pipeline.libs.utils_pdb import get_pdb_model_readonly, are_subunits_close_in_pdb, get_interface_res_ids
try:
import ujson as json
except ModuleNotFoundError:
print("using slow json!")
import json
@lru_cache(5)
def get_alphafold_scores(pdb_path: str):
return json.load(open(get_scores_from_path(pdb_path), "r"))
def parse_results_to_scored_pairs(alphafold_results: Dict[AlphaFoldJobInfo, List[PdbPath]],
subunits_info: SubunitsInfo) -> List[AFResultScoredPair]:
all_pairs = []
for job_count, (af_job_info, pdb_paths) in enumerate(alphafold_results.items()):
if job_count % 5 == 0:
print("finding pairs", job_count, "out of", len(alphafold_results), "found", len(all_pairs))
for pdb_path in pdb_paths:
pdb_model = get_pdb_model_readonly(pdb_path)
chain_names = sorted([c.id for c in pdb_model.get_chains()])
subunits_per_chain = [[af_job_info.subunit_names[0]]]
for subunit_name, should_merge in zip(af_job_info.subunit_names[1:], af_job_info.merged_subunits):
if should_merge:
subunits_per_chain[-1].append(subunit_name)
else:
subunits_per_chain.append([subunit_name])
assert len(chain_names) == len(subunits_per_chain), f"Mismatch subunits and chains lengths " \
f"{len(chain_names)} {len(subunits_per_chain)}"
subunits_pdb_infos = []
pdb_start_res = 0
for chain_name, subunit_list in zip(chain_names, subunits_per_chain):
chain_start_res = 1
for subunit_i in range(len(subunit_list)):
subunit_name = subunit_list[subunit_i]
subunit = subunits_info[subunit_name]
if subunit_i > 0:
prev_subunit = subunits_info[subunit_list[subunit_i - 1]]
chain_start_res += get_residue_diff(prev_subunit, subunit)
subunits_pdb_infos.append(SubunitPdbInfo(chain_id=chain_name, chain_residue_id=chain_start_res,
pdb_residue_id=pdb_start_res,
length=len(subunit.sequence)))
chain_start_res += len(subunit.sequence)
pdb_start_res += len(subunit.sequence)
for i in range(len(subunits_pdb_infos)):
for j in range(i + 1, len(subunits_pdb_infos)):
if are_subunits_close_in_pdb(pdb_path, subunits_pdb_infos[i], subunits_pdb_infos[j]):
all_pairs.append(AFResultScoredPair(pdb_path=pdb_path,
subunits_names=(af_job_info.subunit_names[i],
af_job_info.subunit_names[j]),
subunit1_pdb_info=subunits_pdb_infos[i],
subunit2_pdb_info=subunits_pdb_infos[j]))
return all_pairs
def _get_subunit_scores(plddt: np.ndarray, pae: np.ndarray, subunit_indexes: List[int], interface_indexes: List[int]) \
-> AFSubunitScores:
subunit_plddt = plddt[subunit_indexes]
return AFSubunitScores(
plddt_avg=float(np.mean(subunit_plddt)),
plddt_percentile=list(np.percentile(subunit_plddt, np.arange(0, 101, 10))),
plddt_interface_avg=float(np.mean(plddt[interface_indexes])),
plddt_interface_percentile=list(np.percentile(plddt[interface_indexes], np.arange(0, 101, 10))),
self_pae_avg=float(np.mean(pae[subunit_indexes][:, subunit_indexes])),
self_pae_percentile=list(np.percentile(pae[subunit_indexes][:, subunit_indexes], np.arange(0, 101, 10)))
)
def _get_interaction_scores(pae: np.ndarray, subunit_indexes1: List[int], subunit_indexes2: List[int],
interface_indexes1: List[int], interface_indexes2: List[int]) -> AFInteractionScores:
all_pae = np.concatenate([pae[subunit_indexes1][:, subunit_indexes2].flatten(),
pae[subunit_indexes2][:, subunit_indexes1].flatten()])
pae_joined_interface = np.concatenate([pae[interface_indexes1][:, interface_indexes2].flatten(),
pae[interface_indexes2][:, interface_indexes1].flatten()])
return AFInteractionScores(
pae_avg=float(np.mean(all_pae)),
pae_percentile=list(np.percentile(all_pae, np.arange(0, 101, 10))),
pae_joined_interface_avg=float(np.mean(pae_joined_interface)),
pae_joined_interface_percentile=list(np.percentile(pae_joined_interface, np.arange(0, 101, 10))),
interface1_size=len(interface_indexes1),
interface2_size=len(interface_indexes2),
)
def score_af_results_as_pairs(alphafold_results: Dict[AlphaFoldJobInfo, List[PdbPath]],
output_path: str, subunits_info: SubunitsInfo) -> List[AFResultScoredPair]:
if os.path.exists(output_path):
with open(output_path, "rb") as f:
all_pairs = pickle.load(f)
else:
all_pairs = parse_results_to_scored_pairs(alphafold_results, subunits_info)
pickle.dump(all_pairs, open(output_path, "wb"))
not_scored_results: List[AFResultScoredPair] = [i for i in all_pairs if i.subunit1_scores is None]
# enrich with scores
for count, pair in enumerate(not_scored_results):
# pdb_info = AlphaFoldJobInfo.from_result_path(pair.pdb_path)
job_scores = get_alphafold_scores(pair.pdb_path)
plddt = np.array(job_scores["plddt"])
pae = np.array(job_scores["pae"])
# index are 0-based
subunit1_indexes = [i for i in range(pair.subunit1_pdb_info.length)
if subunits_info[pair.subunits_names[0]].sequence[i] != "X"]
subunit1_indexes = np.array(subunit1_indexes) + pair.subunit1_pdb_info.pdb_residue_id
subunit2_indexes = [i for i in range(pair.subunit2_pdb_info.length)
if subunits_info[pair.subunits_names[1]].sequence[i] != "X"]
subunit2_indexes = np.array(subunit2_indexes) + pair.subunit2_pdb_info.pdb_residue_id
subunit1_interface, subunit2_interface = get_interface_res_ids(pair.pdb_path,
pair.subunit1_pdb_info,
pair.subunit2_pdb_info)
subunit1_interface_indexes = np.array(list(subunit1_interface)) + pair.subunit1_pdb_info.pdb_residue_id
subunit2_interface_indexes = np.array(list(subunit2_interface)) + pair.subunit2_pdb_info.pdb_residue_id
pair.subunit1_scores = _get_subunit_scores(plddt, pae, subunit1_indexes, subunit1_interface_indexes)
pair.subunit2_scores = _get_subunit_scores(plddt, pae, subunit2_indexes, subunit2_interface_indexes)
pair.interaction_scores = _get_interaction_scores(pae, subunit1_indexes, subunit2_indexes,
subunit1_interface_indexes, subunit2_interface_indexes)
if count % 100 == 0 or count == len(not_scored_results) - 1:
print(f"Processed {count + 1}/{len(not_scored_results)} total pairs: {len(all_pairs)}")
pickle.dump(all_pairs, open(output_path, "wb"))
return all_pairs