



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


UpperCamelCase__ =						Mapping[str, np.ndarray]
UpperCamelCase__ =						Mapping[str, Any]  # Is a nested dict.
UpperCamelCase__ =						0.01
@dataclasses.dataclass(frozen=_UpperCAmelCase			)
class 			_lowerCAmelCase   :






			"""simple docstring"""





			lowercase__      :  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'.
			lowercase__      :  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.
			lowercase__      :  np.ndarray  # [num_res, num_atom_type]

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

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

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

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

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






def  UpperCAmelCase__    (    lowercase__   ) ->      Protein:
						__lowercase					=				r"""(\[[A-Z]+\]\n)"""
						__lowercase					=				[tag.strip() for tag in re.split(lowercase__						,       lowercase__   ) if len(lowercase__   ) > 0]
						__lowercase					=				zip(tags[0::2]						,       [l.split("""\n"""   ) for l in tags[1::2]]   )

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

						assert aatype is not None

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






def  UpperCAmelCase__    (    lowercase__						,       lowercase__ = 0   ) ->      List[str]:
						__lowercase					=				[]

						__lowercase					=				prot.remark
						if remark is not None:
												pdb_headers.append(F"REMARK {remark}"   )

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

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

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

						return pdb_headers






def  UpperCAmelCase__    (    lowercase__						,       lowercase__   ) ->      str:
						__lowercase					=				[]
						__lowercase					=				pdb_str.split("""\n"""   )

						__lowercase					=				prot.remark
						if remark is not None:
												out_pdb_lines.append(F"REMARK {remark}"   )

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

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

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

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

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

																		out_pdb_lines.append(make_parent_line(lowercase__   )   )

						return "\n".join(lowercase__   )






def  UpperCAmelCase__    (    lowercase__   ) ->      str:
						__lowercase					=				residue_constants.restypes + ["""X"""]

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

						__lowercase					=				residue_constants.atom_types

						__lowercase					=				[]

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

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

						__lowercase					=				get_pdb_headers(lowercase__   )
						if len(lowercase__   ) > 0:
												pdb_lines.extend(lowercase__   )

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

																		__lowercase					=				"""ATOM"""
																		__lowercase					=				atom_name if len(lowercase__   ) == 4 else F" {atom_name}"
																		__lowercase					=				""""""
																		__lowercase					=				""""""
																		__lowercase					=				1.00
																		__lowercase					=				atom_name[0]  # Protein supports only C, N, O, S, this works.
																		__lowercase					=				""""""

																		__lowercase					=				"""A"""
																		if chain_index is not None:
																								__lowercase					=				chain_tags[chain_index[i]]

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

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

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

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






def  UpperCAmelCase__    (    lowercase__   ) ->      np.ndarray:
						return residue_constants.STANDARD_ATOM_MASK[prot.aatype]







def  UpperCAmelCase__    (    lowercase__						,       lowercase__						,       lowercase__ = None						,       lowercase__ = None						,       lowercase__ = None						,       lowercase__ = None						,       lowercase__ = None						,       ) ->      Protein:
						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=lowercase__						,       remark=lowercase__						,       parents=lowercase__						,       parents_chain_index=lowercase__						,       )










from typing import TYPE_CHECKING

from ...utils import OptionalDependencyNotAvailable, _LazyModule, is_tf_available, is_torch_available


UpperCamelCase__ =						{
    "configuration_ctrl": ["CTRL_PRETRAINED_CONFIG_ARCHIVE_MAP", "CTRLConfig"],
    "tokenization_ctrl": ["CTRLTokenizer"],
}

try:
			if not is_torch_available():
						raise OptionalDependencyNotAvailable()
except OptionalDependencyNotAvailable:
			pass
else:
			UpperCamelCase__ =						[
			    "CTRL_PRETRAINED_MODEL_ARCHIVE_LIST",
			    "CTRLForSequenceClassification",
			    "CTRLLMHeadModel",
			    "CTRLModel",
			    "CTRLPreTrainedModel",
			]

try:
			if not is_tf_available():
						raise OptionalDependencyNotAvailable()
except OptionalDependencyNotAvailable:
			pass
else:
			UpperCamelCase__ =						[
			    "TF_CTRL_PRETRAINED_MODEL_ARCHIVE_LIST",
			    "TFCTRLForSequenceClassification",
			    "TFCTRLLMHeadModel",
			    "TFCTRLModel",
			    "TFCTRLPreTrainedModel",
			]


if TYPE_CHECKING:
			from .configuration_ctrl import CTRL_PRETRAINED_CONFIG_ARCHIVE_MAP, CTRLConfig
			from .tokenization_ctrl import CTRLTokenizer

			try:
						if not is_torch_available():
									raise OptionalDependencyNotAvailable()
			except OptionalDependencyNotAvailable:
						pass
			else:
						from .modeling_ctrl import (
						    CTRL_PRETRAINED_MODEL_ARCHIVE_LIST,
						    CTRLForSequenceClassification,
						    CTRLLMHeadModel,
						    CTRLModel,
						    CTRLPreTrainedModel,
						)

			try:
						if not is_tf_available():
									raise OptionalDependencyNotAvailable()
			except OptionalDependencyNotAvailable:
						pass
			else:
						from .modeling_tf_ctrl import (
						    TF_CTRL_PRETRAINED_MODEL_ARCHIVE_LIST,
						    TFCTRLForSequenceClassification,
						    TFCTRLLMHeadModel,
						    TFCTRLModel,
						    TFCTRLPreTrainedModel,
						)

else:
			import sys

			UpperCamelCase__ =						_LazyModule(__name__, globals()["__file__"], _import_structure, module_spec=__spec__)





