





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__      :     List[str]         =		Mapping[str, np.ndarray]
a__      :     Optional[Any]         =		Mapping[str, Any]  # Is a nested dict.
a__      :     Any         =		0.01





@dataclasses.dataclass(frozen=_SCREAMING_SNAKE_CASE )
class UpperCAmelCase_				:
  __lowerCAmelCase   :						np.ndarray  # [num_res, num_atom_type, 3]

  # Amino-acid type for each residue represented as an integer between 0 and
  # 20, where 20 is 'X'.
  __lowerCAmelCase   :						np.ndarray  # [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.
  __lowerCAmelCase   :						np.ndarray  # [num_res, num_atom_type]

  # Residue index as used in PDB. It is not necessarily continuous or 0-indexed.
  __lowerCAmelCase   :						np.ndarray  # [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.
  __lowerCAmelCase   :						np.ndarray  # [num_res, num_atom_type]

  # Chain indices for multi-chain predictions
  __lowerCAmelCase   :						Optional[np.ndarray]							=   None

  # Optional remark about the protein. Included as a comment in output PDB
  # files
  __lowerCAmelCase   :						Optional[str]							=   None

  # Templates used to generate this protein (prediction-only)
  __lowerCAmelCase   :						Optional[Sequence[str]]							=   None

  # Chain corresponding to each parent
  __lowerCAmelCase   :						Optional[Sequence[int]]							=   None




def      UpperCAmelCase_    (    _UpperCAmelCase							:str				)	->				Protein:
     '''simple docstring'''


     A_          =       R'''(\[[A-Z]+\]\n)'''
     A_          =       [tag.strip() for tag in re.split(_UpperCAmelCase  ,						_UpperCAmelCase				) if len(_UpperCAmelCase				) > 0]
     A_          =       zip(tags[0::2]  ,						[l.split('''\n'''				) for l in tags[1::2]]				)

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

     assert aatype is not None

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

def      UpperCAmelCase_    (    _UpperCAmelCase							:Protein  ,						_UpperCAmelCase							:int = 0				)	->				List[str]:
     '''simple docstring'''


     A_          =       []

     A_          =       prot.remark
     if remark is not None:
          pdb_headers.append(f'REMARK {remark}'				)

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

     if parents is None or len(_UpperCAmelCase				) == 0:
          A_          =       ['''N/A''']

     pdb_headers.append(f'PARENT {" ".join(_UpperCAmelCase				)}'				)

     return pdb_headers

def      UpperCAmelCase_    (    _UpperCAmelCase							:Protein  ,						_UpperCAmelCase							:str				)	->				str:
     '''simple docstring'''


     A_          =       []
     A_          =       pdb_str.split('''\n'''				)

     A_          =       prot.remark
     if remark is not None:
          out_pdb_lines.append(f'REMARK {remark}'				)

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

               A_          =       max([int(_UpperCAmelCase				) for chain_idx in parent_dict]				)
               for i in range(max_idx + 1				):
                    A_          =       parent_dict.get(str(_UpperCAmelCase				)  ,						['''N/A''']				)
                    parents_per_chain.append(_UpperCAmelCase				)
          else:
               parents_per_chain.append(list(prot.parents				)				)
     else:
          A_          =       [['''N/A''']]

     def make_parent_line(_UpperCAmelCase							:Sequence[str]				) -> str:
          return f'PARENT {" ".join(_UpperCAmelCase				)}'

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

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

               out_pdb_lines.append(make_parent_line(_UpperCAmelCase				)				)

     return "\n".join(_UpperCAmelCase				)

