

"""simple docstring"""





from typing import Dict, Tuple, overload

import torch
import torch.types
from torch import nn

from . import residue_constants as rc
from .rigid_utils import Rigid, Rotation
from .tensor_utils import batched_gather



@overload
def        _lowerCAmelCase      (						UpperCAmelCase     :							torch.Tensor      ,							UpperCAmelCase     :							torch.Tensor      ,							UpperCAmelCase     :							None				):


					'''simple docstring'''






					...



@overload
def        _lowerCAmelCase      (						UpperCAmelCase     :							torch.Tensor      ,							UpperCAmelCase     :							torch.Tensor      ,							UpperCAmelCase     :							torch.Tensor				):


					'''simple docstring'''






					...



def        _lowerCAmelCase      (						UpperCAmelCase     :							Union[str, Any]      ,							UpperCAmelCase     :							Optional[Any]      ,							UpperCAmelCase     :							Optional[int]				):


					'''simple docstring'''






					UpperCamelCase__		:    int         =aatype == rc.restype_order['''G''']
					UpperCamelCase__		:    Dict         =rc.atom_order['''CA''']
					UpperCamelCase__		:    Dict         =rc.atom_order['''CB''']
					UpperCamelCase__		:    Any         =torch.where(
					    is_gly[..., None].expand(*((-1,) * len(is_gly.shape				))      ,							3				)      ,							all_atom_positions[..., ca_idx, :]      ,							all_atom_positions[..., cb_idx, :]      ,							)

					if all_atom_masks is not None:
										UpperCamelCase__		:    Union[str, Any]         =torch.where(
										    UpperCAmelCase      ,							all_atom_masks[..., ca_idx]      ,							all_atom_masks[..., cb_idx]      ,							)
										return pseudo_beta, pseudo_beta_mask
					else:
										return pseudo_beta



def        _lowerCAmelCase      (						UpperCAmelCase     :							torch.Tensor      ,							UpperCAmelCase     :							Dict[str, torch.Tensor]				):


					'''simple docstring'''






					UpperCamelCase__		:    int         =batched_gather(
					    UpperCAmelCase      ,							batch['''residx_atom37_to_atom14''']      ,							dim=-2      ,							no_batch_dims=len(atomaa.shape[:-2]				)      ,							)

					UpperCamelCase__		:    Union[str, Any]         =atomaa_data * batch['''atom37_atom_exists'''][..., None]

					return atomaa_data



def        _lowerCAmelCase      (						UpperCAmelCase     :							Dict[str, torch.Tensor]				):


					'''simple docstring'''






					UpperCamelCase__		:    Tuple         =template_feats['''template_aatype''']
					UpperCamelCase__		:    Optional[Any]         =template_feats['''template_torsion_angles_sin_cos''']
					UpperCamelCase__		:    Union[str, Any]         =template_feats['''template_alt_torsion_angles_sin_cos''']
					UpperCamelCase__		:    Dict         =template_feats['''template_torsion_angles_mask''']
					UpperCamelCase__		:    Any         =torch.cat(
					    [
					        nn.functional.one_hot(UpperCAmelCase      ,							22				),
					        torsion_angles_sin_cos.reshape(*torsion_angles_sin_cos.shape[:-2]      ,							14				),
					        alt_torsion_angles_sin_cos.reshape(*alt_torsion_angles_sin_cos.shape[:-2]      ,							14				),
					        torsion_angles_mask,
					    ]      ,							dim=-1      ,							)

					return template_angle_feat



