



'''simple docstring'''






import dataclasses
import re
import string
from typing import Any, Dict, Iterator, List, Mapping, Optional, Sequence, Tuple

import numpy as np

from . import residue_constants


A_							: Optional[int]						 =	Mapping[str, np.ndarray]
A_							: Union[str, Any]						 =	Mapping[str, Any]  # Is a nested dict.
A_							: Any						 =	0.01



@dataclasses.dataclass(frozen=_lowerCamelCase				)
class 							lowercase       :


 """simple docstring"""


 UpperCAmelCase							=  42  # [num_res, num_atom_type, 3]

 # Amino-acid type for each residue represented as an integer between 0 and
 # 20, where 20 is 'X'.
 UpperCAmelCase							=  42  # [num_res]

 # Binary float mask to indicate presence of a particular atom. 1.0 if an atom
 # is present and 0.0 if not. This should be used for loss masking.
 UpperCAmelCase							=  42  # [num_res, num_atom_type]

 # Residue index as used in PDB. It is not necessarily continuous or 0-indexed.
 UpperCAmelCase							=  42  # [num_res]

 # B-factors, or temperature factors, of each residue (in sq. angstroms units),
 # representing the displacement of the residue from its ground truth mean
 # value.
 UpperCAmelCase							=  42  # [num_res, num_atom_type]

 # Chain indices for multi-chain predictions
 UpperCAmelCase							=  None

 # Optional remark about the protein. Included as a comment in output PDB
 # files
 UpperCAmelCase							=  None

 # Templates used to generate this protein (prediction-only)
 UpperCAmelCase							=  None

 # Chain corresponding to each parent
 UpperCAmelCase							=  None







