





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


snake_case__					:							List[Any]													=     Mapping[str, np.ndarray]
snake_case__					:							List[str]													=     Mapping[str, Any]  # Is a nested dict.
snake_case__					:							Tuple													=     0.01





@dataclasses.dataclass(frozen=_lowerCamelCase   )
class A_					:
   lowerCAmelCase__        = 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'.
   lowerCAmelCase__        = 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.
   lowerCAmelCase__        = 42  # [num_res, num_atom_type]

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

   # Chain indices for multi-chain predictions
   lowerCAmelCase__        = None

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

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

   # Chain corresponding to each parent
   lowerCAmelCase__        = None





def _a				(	lowerCamelCase:   str )	->						Tuple:







      '''simple docstring'''






      __A          =				r"(\[[A-Z]+\]\n)"
      __A          =				[tag.strip() for tag in re.split(_lowerCamelCase					,				_lowerCamelCase ) if len(_lowerCamelCase ) > 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(_lowerCamelCase ) ):
                        if seq[i] not in residue_constants.restypes:
                              __A          =				"X"  # FIXME: strings are immutable
                  __A          =				np.array(
                      [residue_constants.restype_order.get(_lowerCamelCase					,				residue_constants.restype_num ) for res_symbol in seq] )
            elif "[TERTIARY]" == g[0]:
                  __A          =				[]
                  for axis in range(3 ):
                        tertiary.append(list(map(_lowerCamelCase					,				g[1][axis].split() ) ) )
                  __A          =				np.array(_lowerCamelCase )
                  __A          =				np.zeros((len(tertiary[0] ) // 3, residue_constants.atom_type_num, 3) ).astype(np.floataa )
                  for i, atom in enumerate(_lowerCamelCase ):
                        __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(_lowerCamelCase ),
                          residue_constants.atom_type_num,
                      ) ).astype(np.floataa )
                  for i, atom in enumerate(_lowerCamelCase ):
                        __A          =				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 _a				(	lowerCamelCase:   Tuple					,				lowerCamelCase:   Dict = 0 )	->						Optional[int]:







      '''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(_lowerCamelCase					,				_lowerCamelCase ) if i == chain_id]

      if parents is None or len(_lowerCamelCase ) == 0:
            __A          =				["N/A"]

      pdb_headers.append(F"""PARENT {' '.join(_lowerCamelCase )}""" )

      return pdb_headers



def _a				(	lowerCamelCase:   int					,				lowerCamelCase:   int )	->						Any:







      '''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(_lowerCamelCase )					,				[] )
                        parent_dict[str(_lowerCamelCase )].append(_lowerCamelCase )

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

      def make_parent_line(lowerCamelCase:   Any ) -> str:
            return F"""PARENT {' '.join(_lowerCamelCase )}"""

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

      __A          =				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 ):
                        __A          =				parents_per_chain[chain_counter]
                  else:
                        __A          =				["N/A"]

                  out_pdb_lines.append(make_parent_line(_lowerCamelCase ) )

      return "\n".join(_lowerCamelCase )