def        _lowerCAmelCase      (						UpperCAmelCase     :							Dict[str, torch.Tensor]      ,							UpperCAmelCase     :							torch.types.Number      ,							UpperCAmelCase     :							torch.types.Number      ,							UpperCAmelCase     :							int      ,							UpperCAmelCase     :							bool = False      ,							UpperCAmelCase     :							float = 1E-20      ,							UpperCAmelCase     :							float = 1E8      ,							):


					'''simple docstring'''






					UpperCamelCase__		:    Tuple         =batch['''template_pseudo_beta_mask''']
					UpperCamelCase__		:    Optional[int]         =template_mask[..., None] * template_mask[..., None, :]

					# Compute distogram (this seems to differ slightly from Alg. 5)
					UpperCamelCase__		:    Union[str, Any]         =batch['''template_pseudo_beta''']
					UpperCamelCase__		:    Dict         =torch.sum((tpb[..., None, :] - tpb[..., None, :, :]) ** 2      ,							dim=-1      ,							keepdim=UpperCAmelCase				)
					UpperCamelCase__		:    List[str]         =torch.linspace(UpperCAmelCase      ,							UpperCAmelCase      ,							UpperCAmelCase      ,							device=tpb.device				) ** 2
					UpperCamelCase__		:    Any         =torch.cat([lower[1:], lower.new_tensor([inf]				)]      ,							dim=-1				)
					UpperCamelCase__		:    Optional[Any]         =((dgram > lower) * (dgram < upper)).type(dgram.dtype				)

					UpperCamelCase__		:    Any         =[dgram, template_mask_ad[..., None]]

					UpperCamelCase__		:    torch.LongTensor         =nn.functional.one_hot(
					    batch['''template_aatype''']      ,							rc.restype_num + 2      ,							)

					UpperCamelCase__		:    Dict         =batch['''template_aatype'''].shape[-1]
					to_concat.append(aatype_one_hot[..., None, :, :].expand(*aatype_one_hot.shape[:-2]      ,							UpperCAmelCase      ,							-1      ,							-1				)				)
					to_concat.append(aatype_one_hot[..., None, :].expand(*aatype_one_hot.shape[:-2]      ,							-1      ,							UpperCAmelCase      ,							-1				)				)

					UpperCamelCase__  ,			UpperCamelCase__  ,			UpperCamelCase__		:    List[str]         =[rc.atom_order[a] for a in ['''N''', '''CA''', '''C''']]
					UpperCamelCase__		:    List[Any]         =Rigid.make_transform_from_reference(
					    n_xyz=batch['''template_all_atom_positions'''][..., n, :]      ,							ca_xyz=batch['''template_all_atom_positions'''][..., ca, :]      ,							c_xyz=batch['''template_all_atom_positions'''][..., c, :]      ,							eps=UpperCAmelCase      ,							)
					UpperCamelCase__		:    List[str]         =rigids.get_trans()[..., None, :, :]
					UpperCamelCase__		:    Union[str, Any]         =rigids[..., None].invert_apply(UpperCAmelCase				)

					UpperCamelCase__		:    Tuple         =torch.rsqrt(eps + torch.sum(rigid_vec**2      ,							dim=-1				)				)

					UpperCamelCase__		:    Dict         =batch['''template_all_atom_mask''']
					UpperCamelCase__		:    Optional[int]         =t_aa_masks[..., n] * t_aa_masks[..., ca] * t_aa_masks[..., c]
					UpperCamelCase__		:    Dict         =template_mask[..., None] * template_mask[..., None, :]

					UpperCamelCase__		:    Tuple         =inv_distance_scalar * template_mask_ad
					UpperCamelCase__		:    Tuple         =rigid_vec * inv_distance_scalar[..., None]

					if not use_unit_vector:
										UpperCamelCase__		:    Dict         =unit_vector * 0.0

					to_concat.extend(torch.unbind(unit_vector[..., None, :]      ,							dim=-1				)				)
					to_concat.append(template_mask_ad[..., None]				)

					UpperCamelCase__		:    Any         =torch.cat(UpperCAmelCase      ,							dim=-1				)
					UpperCamelCase__		:    List[str]         =act * template_mask_ad[..., None]

					return act



def        _lowerCAmelCase      (						UpperCAmelCase     :							Dict[str, torch.Tensor]				):


					'''simple docstring'''






					UpperCamelCase__		:    torch.LongTensor         =nn.functional.one_hot(batch['''extra_msa''']      ,							23				)
					UpperCamelCase__		:    Any         =[
					    msa_ahot,
					    batch['''extra_has_deletion'''].unsqueeze(-1				),
					    batch['''extra_deletion_value'''].unsqueeze(-1				),
					]
					return torch.cat(UpperCAmelCase      ,							dim=-1				)



