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


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

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

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

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

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

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

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







def 						__UpperCAmelCase       (					UpperCAmelCase_					:       List[Any]						)							->    Protein:

	'''simple docstring'''





	__snake_case    :							Any   	=				r'(\[[A-Z]+\]\n)'
	__snake_case    :							Union[str, Any]   	=				[tag.strip() for tag in re.split(_SCREAMING_SNAKE_CASE    ,							_SCREAMING_SNAKE_CASE						) if len(_SCREAMING_SNAKE_CASE						) > 0]
	__snake_case    :							Tuple   	=				zip(tags[0::2]    ,							[l.split('\n'						) for l in tags[1::2]]						)

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

	assert aatype is not None

	return Protein(
	    atom_positions=_SCREAMING_SNAKE_CASE    ,							atom_mask=_SCREAMING_SNAKE_CASE    ,							aatype=_SCREAMING_SNAKE_CASE    ,							residue_index=np.arange(len(_SCREAMING_SNAKE_CASE						)						)    ,							b_factors=_SCREAMING_SNAKE_CASE    ,							)
def 						__UpperCAmelCase       (					UpperCAmelCase_					:       int    ,							UpperCAmelCase_					:       Optional[Any] = 0						)							->    List[str]:

	'''simple docstring'''





	__snake_case    :							Any   	=				[]

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

	__snake_case    :							List[str]   	=				prot.parents
	__snake_case    :							Any   	=				prot.parents_chain_index
	if parents is not None and parents_chain_index is not None:
		__snake_case    :							Optional[Any]   	=				[p for i, p in zip(_SCREAMING_SNAKE_CASE    ,							_SCREAMING_SNAKE_CASE						) if i == chain_id]

	if parents is None or len(_SCREAMING_SNAKE_CASE						) == 0:
		__snake_case    :							Optional[int]   	=				['N/A']

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

	return pdb_headers
def 						__UpperCAmelCase       (					UpperCAmelCase_					:       str    ,							UpperCAmelCase_					:       str						)							->    str:

	'''simple docstring'''





	__snake_case    :							Union[str, Any]   	=				[]
	__snake_case    :							str   	=				pdb_str.split('\n'						)

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

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

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

	def make_parent_line(UpperCAmelCase_					:       Union[str, Any]						) -> str:
		return F"PARENT {' '.join(_SCREAMING_SNAKE_CASE						)}"

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

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

			out_pdb_lines.append(make_parent_line(_SCREAMING_SNAKE_CASE						)						)

	return "\n".join(_SCREAMING_SNAKE_CASE						)
