





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


_SCREAMING_SNAKE_CASE   =      Mapping[str, np.ndarray]
_SCREAMING_SNAKE_CASE   =      Mapping[str, Any]  # Is a nested dict.
_SCREAMING_SNAKE_CASE   =      0.0_1






@dataclasses.dataclass(frozen=lowerCAmelCase__  )
class 							__lowercase    :







	'''simple docstring'''

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

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

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

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

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

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





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

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

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

			return pdb_headers




def 				_lowerCAmelCase  (			lowerCamelCase_     :					Protein						,    lowerCamelCase_     :					str			):
			__lowercase			  =							[]
			__lowercase			  =							pdb_str.split('''\n'''			)

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

			__lowercase			  =							4_2
			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(lowerCamelCase_			)						,    []			)
												parent_dict[str(lowerCamelCase_			)].append(lowerCamelCase_			)

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

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

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

			__lowercase			  =							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_			):
												__lowercase			  =							parents_per_chain[chain_counter]
									else:
												__lowercase			  =							['''N/A''']

									out_pdb_lines.append(make_parent_line(lowerCamelCase_			)			)

			return "\n".join(lowerCamelCase_			)




def 				_lowerCAmelCase  (			lowerCamelCase_     :					Protein			):
			__lowercase			  =							residue_constants.restypes + ['''X''']

			def res_atoa(lowerCamelCase_     :					int			) -> 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(lowerCamelCase_			)
			if len(lowerCamelCase_			) > 0:
						pdb_lines.extend(lowerCamelCase_			)

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

									__lowercase			  =							'''ATOM'''
									__lowercase			  =							atom_name if len(lowerCamelCase_			) == 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(lowerCamelCase_			)
									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(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 				_lowerCAmelCase  (			lowerCamelCase_     :					Protein			):
			return residue_constants.STANDARD_ATOM_MASK[prot.aatype]




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












'''simple docstring'''



import numpy as np




def 				_lowerCAmelCase  (			lowerCamelCase_     :					np.array			):
			return 1 / (1 + np.exp(-vector			))




def 				_lowerCAmelCase  (			lowerCamelCase_     :					np.array			):
			return vector * sigmoid(1.7_02 * vector			)


if __name__ == "__main__":
	import doctest

	doctest.testmod()