def        _lowerCAmelCase      (						UpperCAmelCase     :							Rigid      ,							UpperCAmelCase     :							torch.Tensor      ,							UpperCAmelCase     :							torch.Tensor      ,							UpperCAmelCase     :							torch.Tensor      ,							):


					'''simple docstring'''






					UpperCamelCase__		:    Optional[Any]         =rrgdf[aatype, ...]

					# [*, N, 8] transformations, i.e.
					#   One [*, N, 8, 3, 3] rotation matrix and
					#   One [*, N, 8, 3]    translation matrix
					UpperCamelCase__		:    List[Any]         =r.from_tensor_axa(UpperCAmelCase				)

					UpperCamelCase__		:    int         =alpha.new_zeros((*((1,) * len(alpha.shape[:-1]				)), 2)				)
					UpperCamelCase__		:    Any         =1

					# [*, N, 8, 2]
					UpperCamelCase__		:    List[Any]         =torch.cat([bb_rot.expand(*alpha.shape[:-2]      ,							-1      ,							-1				), alpha]      ,							dim=-2				)

					# [*, N, 8, 3, 3]
					# Produces rotation matrices of the form:
					# [
					#   [1, 0  , 0  ],
					#   [0, a_2,-a_1],
					#   [0, a_1, a_2]
					# ]
					# This follows the original code rather than the supplement, which uses
					# different indices.

					UpperCamelCase__		:    str         =alpha.new_zeros(default_r.get_rots().get_rot_mats().shape				)
					UpperCamelCase__		:    Any         =1
					UpperCamelCase__		:    List[Any]         =alpha[..., 1]
					UpperCamelCase__		:    Optional[int]         =-alpha[..., 0]
					UpperCamelCase__		:    Optional[Any]         =alpha

					UpperCamelCase__		:    str         =default_r.compose(Rigid(Rotation(rot_mats=UpperCAmelCase				)      ,							UpperCAmelCase				)				)

					UpperCamelCase__		:    str         =all_frames[..., 5]
					UpperCamelCase__		:    Tuple         =all_frames[..., 6]
					UpperCamelCase__		:    Dict         =all_frames[..., 7]

					UpperCamelCase__		:    Optional[Any]         =all_frames[..., 4]
					UpperCamelCase__		:    Optional[int]         =chia_frame_to_bb.compose(UpperCAmelCase				)
					UpperCamelCase__		:    Union[str, Any]         =chia_frame_to_bb.compose(UpperCAmelCase				)
					UpperCamelCase__		:    int         =chia_frame_to_bb.compose(UpperCAmelCase				)

					UpperCamelCase__		:    Union[str, Any]         =Rigid.cat(
					    [
					        all_frames[..., :5],
					        chia_frame_to_bb.unsqueeze(-1				),
					        chia_frame_to_bb.unsqueeze(-1				),
					        chia_frame_to_bb.unsqueeze(-1				),
					    ]      ,							dim=-1      ,							)

					UpperCamelCase__		:    Dict         =r[..., None].compose(UpperCAmelCase				)

					return all_frames_to_global







def        _lowerCAmelCase      (						UpperCAmelCase     :							Rigid      ,							UpperCAmelCase     :							torch.Tensor      ,							UpperCAmelCase     :							torch.Tensor      ,							UpperCAmelCase     :							torch.Tensor      ,							UpperCAmelCase     :							torch.Tensor      ,							UpperCAmelCase     :							torch.Tensor      ,							):


					'''simple docstring'''






					UpperCamelCase__		:    str         =group_idx[aatype, ...]

					# [*, N, 14, 8]
					UpperCamelCase__		:    torch.LongTensor         =nn.functional.one_hot(
					    UpperCAmelCase      ,							num_classes=default_frames.shape[-3]      ,							)

					# [*, N, 14, 8]
					UpperCamelCase__		:    Optional[int]         =r[..., None, :] * group_mask_one_hot

					# [*, N, 14]
					UpperCamelCase__		:    Any         =t_atoms_to_global.map_tensor_fn(lambda UpperCAmelCase				: torch.sum(UpperCAmelCase      ,							dim=-1				)				)

					# [*, N, 14, 1]
					UpperCamelCase__		:    Union[str, Any]         =atom_mask[aatype, ...].unsqueeze(-1				)

					# [*, N, 14, 3]
					UpperCamelCase__		:    List[str]         =lit_positions[aatype, ...]
					UpperCamelCase__		:    Tuple         =t_atoms_to_global.apply(UpperCAmelCase				)
					UpperCamelCase__		:    List[str]         =pred_positions * atom_mask

					return pred_positions





"""simple docstring"""





from __future__ import annotations

from collections.abc import Iterable
from dataclasses import dataclass
from typing import Any

