| """ |
| Created by Jude Wells 2023-04-20 |
| Objective is to create a secondary structure matrix for each protein |
| 1) renumbers the pdb file (1-indexed) |
| 2) runs stride to get secondary structure file |
| 3) parses the secondary structure file to create a matrix of secondary structure |
| |
| # should take around 3 minutes for 1000 structures |
| """ |
|
|
| import os |
| import re |
| import subprocess |
| import sys |
|
|
| import numpy as np |
|
|
| from model.constants import REPO_ROOT |
| import logging |
| LOG = logging.getLogger(__name__) |
|
|
|
|
| def calculate_ss(pdbfile, chain, stride_path, ssfile='pdb_ss'): |
| assert os.path.exists(pdbfile) |
| with open(ssfile, 'w') as ssout_file: |
| args = [stride_path, pdbfile, '-r' + chain] |
| LOG.info(f"Running command: {' '.join(args)}") |
| try: |
| subprocess.run(args, |
| stdout=ssout_file, |
| stderr=subprocess.DEVNULL, |
| check=True) |
| except subprocess.CalledProcessError as e: |
| LOG.warning(f"Stride failed on {pdbfile}, creating empty file") |
| pass |
|
|
|
|
| def make_ss_matrix(ss_path, nres): |
| |
| with open(ss_path) as f: |
| lines = f.readlines() |
| type_set = set() |
| helix = np.zeros([nres, nres], dtype=np.float32) |
| strand = np.zeros([nres, nres], dtype=np.float32) |
| for line in lines: |
| if line.startswith('LOC'): |
| start = int(re.sub(r'\D', '', line[22:28].strip())) |
| end = int(re.sub(r'\D', '', line[40:46].strip())) |
| type = line[5:17].strip() |
| type_set.add(type) |
| if type in ['AlphaHelix', '310Helix']: |
| helix[start-1:end, start-1:end] = 1 |
| elif type == 'Strand': |
| strand[start-1:end, start-1:end] = 1 |
| elif line.startswith('ASG'): |
| break |
| return helix, strand |
|
|
|
|
| def renum_pdb_file(pdb_path, output_pdb_path): |
| pdb_reres_path = REPO_ROOT / 'model/utils/pdb_reres.py' |
| with open(output_pdb_path, "w") as output_file: |
| subprocess.run([sys.executable, str(pdb_reres_path), pdb_path], |
| stdout=output_file, |
| check=True, |
| text=True) |
| |
|
|
| def main(chain_ids, pdb_dir, feature_dir, stride_path, reres_path, savedir, job_index=0): |
| os.makedirs(savedir, exist_ok=True) |
| os.makedirs(os.path.join(savedir, '2d_features'), exist_ok=True) |
| for chain_id in chain_ids: |
| try: |
| pdb_path = os.path.join(pdb_dir, chain_id + '.pdb') |
| if os.path.exists(pdb_path): |
| features = np.load(os.path.join(feature_dir, chain_id + '.npz'))['arr_0'] |
| nres = features.shape[-1] |
| LOG.info("Processing", pdb_path) |
| chain = chain_id[4] |
| output_pdb_path = os.path.join(savedir, f"{job_index}.pdb") |
| file_nres = renum_pdb_file(pdb_path, reres_path, output_pdb_path) |
| if nres != file_nres: |
| with open(os.path.join(savedir, 'error.txt'), 'a') as f: |
| msg = f' residue number mismatch (from features) {nres}, (from pdb file) {file_nres}' |
| f.write(chain_id + msg + '\n') |
| ss_filepath = os.path.join(savedir, f'pdb_ss{job_index}.txt') |
| calculate_ss(output_pdb_path, chain, stride_path, ssfile=ss_filepath) |
| helix, strand = make_ss_matrix(ss_filepath, nres=nres) |
| np.savez_compressed( |
| os.path.join(*[savedir, '2d_features', chain_id + '.npz']), |
| np.stack((features, helix, strand), axis=0)) |
| except Exception as e: |
| with open(os.path.join(savedir, 'error.txt'), 'a') as f: |
| f.write(chain_id + str(e) + '\n') |
|
|