def 						__UpperCAmelCase       (					UpperCAmelCase_					:       Dict						)							->    str:

	'''simple docstring'''





	__snake_case    :							Optional[int]   	=				residue_constants.restypes + ['X']

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

	__snake_case    :							List[str]   	=				residue_constants.atom_types

	__snake_case    :							Union[str, Any]   	=				[]

	__snake_case    :							List[Any]   	=				prot.atom_mask
	__snake_case    :							Dict   	=				prot.aatype
	__snake_case    :							Any   	=				prot.atom_positions
	__snake_case    :							List[str]   	=				prot.residue_index.astype(np.intaa						)
	__snake_case    :							List[Any]   	=				prot.b_factors
	__snake_case    :							str   	=				prot.chain_index

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

	__snake_case    :							Union[str, Any]   	=				get_pdb_headers(_SCREAMING_SNAKE_CASE						)
	if len(_SCREAMING_SNAKE_CASE						) > 0:
		pdb_lines.extend(_SCREAMING_SNAKE_CASE						)

	__snake_case    :							Optional[Any]   	=				aatype.shape[0]
	__snake_case    :							str   	=				1
	__snake_case    :							Dict   	=				0
	__snake_case    :							List[str]   	=				string.ascii_uppercase
	__snake_case    :							List[Any]   	=				None
	# Add all atom sites.
	for i in range(_SCREAMING_SNAKE_CASE						):
		__snake_case    :							Union[str, Any]   	=				res_atoa(aatype[i]						)
		for atom_name, pos, mask, b_factor in zip(_SCREAMING_SNAKE_CASE    ,							atom_positions[i]    ,							atom_mask[i]    ,							b_factors[i]						):
			if mask < 0.5:
				continue

			__snake_case    :							Dict   	=				'ATOM'
			__snake_case    :							List[str]   	=				atom_name if len(_SCREAMING_SNAKE_CASE						) == 4 else F" {atom_name}"
			__snake_case    :							List[str]   	=				''
			__snake_case    :							Tuple   	=				''
			__snake_case    :							Union[str, Any]   	=				1.00
			__snake_case    :							Optional[int]   	=				atom_name[0]  # Protein supports only C, N, O, S, this works.
			__snake_case    :							Optional[Any]   	=				''

			__snake_case    :							Optional[int]   	=				'A'
			if chain_index is not None:
				__snake_case    :							Optional[int]   	=				chain_tags[chain_index[i]]

			# PDB is a columnar format, every space matters here!
			__snake_case    :							Optional[int]   	=				(
			    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(_SCREAMING_SNAKE_CASE						)
			atom_index += 1

		__snake_case    :							str   	=				i == n - 1
		if chain_index is not None:
			if i != n - 1 and chain_index[i + 1] != prev_chain_index:
				__snake_case    :							Optional[Any]   	=				True
				__snake_case    :							Optional[Any]   	=				chain_index[i + 1]

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

	pdb_lines.append('END'						)
	pdb_lines.append(''						)
	return "\n".join(_SCREAMING_SNAKE_CASE						)
def 						__UpperCAmelCase       (					UpperCAmelCase_					:       str						)							->    np.ndarray:

	'''simple docstring'''





	return residue_constants.STANDARD_ATOM_MASK[prot.aatype]

def 						__UpperCAmelCase       (					UpperCAmelCase_					:       List[str]    ,							UpperCAmelCase_					:       Optional[int]    ,							UpperCAmelCase_					:       Optional[int] = None    ,							UpperCAmelCase_					:       Optional[int] = None    ,							UpperCAmelCase_					:       Dict = None    ,							UpperCAmelCase_					:       Union[str, Any] = None    ,							UpperCAmelCase_					:       Optional[Any] = None    ,							)							->    Protein:

	'''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=_SCREAMING_SNAKE_CASE    ,							remark=_SCREAMING_SNAKE_CASE    ,							parents=_SCREAMING_SNAKE_CASE    ,							parents_chain_index=_SCREAMING_SNAKE_CASE    ,							)


"""simple docstring"""







import argparse
from collections import defaultdict

import yaml


_a  :  Tuple=				"docs/source/en/_toctree.yml"
def 						__UpperCAmelCase       (					UpperCAmelCase_					:       Optional[Any]						)							->    Dict:

	'''simple docstring'''





	__snake_case    :							Union[str, Any]   	=				defaultdict(UpperCAmelCase_						)
	__snake_case    :							List[str]   	=				[]
	__snake_case    :							Tuple   	=				[]
	for doc in doc_list:
		if "local" in doc:
			counts[doc["local"]] += 1

		if doc["title"].lower() == "overview":
			overview_doc.append({'local': doc['local'], 'title': doc['title']}						)
		else:
			new_doc_list.append(UpperCAmelCase_						)

	__snake_case    :							Any   	=				new_doc_list
	__snake_case    :							Dict   	=				[key for key, value in counts.items() if value > 1]

	__snake_case    :							Optional[int]   	=				[]
	for duplicate_key in duplicates:
		__snake_case    :							Tuple   	=				list({doc['title'] for doc in doc_list if doc['local'] == duplicate_key}						)
		if len(UpperCAmelCase_						) > 1:
			raise ValueError(
			    F"{duplicate_key} is present several times in the documentation table of content at "
			    '`docs/source/en/_toctree.yml` with different *Title* values. Choose one of those and remove the '
			    'others.'						)
		# Only add this once
		new_doc.append({'local': duplicate_key, 'title': titles[0]}						)

	# Add none duplicate-keys
	new_doc.extend([doc for doc in doc_list if 'local' not in counts or counts[doc['local']] == 1]						)
	__snake_case    :							List[Any]   	=				sorted(UpperCAmelCase_    ,							key=lambda UpperCAmelCase_						: s["title"].lower()						)

	# "overview" gets special treatment and is always first
	if len(UpperCAmelCase_						) > 1:
		raise ValueError('{doc_list} has two \'overview\' docs which is not allowed.'						)

	overview_doc.extend(UpperCAmelCase_						)

	# Sort
	return overview_doc
def 						__UpperCAmelCase       (					UpperCAmelCase_					:       Optional[int]=False						)							->    str:

	'''simple docstring'''





	with open(UpperCAmelCase_    ,							encoding='utf-8'						) as f:
		__snake_case    :							List[Any]   	=				yaml.safe_load(f.read()						)

	# Get to the API doc
	__snake_case    :							str   	=				0
	while content[api_idx]["title"] != "API":
		api_idx += 1
	__snake_case    :							Union[str, Any]   	=				content[api_idx]['sections']

	# Then to the model doc
	__snake_case    :							Dict   	=				0
	while api_doc[scheduler_idx]["title"] != "Schedulers":
		scheduler_idx += 1

	__snake_case    :							Optional[Any]   	=				api_doc[scheduler_idx]['sections']
	__snake_case    :							Tuple   	=				clean_doc_toc(UpperCAmelCase_						)

	__snake_case    :							Tuple   	=				False
	if new_scheduler_doc != scheduler_doc:
		__snake_case    :							Optional[int]   	=				True
		if overwrite:
			__snake_case    :							Tuple   	=				new_scheduler_doc

	if diff:
		if overwrite:
			__snake_case    :							Optional[int]   	=				api_doc
			with open(UpperCAmelCase_    ,							'w'    ,							encoding='utf-8'						) as f:
				f.write(yaml.dump(UpperCAmelCase_    ,							allow_unicode=UpperCAmelCase_						)						)
		else:
			raise ValueError(
			    'The model doc part of the table of content is not properly sorted, run `make style` to fix this.'						)
def 						__UpperCAmelCase       (					UpperCAmelCase_					:       Any=False						)							->    Union[str, Any]:

	'''simple docstring'''





	with open(UpperCAmelCase_    ,							encoding='utf-8'						) as f:
		__snake_case    :							Dict   	=				yaml.safe_load(f.read()						)

	# Get to the API doc
	__snake_case    :							Dict   	=				0
	while content[api_idx]["title"] != "API":
		api_idx += 1
	__snake_case    :							Dict   	=				content[api_idx]['sections']

	# Then to the model doc
	__snake_case    :							Dict   	=				0
	while api_doc[pipeline_idx]["title"] != "Pipelines":
		pipeline_idx += 1

	__snake_case    :							Optional[int]   	=				False
	__snake_case    :							Optional[Any]   	=				api_doc[pipeline_idx]['sections']
	__snake_case    :							Tuple   	=				[]

	# sort sub pipeline docs
	for pipeline_doc in pipeline_docs:
		if "section" in pipeline_doc:
			__snake_case    :							List[str]   	=				pipeline_doc['section']
			__snake_case    :							Optional[int]   	=				clean_doc_toc(UpperCAmelCase_						)
			if overwrite:
				__snake_case    :							List[Any]   	=				new_sub_pipeline_doc
		new_pipeline_docs.append(UpperCAmelCase_						)

	# sort overall pipeline doc
	__snake_case    :							List[Any]   	=				clean_doc_toc(UpperCAmelCase_						)

	if new_pipeline_docs != pipeline_docs:
		__snake_case    :							Dict   	=				True
		if overwrite:
			__snake_case    :							Tuple   	=				new_pipeline_docs

	if diff:
		if overwrite:
			__snake_case    :							Union[str, Any]   	=				api_doc
			with open(UpperCAmelCase_    ,							'w'    ,							encoding='utf-8'						) as f:
				f.write(yaml.dump(UpperCAmelCase_    ,							allow_unicode=UpperCAmelCase_						)						)
		else:
			raise ValueError(
			    'The model doc part of the table of content is not properly sorted, run `make style` to fix this.'						)


if __name__ == "__main__":
	_a  :  Optional[int]=				argparse.ArgumentParser()
	parser.add_argument("--fix_and_overwrite", action="store_true", help="Whether to fix inconsistencies.")
	_a  :  List[str]=				parser.parse_args()

	check_scheduler_doc(args.fix_and_overwrite)
	check_pipeline_doc(args.fix_and_overwrite)