class     __a   :

			"""simple docstring"""

			SCREAMING_SNAKE_CASE_						     =						('_front', '_back', '_len')

			@dataclass
			class     __a   :

						"""simple docstring"""

						SCREAMING_SNAKE_CASE_						     =						None
						SCREAMING_SNAKE_CASE_						     =						None
						SCREAMING_SNAKE_CASE_						     =						None



			class     __a   :

						"""simple docstring"""

						SCREAMING_SNAKE_CASE_						     =						('_cur',)






						def __init__(							self     :					Optional[int]						,  lowercase_     :					Deque._Node | None						):
											UpperCamelCase__		:    List[str]         =cur






						def __iter__(							self     :					List[str]						):
											return self






						def    _lowerCAmelCase			(							self     :					List[Any]						):
											if self._cur is None:
																# finished iterating
																raise StopIteration
											UpperCamelCase__		:    str         =self._cur.val
											UpperCamelCase__		:    Any         =self._cur.next_node

											return val






			def __init__(							self     :					str						,  lowercase_     :					Iterable[Any] | None = None						):
								UpperCamelCase__		:    Any         =None
								UpperCamelCase__		:    Any         =None
								UpperCamelCase__		:    int         =0

								if iterable is not None:
													# append every value to the deque
													for val in iterable:
																		self.append(lowercase_						)






			def    _lowerCAmelCase			(							self     :					str						,  lowercase_     :					Any						):
								UpperCamelCase__		:    Union[str, Any]         =self._Node(lowercase_						,  lowercase_						,  lowercase_						)
								if self.is_empty():
													# front = back
													UpperCamelCase__		:    Any         =node
													UpperCamelCase__		:    List[Any]         =1
								else:
													# connect nodes
													UpperCamelCase__		:    Any         =node
													UpperCamelCase__		:    Optional[Any]         =self._back
													UpperCamelCase__		:    str         =node  # assign new back to the new node

													self._len += 1

													# make sure there were no errors
													assert not self.is_empty(), "Error on appending value."






			def    _lowerCAmelCase			(							self     :					Optional[Any]						,  lowercase_     :					Any						):
								UpperCamelCase__		:    str         =self._Node(lowercase_						,  lowercase_						,  lowercase_						)
								if self.is_empty():
													# front = back
													UpperCamelCase__		:    str         =node
													UpperCamelCase__		:    Any         =1
								else:
													# connect nodes
													UpperCamelCase__		:    int         =self._front
													UpperCamelCase__		:    int         =node
													UpperCamelCase__		:    Any         =node  # assign new front to the new node

													self._len += 1

													# make sure there were no errors
													assert not self.is_empty(), "Error on appending value."






			def    _lowerCAmelCase			(							self     :					List[Any]						,  lowercase_     :					Iterable[Any]						):
								for val in iterable:
													self.append(lowercase_						)






			def    _lowerCAmelCase			(							self     :					Dict						,  lowercase_     :					Iterable[Any]						):
								for val in iterable:
													self.appendleft(lowercase_						)






			def    _lowerCAmelCase			(							self     :					Optional[int]						):
								assert not self.is_empty(), "Deque is empty."

								UpperCamelCase__		:    List[Any]         =self._back
								UpperCamelCase__		:    Any         =self._back.prev_node  # set new back
								# drop the last node - python will deallocate memory automatically
								UpperCamelCase__		:    List[str]         =None

								self._len -= 1

								return topop.val






			def    _lowerCAmelCase			(							self     :					str						):
								assert not self.is_empty(), "Deque is empty."

								UpperCamelCase__		:    List[str]         =self._front
								UpperCamelCase__		:    List[Any]         =self._front.next_node  # set new front and drop the first node
								UpperCamelCase__		:    Dict         =None

								self._len -= 1

								return topop.val






			def    _lowerCAmelCase			(							self     :					Dict						):
								return self._front is None






			def __len__(							self     :					Any						):
								return self._len






			def __eq__(							self     :					Dict						,  lowercase_     :					object						):

								if not isinstance(lowercase_						,  lowercase_						):
													return NotImplemented

								UpperCamelCase__		:    Union[str, Any]         =self._front
								UpperCamelCase__		:    Union[str, Any]         =other._front

								# if the length of the dequeues are not the same, they are not equal
								if len(self						) != len(lowercase_						):
													return False

								while me is not None and oth is not None:
													# compare every value
													if me.val != oth.val:
																		return False
													UpperCamelCase__		:    Union[str, Any]         =me.next_node
													UpperCamelCase__		:    Union[str, Any]         =oth.next_node

								return True






			def __iter__(							self     :					Optional[int]						):
								return Deque._Iterator(self._front						)






			def __repr__(							self     :					Tuple						):
								UpperCamelCase__		:    List[Any]         =[]
								UpperCamelCase__		:    Optional[int]         =self._front
								while aux is not None:
													# append the values in a list to display
													values_list.append(aux.val						)
													UpperCamelCase__		:    Optional[Any]         =aux.next_node

								return f'''[{', '.join(repr(lowercase_						) for val in values_list						)}]'''


if __name__ == "__main__":
				import doctest

				doctest.testmod()