def      UpperCAmelCase_    (    _UpperCAmelCase							:Protein				)	->				str:
     '''simple docstring'''


     A_          =       residue_constants.restypes + ['''X''']

     def res_atoa(_UpperCAmelCase							:int				) -> str:
          return residue_constants.restype_atoa.get(restypes[r]  ,						'''UNK'''				)

     A_          =       residue_constants.atom_types

     A_          =       []

     A_          =       prot.atom_mask
     A_          =       prot.aatype
     A_          =       prot.atom_positions
     A_          =       prot.residue_index.astype(np.intaa				)
     A_          =       prot.b_factors
     A_          =       prot.chain_index

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

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

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

               A_          =       '''ATOM'''
               A_          =       atom_name if len(_UpperCAmelCase				) == 4 else f' {atom_name}'
               A_          =       ''''''
               A_          =       ''''''
               A_          =       1.00
               A_          =       atom_name[0]  # Protein supports only C, N, O, S, this works.
               A_          =       ''''''

               A_          =       '''A'''
               if chain_index is not None:
                    A_          =       chain_tags[chain_index[i]]

               # PDB is a columnar format, every space matters here!
               A_          =       (
                   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(_UpperCAmelCase				)
               atom_index += 1

          A_          =       i == n - 1
          if chain_index is not None:
               if i != n - 1 and chain_index[i + 1] != prev_chain_index:
                    A_          =       True
                    A_          =       chain_index[i + 1]

          if should_terminate:
               # Close the chain.
               A_          =       '''TER'''
               A_          =       (
                   f'{chain_end:<6}{atom_index:>5}      {res_atoa(aatype[i]				):>3} {chain_tag:>1}{residue_index[i]:>4}'
               )
               pdb_lines.append(_UpperCAmelCase				)
               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(_UpperCAmelCase  ,						_UpperCAmelCase				)				)

     pdb_lines.append('''END'''				)
     pdb_lines.append(''''''				)
     return "\n".join(_UpperCAmelCase				)

def      UpperCAmelCase_    (    _UpperCAmelCase							:Protein				)	->				np.ndarray:
     '''simple docstring'''


     return residue_constants.STANDARD_ATOM_MASK[prot.aatype]


def      UpperCAmelCase_    (    _UpperCAmelCase							:FeatureDict  ,						_UpperCAmelCase							:ModelOutput  ,						_UpperCAmelCase							:Optional[np.ndarray] = None  ,						_UpperCAmelCase							:Optional[np.ndarray] = None  ,						_UpperCAmelCase							:Optional[str] = None  ,						_UpperCAmelCase							:Optional[Sequence[str]] = None  ,						_UpperCAmelCase							:Optional[Sequence[int]] = 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=_UpperCAmelCase  ,						remark=_UpperCAmelCase  ,						parents=_UpperCAmelCase  ,						parents_chain_index=_UpperCAmelCase  ,						)










import enum
import shutil
import sys


a__   ,				a__      :     int         =		shutil.get_terminal_size()

a__      :     Tuple         =		{'UP': 'A', 'DOWN': 'B', 'RIGHT': 'C', 'LEFT': 'D'}





class UpperCAmelCase_				( enum.Enum ):
  __lowerCAmelCase   :						int							=   0
  __lowerCAmelCase   :						Optional[int]							=   1




def      UpperCAmelCase_    (    _UpperCAmelCase							:Optional[int]  ,						_UpperCAmelCase							:int=""				)	->				str:
     '''simple docstring'''


     sys.stdout.write(str(_UpperCAmelCase				) + end				)
     sys.stdout.flush()

def      UpperCAmelCase_    (    _UpperCAmelCase							:Union[str, Any]  ,						_UpperCAmelCase							:Tuple  ,						_UpperCAmelCase							:Tuple=""				)	->				List[Any]:
     '''simple docstring'''


     forceWrite(f'\u001b[{color}m{content}\u001b[0m'  ,						_UpperCAmelCase				)

def      UpperCAmelCase_    (    )	->				Dict:
     '''simple docstring'''


     forceWrite('''\r'''				)

def      UpperCAmelCase_    (    _UpperCAmelCase							:int  ,						_UpperCAmelCase							:str				)	->				List[Any]:
     '''simple docstring'''


     forceWrite(f'\033[{num_lines}{CURSOR_TO_CHAR[direction.upper()]}'				)

def      UpperCAmelCase_    (    )	->				List[Any]:
     '''simple docstring'''


     forceWrite(''' ''' * TERMINAL_WIDTH				)
     reset_cursor()


def      UpperCAmelCase_    (    )	->				Tuple:
     '''simple docstring'''


     reset_cursor()
     forceWrite('''-''' * TERMINAL_WIDTH				)



