

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		:       Dict						    =	Mapping[str, np.ndarray]
_UpperCAmelCase		:       Union[str, Any]						    =	Mapping[str, Any]  # Is a nested dict.
_UpperCAmelCase		:       int						    =	0.01







@dataclasses.dataclass(frozen=lowercase_      )
class 			lowercase    :
				__SCREAMING_SNAKE_CASE :			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'.
				__SCREAMING_SNAKE_CASE :			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.
				__SCREAMING_SNAKE_CASE :			np.ndarray  # [num_res, num_atom_type]

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

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

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

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

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





def  __lowerCamelCase     (			UpperCamelCase__				):







							'''simple docstring'''






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

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







							'''simple docstring'''






							snake_case_          =   []

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

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

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

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

							return pdb_headers





def  __lowerCamelCase     (			UpperCamelCase__       ,							UpperCamelCase__				):







							'''simple docstring'''






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

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

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

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

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

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

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

																					out_pdb_lines.append(make_parent_line(UpperCamelCase__				)				)

							return "\n".join(UpperCamelCase__				)





def  __lowerCamelCase     (			UpperCamelCase__				):







							'''simple docstring'''






							snake_case_          =   residue_constants.restypes + ['X']

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

							snake_case_          =   residue_constants.atom_types

							snake_case_          =   []

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

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

							snake_case_          =   get_pdb_headers(UpperCamelCase__				)
							if len(UpperCamelCase__				) > 0:
														pdb_lines.extend(UpperCamelCase__				)

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

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

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

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

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

														if should_terminate:
																					# Close the chain.
																					snake_case_          =   'TER'
																					snake_case_          =   (
																					    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  __lowerCamelCase     (			UpperCamelCase__				):







							'''simple docstring'''






							return residue_constants.STANDARD_ATOM_MASK[prot.aatype]





def  __lowerCamelCase     (			UpperCamelCase__       ,							UpperCamelCase__       ,							UpperCamelCase__ = None       ,							UpperCamelCase__ = None       ,							UpperCamelCase__ = None       ,							UpperCamelCase__ = None       ,							UpperCamelCase__ = None       ,							):







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







def  __lowerCamelCase     (			UpperCamelCase__       ,							UpperCamelCase__				):







							'''simple docstring'''






							return int((input_a, input_a).count(0				) != 0				)





def  __lowerCamelCase     (			):







							'''simple docstring'''






							assert nand_gate(0       ,							0				) == 1
							assert nand_gate(0       ,							1				) == 1
							assert nand_gate(1       ,							0				) == 1
							assert nand_gate(1       ,							1				) == 0


if __name__ == "__main__":
					print(nand_gate(0, 0))
					print(nand_gate(0, 1))
					print(nand_gate(1, 0))
					print(nand_gate(1, 1))




