


"""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


__magic_name__						: Optional[int]    =				Mapping[str, np.ndarray]
__magic_name__						: Any    =				Mapping[str, Any]  # Is a nested dict.
__magic_name__						: List[Any]    =				0.0_1




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

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

							# Chain indices for multi-chain predictions
							__a					 =       None

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

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

							# Chain corresponding to each parent
							__a					 =       None





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

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

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

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

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

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

			return pdb_headers





def       a_ (	lowercase__ :Protein,			lowercase__ :str     ):
			__lowerCamelCase          =      []
			__lowerCamelCase          =      pdb_str.split("""\n"""     )

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

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

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

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

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

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

									out_pdb_lines.append(make_parent_line(lowercase__     )     )

			return "\n".join(lowercase__     )





def       a_ (	lowercase__ :Protein     ):
			__lowerCamelCase          =      residue_constants.restypes + ["""X"""]

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

			__lowerCamelCase          =      residue_constants.atom_types

			__lowerCamelCase          =      []

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

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

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

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

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

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

									# PDB is a columnar format, every space matters here!
									__lowerCamelCase          =      (
									    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

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

						if should_terminate:
									# Close the chain.
									__lowerCamelCase          =      """TER"""
									__lowerCamelCase          =      (
									    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       a_ (	lowercase__ :Protein     ):
			return residue_constants.STANDARD_ATOM_MASK[prot.aatype]





def       a_ (	lowercase__ :FeatureDict,			lowercase__ :ModelOutput,			lowercase__ :Optional[np.ndarray] = None,			lowercase__ :Optional[np.ndarray] = None,			lowercase__ :Optional[str] = None,			lowercase__ :Optional[Sequence[str]] = None,			lowercase__ :Optional[Sequence[int]] = None,			):
			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__,			)








"""simple docstring"""




__magic_name__						: Optional[Any]    =				'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'





def       a_ (	lowercase__ :bytes     ):
			# Make sure the supplied data is a bytes-like object
			if not isinstance(lowercase__,			lowercase__     ):
						__lowerCamelCase          =      f'a bytes-like object is required, not \'{data.__class__.__name__}\''
						raise TypeError(lowercase__     )

			__lowerCamelCase          =      """""".join(bin(lowercase__     )[2:].zfill(8     ) for byte in data     )

			__lowerCamelCase          =      len(lowercase__     ) % 6 != 0

			if padding_needed:
						# The padding that will be added later
						__lowerCamelCase          =      B"""=""" * ((6 - len(lowercase__     ) % 6) // 2)

						# Append binary_stream with arbitrary binary digits (0's by default) to make its
						# length a multiple of 6.
						binary_stream += "0" * (6 - len(lowercase__     ) % 6)
			else:
						__lowerCamelCase          =      B""""""

			# Encode every 6 binary digits to their corresponding Base64 character
			return (
			    "".join(
			        B64_CHARSET[int(binary_stream[index : index + 6],			2     )]
			        for index in range(0,			len(lowercase__     ),			6     )     ).encode()
			    + padding
			)





def       a_ (	lowercase__ :str     ):
			# Make sure encoded_data is either a string or a bytes-like object
			if not isinstance(lowercase__,			lowercase__     ) and not isinstance(lowercase__,			lowercase__     ):
						__lowerCamelCase          =      (
						    """argument should be a bytes-like object or ASCII string, """
						    f'not \'{encoded_data.__class__.__name__}\''
						)
						raise TypeError(lowercase__     )

			# In case encoded_data is a bytes-like object, make sure it contains only
			# ASCII characters so we convert it to a string object
			if isinstance(lowercase__,			lowercase__     ):
						try:
									__lowerCamelCase          =      encoded_data.decode("""utf-8"""     )
						except UnicodeDecodeError:
									raise ValueError("""base64 encoded data should only contain ASCII characters"""     )

			__lowerCamelCase          =      encoded_data.count("""="""     )

			# Check if the encoded string contains non base64 characters
			if padding:
						assert all(
						    char in B64_CHARSET for char in encoded_data[:-padding]     ), "Invalid base64 character(s) found."
			else:
						assert all(
						    char in B64_CHARSET for char in encoded_data     ), "Invalid base64 character(s) found."

			# Check the padding
			assert len(lowercase__     ) % 4 == 0 and padding < 3, "Incorrect padding"

			if padding:
						# Remove padding if there is one
						__lowerCamelCase          =      encoded_data[:-padding]

						__lowerCamelCase          =      """""".join(
						    bin(B64_CHARSET.index(lowercase__     )     )[2:].zfill(6     ) for char in encoded_data     )[: -padding * 2]
			else:
						__lowerCamelCase          =      """""".join(
						    bin(B64_CHARSET.index(lowercase__     )     )[2:].zfill(6     ) for char in encoded_data     )

			__lowerCamelCase          =      [
			    int(binary_stream[index : index + 8],			2     )
			    for index in range(0,			len(lowercase__     ),			8     )
			]

			return bytes(lowercase__     )


if __name__ == "__main__":
					import doctest

					doctest.testmod()




