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


snake_case_			=     Mapping[str, np.ndarray]
snake_case_			=     Mapping[str, Any]  # Is a nested dict.
snake_case_			=     0.01


@dataclasses.dataclass(frozen=_snake_case	)
class 	a__     :
	__magic_name__		:    List[str]	    =     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'.
	__magic_name__		:    Optional[Any]	    =     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.
	__magic_name__		:    str	    =     42  # [num_res, num_atom_type]

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

	# Chain indices for multi-chain predictions
	__magic_name__		:    str	    =     None

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

	# Templates used to generate this protein (prediction-only)
	__magic_name__		:    Union[str, Any]	    =     None

	# Chain corresponding to each parent
	__magic_name__		:    Union[str, Any]	    =     None






def       __lowercase  (_SCREAMING_SNAKE_CASE      :Tuple       ):
				SCREAMING_SNAKE_CASE  :						List[str]      					= R'''(\[[A-Z]+\]\n)'''
				SCREAMING_SNAKE_CASE  :						Optional[Any]      					= [tag.strip() for tag in re.split(__A    ,	__A       ) if len(__A       ) > 0]
				SCREAMING_SNAKE_CASE  :						Tuple      					= zip(tags[0::2]    ,	[l.split('''\n'''       ) for l in tags[1::2]]       )

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

				assert aatype is not None

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






def       __lowercase  (_SCREAMING_SNAKE_CASE      :int    ,	_SCREAMING_SNAKE_CASE      :str = 0       ):
				SCREAMING_SNAKE_CASE  :						Optional[Any]      					= []

				SCREAMING_SNAKE_CASE  :						Union[str, Any]      					= prot.remark
				if remark is not None:
								pdb_headers.append(F'''REMARK {remark}'''       )

				SCREAMING_SNAKE_CASE  :						int      					= prot.parents
				SCREAMING_SNAKE_CASE  :						Tuple      					= prot.parents_chain_index
				if parents is not None and parents_chain_index is not None:
								SCREAMING_SNAKE_CASE  :						Optional[int]      					= [p for i, p in zip(__A    ,	__A       ) if i == chain_id]

				if parents is None or len(__A       ) == 0:
								SCREAMING_SNAKE_CASE  :						Optional[Any]      					= ['''N/A''']

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

				return pdb_headers






def       __lowercase  (_SCREAMING_SNAKE_CASE      :Dict    ,	_SCREAMING_SNAKE_CASE      :str       ):
				SCREAMING_SNAKE_CASE  :						List[str]      					= []
				SCREAMING_SNAKE_CASE  :						Union[str, Any]      					= pdb_str.split('''\n'''       )

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

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

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

				def make_parent_line(_SCREAMING_SNAKE_CASE      :List[str]       ) -> str:
								return F'''PARENT {" ".join(__A       )}'''

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

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

												out_pdb_lines.append(make_parent_line(__A       )       )

				return "\n".join(__A       )






def       __lowercase  (_SCREAMING_SNAKE_CASE      :int       ):
				SCREAMING_SNAKE_CASE  :						str      					= residue_constants.restypes + ['''X''']

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

				SCREAMING_SNAKE_CASE  :						List[Any]      					= residue_constants.atom_types

				SCREAMING_SNAKE_CASE  :						Optional[int]      					= []

				SCREAMING_SNAKE_CASE  :						Tuple      					= prot.atom_mask
				SCREAMING_SNAKE_CASE  :						int      					= prot.aatype
				SCREAMING_SNAKE_CASE  :						Optional[int]      					= prot.atom_positions
				SCREAMING_SNAKE_CASE  :						Union[str, Any]      					= prot.residue_index.astype(np.intaa       )
				SCREAMING_SNAKE_CASE  :						Dict      					= prot.b_factors
				SCREAMING_SNAKE_CASE  :						int      					= prot.chain_index

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

				SCREAMING_SNAKE_CASE  :						List[Any]      					= get_pdb_headers(__A       )
				if len(__A       ) > 0:
								pdb_lines.extend(__A       )

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

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

												SCREAMING_SNAKE_CASE  :						Any      					= '''A'''
												if chain_index is not None:
																SCREAMING_SNAKE_CASE  :						List[Any]      					= chain_tags[chain_index[i]]

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

								SCREAMING_SNAKE_CASE  :						Union[str, Any]      					= i == n - 1
								if chain_index is not None:
												if i != n - 1 and chain_index[i + 1] != prev_chain_index:
																SCREAMING_SNAKE_CASE  :						Tuple      					= True
																SCREAMING_SNAKE_CASE  :						Tuple      					= chain_index[i + 1]

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

				pdb_lines.append('''END'''       )
				pdb_lines.append(''''''       )
				return "\n".join(__A       )