def     snake_case_					(     lowerCAmelCase_		)->		Protein:





       '''simple docstring'''


       _UpperCAmelCase  :						List[Any]			     = R"""(\[[A-Z]+\]\n)"""
       _UpperCAmelCase  :						List[str]			     = [tag.strip() for tag in re.split(lowerCAmelCase_       ,   lowerCAmelCase_		) if len(lowerCAmelCase_		) > 0]
       _UpperCAmelCase  :						Iterator[Tuple[str, List[str]]]			     = zip(tags[0::2]       ,   [l.split("""\n"""		) for l in tags[1::2]]		)

       _UpperCAmelCase  :						List[str]			     = ["N", "CA", "C"]
       _UpperCAmelCase  :						List[Any]			     = None
       _UpperCAmelCase  :						Tuple			     = None
       _UpperCAmelCase  :						Union[str, Any]			     = None
       for g in groups:
              if "[PRIMARY]" == g[0]:
                     _UpperCAmelCase  :						List[str]			     = g[1][0].strip()
                     for i in range(len(lowerCAmelCase_		)		):
                            if seq[i] not in residue_constants.restypes:
                                   _UpperCAmelCase  :						Any			     = """X"""  # FIXME: strings are immutable
                     _UpperCAmelCase  :						List[Any]			     = np.array(
                         [residue_constants.restype_order.get(lowerCAmelCase_       ,   residue_constants.restype_num		) for res_symbol in seq]		)
              elif "[TERTIARY]" == g[0]:
                     _UpperCAmelCase  :						List[List[float]]			     = []
                     for axis in range(3		):
                            tertiary.append(list(map(lowerCAmelCase_       ,   g[1][axis].split()		)		)		)
                     _UpperCAmelCase  :						Tuple			     = np.array(lowerCAmelCase_		)
                     _UpperCAmelCase  :						Optional[Any]			     = np.zeros((len(tertiary[0]		) // 3, residue_constants.atom_type_num, 3)		).astype(np.floataa		)
                     for i, atom in enumerate(lowerCAmelCase_		):
                            _UpperCAmelCase  :						List[str]			     = np.transpose(tertiary_np[:, i::3]		)
                     atom_positions *= PICO_TO_ANGSTROM
              elif "[MASK]" == g[0]:
                     _UpperCAmelCase  :						List[str]			     = np.array(list(map({"""-""": 0, """+""": 1}.get       ,   g[1][0].strip()		)		)		)
                     _UpperCAmelCase  :						str			     = np.zeros(
                         (
                             len(lowerCAmelCase_		),
                             residue_constants.atom_type_num,
                         )		).astype(np.floataa		)
                     for i, atom in enumerate(lowerCAmelCase_		):
                            _UpperCAmelCase  :						Any			     = 1
                     atom_mask *= mask[..., None]

       assert aatype is not None

       return Protein(
           atom_positions=lowerCAmelCase_       ,   atom_mask=lowerCAmelCase_       ,   aatype=lowerCAmelCase_       ,   residue_index=np.arange(len(lowerCAmelCase_		)		)       ,   b_factors=lowerCAmelCase_       ,   )




def     snake_case_					(     lowerCAmelCase_       ,   lowerCAmelCase_ = 0		)->		List[str]:





       '''simple docstring'''


       _UpperCAmelCase  :						List[str]			     = []

       _UpperCAmelCase  :						int			     = prot.remark
       if remark is not None:
              pdb_headers.append(F'''REMARK {remark}'''		)

       _UpperCAmelCase  :						Tuple			     = prot.parents
       _UpperCAmelCase  :						str			     = prot.parents_chain_index
       if parents is not None and parents_chain_index is not None:
              _UpperCAmelCase  :						Tuple			     = [p for i, p in zip(lowerCAmelCase_       ,   lowerCAmelCase_		) if i == chain_id]

       if parents is None or len(lowerCAmelCase_		) == 0:
              _UpperCAmelCase  :						Optional[Any]			     = ["""N/A"""]

       pdb_headers.append(F'''PARENT {' '.join(lowerCAmelCase_		)}'''		)

       return pdb_headers




def     snake_case_					(     lowerCAmelCase_       ,   lowerCAmelCase_		)->		str:





       '''simple docstring'''


       _UpperCAmelCase  :						List[str]			     = []
       _UpperCAmelCase  :						List[Any]			     = pdb_str.split("""\n"""		)

       _UpperCAmelCase  :						Optional[Any]			     = prot.remark
       if remark is not None:
              out_pdb_lines.append(F'''REMARK {remark}'''		)

       _UpperCAmelCase  :						List[List[str]]
       if prot.parents is not None and len(prot.parents		) > 0:
              _UpperCAmelCase  :						List[str]			     = []
              if prot.parents_chain_index is not None:
                     _UpperCAmelCase  :						Dict[str, List[str]]			     = {}
                     for p, i in zip(prot.parents       ,   prot.parents_chain_index		):
                            parent_dict.setdefault(str(lowerCAmelCase_		)       ,   []		)
                            parent_dict[str(lowerCAmelCase_		)].append(lowerCAmelCase_		)

                     _UpperCAmelCase  :						List[Any]			     = max([int(lowerCAmelCase_		) for chain_idx in parent_dict]		)
                     for i in range(max_idx + 1		):
                            _UpperCAmelCase  :						Optional[Any]			     = parent_dict.get(str(lowerCAmelCase_		)       ,   ["""N/A"""]		)
                            parents_per_chain.append(lowerCAmelCase_		)
              else:
                     parents_per_chain.append(list(prot.parents		)		)
       else:
              _UpperCAmelCase  :						Union[str, Any]			     = [["""N/A"""]]

       def make_parent_line(lowerCAmelCase_		) -> str:
              return F'''PARENT {' '.join(lowerCAmelCase_		)}'''

       out_pdb_lines.append(make_parent_line(parents_per_chain[0]		)		)

       _UpperCAmelCase  :						int			     = 0
       for i, l in enumerate(lowerCAmelCase_		):
              if "PARENT" not in l and "REMARK" not in l:
                     out_pdb_lines.append(lowerCAmelCase_		)
              if "TER" in l and "END" not in lines[i + 1]:
                     chain_counter += 1
                     if not chain_counter >= len(lowerCAmelCase_		):
                            _UpperCAmelCase  :						Union[str, Any]			     = parents_per_chain[chain_counter]
                     else:
                            _UpperCAmelCase  :						Dict			     = ["""N/A"""]

                     out_pdb_lines.append(make_parent_line(lowerCAmelCase_		)		)

       return "\n".join(lowerCAmelCase_		)




def     snake_case_					(     lowerCAmelCase_		)->		str:





       '''simple docstring'''


       _UpperCAmelCase  :						Optional[Any]			     = residue_constants.restypes + ["""X"""]

       def res_atoa(lowerCAmelCase_		) -> str:
              return residue_constants.restype_atoa.get(restypes[r]       ,   """UNK"""		)

       _UpperCAmelCase  :						Optional[int]			     = residue_constants.atom_types

       _UpperCAmelCase  :						List[str]			     = []

       _UpperCAmelCase  :						Any			     = prot.atom_mask
       _UpperCAmelCase  :						Tuple			     = prot.aatype
       _UpperCAmelCase  :						Any			     = prot.atom_positions
       _UpperCAmelCase  :						Optional[Any]			     = prot.residue_index.astype(np.intaa		)
       _UpperCAmelCase  :						Optional[int]			     = prot.b_factors
       _UpperCAmelCase  :						Optional[int]			     = prot.chain_index

       if np.any(aatype > residue_constants.restype_num		):
              raise ValueError("""Invalid aatypes."""		)

       _UpperCAmelCase  :						Any			     = get_pdb_headers(lowerCAmelCase_		)
       if len(lowerCAmelCase_		) > 0:
              pdb_lines.extend(lowerCAmelCase_		)

       _UpperCAmelCase  :						Any			     = aatype.shape[0]
       _UpperCAmelCase  :						str			     = 1
       _UpperCAmelCase  :						Optional[int]			     = 0
       _UpperCAmelCase  :						List[Any]			     = string.ascii_uppercase
       _UpperCAmelCase  :						List[Any]			     = None
       # Add all atom sites.
       for i in range(lowerCAmelCase_		):
              _UpperCAmelCase  :						List[str]			     = res_atoa(aatype[i]		)
              for atom_name, pos, mask, b_factor in zip(lowerCAmelCase_       ,   atom_positions[i]       ,   atom_mask[i]       ,   b_factors[i]		):
                     if mask < 0.5:
                            continue

                     _UpperCAmelCase  :						str			     = """ATOM"""
                     _UpperCAmelCase  :						Any			     = atom_name if len(lowerCAmelCase_		) == 4 else F''' {atom_name}'''
                     _UpperCAmelCase  :						Dict			     = """"""
                     _UpperCAmelCase  :						Union[str, Any]			     = """"""
                     _UpperCAmelCase  :						Tuple			     = 1.0_0
                     _UpperCAmelCase  :						Dict			     = atom_name[0]  # Protein supports only C, N, O, S, this works.
                     _UpperCAmelCase  :						Optional[Any]			     = """"""

                     _UpperCAmelCase  :						List[str]			     = """A"""
                     if chain_index is not None:
                            _UpperCAmelCase  :						List[Any]			     = chain_tags[chain_index[i]]

                     # PDB is a columnar format, every space matters here!
                     _UpperCAmelCase  :						Tuple			     = (
                         F'''{record_type:<6}{atom_index:>5} {name:<4}{alt_loc:>1}'''
                         F'''{res_name_a:>3} {chain_tag:>1}'''
                         F'''{residue_index[i]:>4}{insertion_code:>1}   '''
                         F'''{pos[0]:>8.3f}{pos[1]:>8.3f}{pos[2]:>8.3f}'''
                         F'''{occupancy:>6.2f}{b_factor:>6.2f}          '''
                         F'''{element:>2}{charge:>2}'''
                     )
                     pdb_lines.append(lowerCAmelCase_		)
                     atom_index += 1

              _UpperCAmelCase  :						int			     = i == n - 1
              if chain_index is not None:
                     if i != n - 1 and chain_index[i + 1] != prev_chain_index:
                            _UpperCAmelCase  :						Optional[int]			     = True
                            _UpperCAmelCase  :						str			     = chain_index[i + 1]

              if should_terminate:
                     # Close the chain.
                     _UpperCAmelCase  :						Tuple			     = """TER"""
                     _UpperCAmelCase  :						List[str]			     = (
                         F'''{chain_end:<6}{atom_index:>5}      {res_atoa(aatype[i]		):>3} {chain_tag:>1}{residue_index[i]:>4}'''
                     )
                     pdb_lines.append(lowerCAmelCase_		)
                     atom_index += 1

                     if i != n - 1:
                            # "prev" is a misnomer here. This happens at the beginning of
                            # each new chain.
                            pdb_lines.extend(get_pdb_headers(lowerCAmelCase_       ,   lowerCAmelCase_		)		)

       pdb_lines.append("""END"""		)
       pdb_lines.append(""""""		)
       return "\n".join(lowerCAmelCase_		)




def     snake_case_					(     lowerCAmelCase_		)->		np.ndarray:





       '''simple docstring'''


       return residue_constants.STANDARD_ATOM_MASK[prot.aatype]




def     snake_case_					(     lowerCAmelCase_       ,   lowerCAmelCase_       ,   lowerCAmelCase_ = None       ,   lowerCAmelCase_ = None       ,   lowerCAmelCase_ = None       ,   lowerCAmelCase_ = None       ,   lowerCAmelCase_ = None       ,   )->		Protein:





       '''simple docstring'''


       return Protein(
           aatype=features["""aatype"""]       ,   atom_positions=result["""final_atom_positions"""]       ,   atom_mask=result["""final_atom_mask"""]       ,   residue_index=features["""residue_index"""] + 1       ,   b_factors=b_factors if b_factors is not None else np.zeros_like(result["""final_atom_mask"""]		)       ,   chain_index=lowerCAmelCase_       ,   remark=lowerCAmelCase_       ,   parents=lowerCAmelCase_       ,   parents_chain_index=lowerCAmelCase_       ,   )








'''simple docstring'''






from numpy import exp, pi, sqrt




def     snake_case_					(     lowerCAmelCase_       ,   lowerCAmelCase_ = 0.0       ,   lowerCAmelCase_ = 1.0		)->		int:





       '''simple docstring'''


       return 1 / sqrt(2 * pi * sigma**2		) * exp(-((x - mu) ** 2) / (2 * sigma**2)		)


if __name__ == "__main__":
   import doctest

   doctest.testmod()