def _a				(	lowerCamelCase:   Union[str, Any] )	->						Dict:







      '''simple docstring'''






      __A          =				residue_constants.restypes + ["X"]

      def res_atoa(lowerCamelCase:   str ) -> 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(_lowerCamelCase )
      if len(_lowerCamelCase ) > 0:
            pdb_lines.extend(_lowerCamelCase )

      __A          =				aatype.shape[0]
      __A          =				1
      __A          =				0
      __A          =				string.ascii_uppercase
      __A          =				None
      # Add all atom sites.
      for i in range(_lowerCamelCase ):
            __A          =				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

                  __A          =				"ATOM"
                  __A          =				atom_name if len(_lowerCamelCase ) == 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(_lowerCamelCase )
                  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(_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 _a				(	lowerCamelCase:   int )	->						Optional[Any]:







      '''simple docstring'''






      return residue_constants.STANDARD_ATOM_MASK[prot.aatype]







def _a				(	lowerCamelCase:   Dict					,				lowerCamelCase:   Tuple					,				lowerCamelCase:   int = None					,				lowerCamelCase:   Optional[Any] = None					,				lowerCamelCase:   Dict = None					,				lowerCamelCase:   Optional[Any] = None					,				lowerCamelCase:   int = None					,				)	->						List[Any]:







      '''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					,				)










import importlib.metadata
import operator
import re
import sys
from typing import Optional

from packaging import version


_snake_case		=  {
    "<": operator.lt,
    "<=": operator.le,
    "==": operator.eq,
    "!=": operator.ne,
    ">=": operator.ge,
    ">": operator.gt,
}






def 				A				(					_lowerCamelCase				, _lowerCamelCase				, _lowerCamelCase				, _lowerCamelCase				, _lowerCamelCase				, _lowerCamelCase  ):





							'''simple docstring'''




							if got_ver is None or want_ver is None:
														raise ValueError(
														    F"Unable to compare versions for {requirement}: need={want_ver} found={got_ver}. This is unusual. Consider"
														    F" reinstalling {pkg}."  )
							if not ops[op](version.parse(_lowerCamelCase  )				, version.parse(_lowerCamelCase  )  ):
														raise ImportError(
														    F"{requirement} is required for a normal functioning of this module, but found {pkg}=={got_ver}.{hint}"  )






def 				A				(					_lowerCamelCase				, _lowerCamelCase = None  ):





							'''simple docstring'''




							_lowerCAmelCase     :							List[str]    =    F"\n{hint}" if hint is not None else ""

							# non-versioned check
							if re.match(r"^[\w_\-\d]+$"				, _lowerCamelCase  ):
														_lowerCAmelCase   ,    _lowerCAmelCase   ,    _lowerCAmelCase     :							List[str]    =    requirement, None, None
							else:
														_lowerCAmelCase     :							Optional[int]    =    re.findall(r"^([^!=<>\s]+)([\s!=<>]{1,2}.+)"				, _lowerCamelCase  )
														if not match:
																					raise ValueError(
																					    "requirement needs to be in the pip package format, .e.g., package_a==1.23, or package_b>=1.23, but"
																					    F" got {requirement}"  )
														_lowerCAmelCase   ,    _lowerCAmelCase     :							Dict    =    match[0]
														_lowerCAmelCase     :							Any    =    want_full.split(","  )  # there could be multiple requirements
														_lowerCAmelCase     :							Optional[int]    =    {}
														for w in want_range:
																					_lowerCAmelCase     :							Any    =    re.findall(r"^([\s!=<>]{1,2})(.+)"				, _lowerCamelCase  )
																					if not match:
																												raise ValueError(
																												    "requirement needs to be in the pip package format, .e.g., package_a==1.23, or package_b>=1.23,"
																												    F" but got {requirement}"  )
																					_lowerCAmelCase   ,    _lowerCAmelCase     :							Tuple    =    match[0]
																					_lowerCAmelCase     :							Union[str, Any]    =    want_ver
																					if op not in ops:
																												raise ValueError(F"{requirement}: need one of {list(ops.keys()  )}, but got {op}"  )

    # special case
							if pkg == "python":
														_lowerCAmelCase     :							Tuple    =    ".".join([str(_lowerCamelCase  ) for x in sys.version_info[:3]]  )
														for op, want_ver in wanted.items():
																					_compare_versions(_lowerCamelCase				, _lowerCamelCase				, _lowerCamelCase				, _lowerCamelCase				, _lowerCamelCase				, _lowerCamelCase  )
														return

							# check if any version is installed
							try:
														_lowerCAmelCase     :							Any    =    importlib.metadata.version(_lowerCamelCase  )
							except importlib.metadata.PackageNotFoundError:
														raise importlib.metadata.PackageNotFoundError(
														    F"The '{requirement}' distribution was not found and is required by this application. {hint}"  )

							# check that the right version is installed if version number or a range was provided
							if want_ver is not None:
														for op, want_ver in wanted.items():
																					_compare_versions(_lowerCamelCase				, _lowerCamelCase				, _lowerCamelCase				, _lowerCamelCase				, _lowerCamelCase				, _lowerCamelCase  )






def 				A				(					_lowerCamelCase  ):





							'''simple docstring'''




							_lowerCAmelCase     :							List[str]    =    "Try: pip install transformers -U or pip install -e '.[dev]' if you're working with git main"
							return require_version(_lowerCamelCase				, _lowerCamelCase  )
