| 409 | |
| 410 | |
| 411 | class AAComplex(Protein): # Antibody-Antigen complex |
| 412 | |
| 413 | # threshold = 6.6 # from "Characterization of Protein-Protein Interfaces" |
| 414 | num_interface_residue = 48 # from PNAS, Jian Peng |
| 415 | |
| 416 | def __init__(self, pdb_id: str, peptides: Dict[str, Peptide], heavy_chain: str, |
| 417 | light_chain: str, antigen_chains: List[str], numbering: str='imgt', |
| 418 | cdr_pos: Optional[Dict[str, Tuple]]=None, skip_cal_interface=False): |
| 419 | ''' |
| 420 | heavy_chain: the id of heavy chain |
| 421 | light_chain: the id of light chain |
| 422 | antigen_chains: the list of ids of antigen chains |
| 423 | numbering: currently only support IMGT |
| 424 | self.cdr_pos: dict with keys like CDR-H3 and values like (40, 45) indicating [begin, end] |
| 425 | ''' |
| 426 | self.heavy_chain = heavy_chain |
| 427 | self.light_chain = light_chain |
| 428 | self.antigen_chains = copy(antigen_chains) |
| 429 | |
| 430 | # antibody information |
| 431 | if cdr_pos is None: |
| 432 | selected_peptides, self.cdr_pos = self._extract_antibody_info(peptides, numbering) |
| 433 | else: |
| 434 | selected_peptides, self.cdr_pos = {}, deepcopy(cdr_pos) |
| 435 | for chain_name in [heavy_chain, light_chain]: |
| 436 | if chain_name in peptides: |
| 437 | selected_peptides[chain_name] = peptides[chain_name] |
| 438 | # antigen information |
| 439 | for chain_name in antigen_chains: |
| 440 | assert chain_name not in selected_peptides, f'Antigen chain {chain_name} is antibody itself!' |
| 441 | selected_peptides[chain_name] = peptides[chain_name] |
| 442 | |
| 443 | super().__init__(pdb_id, selected_peptides) |
| 444 | |
| 445 | if not skip_cal_interface: |
| 446 | self._cal_interface() |
| 447 | |
| 448 | def _extract_antibody_info(self, peptides, numbering): |
| 449 | # calculating cdr pos according to number scheme (type_mapping and conserved residues) |
| 450 | if numbering.lower() == 'imgt': |
| 451 | type_mapping = {} # - for non-Fv region, 0 for framework, 1/2/3 for cdr1/2/3 |
| 452 | for i in list(range(1, 27)) + list(range(39, 56)) + list(range(66, 105)) + list(range(118, 130)): |
| 453 | type_mapping[i] = '0' |
| 454 | for i in range(27, 39): # cdr1 |
| 455 | type_mapping[i] = '1' |
| 456 | for i in range(56, 66): # cdr2 |
| 457 | type_mapping[i] = '2' |
| 458 | for i in range(105, 118): # cdr3 |
| 459 | type_mapping[i] = '3' |
| 460 | conserved = { |
| 461 | 23: ['CYS'], |
| 462 | 41: ['TRP'], |
| 463 | 104: ['CYS'], |
| 464 | # 118: ['PHE', 'TRP'] |
| 465 | } |
| 466 | else: |
| 467 | raise NotImplementedError(f'Numbering scheme {numbering} not implemented') |
| 468 |
no outgoing calls
no test coverage detected