def       __lowercase  (_SCREAMING_SNAKE_CASE      :Union[str, Any]       ):
				return residue_constants.STANDARD_ATOM_MASK[prot.aatype]






def       __lowercase  (_SCREAMING_SNAKE_CASE      :Optional[int]    ,	_SCREAMING_SNAKE_CASE      :List[Any]    ,	_SCREAMING_SNAKE_CASE      :Union[str, Any] = None    ,	_SCREAMING_SNAKE_CASE      :Optional[int] = None    ,	_SCREAMING_SNAKE_CASE      :Optional[Any] = None    ,	_SCREAMING_SNAKE_CASE      :List[str] = None    ,	_SCREAMING_SNAKE_CASE      :List[str] = 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=__A    ,	remark=__A    ,	parents=__A    ,	parents_chain_index=__A    ,	)









'''simple docstring'''

from collections import deque






def       __lowercase  (_SCREAMING_SNAKE_CASE      :List[str]       ):
				SCREAMING_SNAKE_CASE  :						Optional[Any]      					= len(_SCREAMING_SNAKE_CASE       )
				SCREAMING_SNAKE_CASE  :						List[str]      					= deque()
				SCREAMING_SNAKE_CASE  :						Union[str, Any]      					= [False for _ in range(_SCREAMING_SNAKE_CASE       )]
				SCREAMING_SNAKE_CASE  :						Any      					= [-1 for _ in range(_SCREAMING_SNAKE_CASE       )]
				SCREAMING_SNAKE_CASE  :						Union[str, Any]      					= index_of[:]

				def strong_connect(_SCREAMING_SNAKE_CASE      :List[str]    ,	_SCREAMING_SNAKE_CASE      :Any    ,	_SCREAMING_SNAKE_CASE      :List[str]       ):
								SCREAMING_SNAKE_CASE  :						Any      					= index  # the number when this node is seen
								SCREAMING_SNAKE_CASE  :						str      					= index  # lowest rank node reachable from here
								index += 1
								stack.append(_SCREAMING_SNAKE_CASE       )
								SCREAMING_SNAKE_CASE  :						Optional[int]      					= True

								for w in g[v]:
												if index_of[w] == -1:
																SCREAMING_SNAKE_CASE  :						List[str]      					= strong_connect(_SCREAMING_SNAKE_CASE    ,	_SCREAMING_SNAKE_CASE    ,	_SCREAMING_SNAKE_CASE       )
																SCREAMING_SNAKE_CASE  :						Optional[int]      					= (
																    lowlink_of[w] if lowlink_of[w] < lowlink_of[v] else lowlink_of[v]
																)
												elif on_stack[w]:
																SCREAMING_SNAKE_CASE  :						List[str]      					= (
																    lowlink_of[w] if lowlink_of[w] < lowlink_of[v] else lowlink_of[v]
																)

								if lowlink_of[v] == index_of[v]:
												SCREAMING_SNAKE_CASE  :						str      					= []
												SCREAMING_SNAKE_CASE  :						Union[str, Any]      					= stack.pop()
												SCREAMING_SNAKE_CASE  :						Union[str, Any]      					= False
												component.append(_SCREAMING_SNAKE_CASE       )
												while w != v:
																SCREAMING_SNAKE_CASE  :						int      					= stack.pop()
																SCREAMING_SNAKE_CASE  :						Tuple      					= False
																component.append(_SCREAMING_SNAKE_CASE       )
												components.append(_SCREAMING_SNAKE_CASE       )
								return index

				SCREAMING_SNAKE_CASE  :						int      					= []
				for v in range(_SCREAMING_SNAKE_CASE       ):
								if index_of[v] == -1:
												strong_connect(_SCREAMING_SNAKE_CASE    ,	0    ,	_SCREAMING_SNAKE_CASE       )

				return components






def       __lowercase  (_SCREAMING_SNAKE_CASE      :List[str]    ,	_SCREAMING_SNAKE_CASE      :Optional[int]       ):
				SCREAMING_SNAKE_CASE  :						Tuple      					= [[] for _ in range(_SCREAMING_SNAKE_CASE       )]
				for u, v in edges:
								g[u].append(_SCREAMING_SNAKE_CASE       )
				return g


if __name__ == "__main__":
	# Test
	snake_case_			=     7
	snake_case_			=     [0, 0, 1, 2, 3, 3, 4, 4, 6]
	snake_case_			=     [1, 3, 2, 0, 1, 4, 5, 6, 5]
	snake_case_			=     [(u, v) for u, v in zip(source, target)]
	snake_case_			=     create_graph(n_vertices, edges)

	assert [[5], [6], [4], [3, 2, 1, 0]] == tarjan(g)




