Spaces:
Runtime error
Runtime error
| import argparse | |
| import abnumber | |
| from Bio import PDB | |
| from Bio.PDB import Model, Chain, Residue, Selection | |
| from Bio.Data import SCOPData | |
| from typing import List, Tuple | |
| def biopython_chain_to_sequence(chain: Chain.Chain): | |
| residue_list = Selection.unfold_entities(chain, 'R') | |
| seq = ''.join([SCOPData.protein_letters_3to1.get(r.resname, 'X') for r in residue_list]) | |
| return seq, residue_list | |
| def assign_number_to_sequence(seq): | |
| abchain = abnumber.Chain(seq, scheme='chothia') | |
| offset = seq.index(abchain.seq) | |
| if not (offset >= 0): | |
| raise ValueError( | |
| 'The identified Fv sequence is not a subsequence of the original sequence.' | |
| ) | |
| numbers = [None for _ in range(len(seq))] | |
| for i, (pos, aa) in enumerate(abchain): | |
| resseq = pos.number | |
| icode = pos.letter if pos.letter else ' ' | |
| numbers[i+offset] = (resseq, icode) | |
| return numbers, abchain | |
| def renumber_biopython_chain(chain_id, residue_list: List[Residue.Residue], numbers: List[Tuple[int, str]]): | |
| chain = Chain.Chain(chain_id) | |
| for residue, number in zip(residue_list, numbers): | |
| if number is None: | |
| continue | |
| residue = residue.copy() | |
| new_id = (residue.id[0], number[0], number[1]) | |
| residue.id = new_id | |
| chain.add(residue) | |
| return chain | |
| def renumber(in_pdb, out_pdb, return_other_chains=False): | |
| parser = PDB.PDBParser(QUIET=True) | |
| structure = parser.get_structure(None, in_pdb) | |
| model = structure[0] | |
| model_new = Model.Model(0) | |
| heavy_chains, light_chains, other_chains = [], [], [] | |
| for chain in model: | |
| try: | |
| seq, reslist = biopython_chain_to_sequence(chain) | |
| numbers, abchain = assign_number_to_sequence(seq) | |
| chain_new = renumber_biopython_chain(chain.id, reslist, numbers) | |
| print(f'[INFO] Renumbered chain {chain_new.id} ({abchain.chain_type})') | |
| if abchain.chain_type == 'H': | |
| heavy_chains.append(chain_new.id) | |
| elif abchain.chain_type in ('K', 'L'): | |
| light_chains.append(chain_new.id) | |
| except abnumber.ChainParseError as e: | |
| print(f'[INFO] Chain {chain.id} does not contain valid Fv: {str(e)}') | |
| chain_new = chain.copy() | |
| other_chains.append(chain_new.id) | |
| model_new.add(chain_new) | |
| pdb_io = PDB.PDBIO() | |
| pdb_io.set_structure(model_new) | |
| pdb_io.save(out_pdb) | |
| if return_other_chains: | |
| return heavy_chains, light_chains, other_chains | |
| else: | |
| return heavy_chains, light_chains | |
| def main(): | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument('in_pdb', type=str) | |
| parser.add_argument('out_pdb', type=str) | |
| args = parser.parse_args() | |
| renumber(args.in_pdb, args.out_pdb) | |
| if __name__ == '__main__': | |
| main() | |