




"""simple docstring"""

import inspect
from typing import Callable, List, Optional, Set, Tuple, Union

import torch
from packaging import version
from safetensors.torch import storage_ptr, storage_size
from torch import nn

from .utils import logging


__lowerCamelCase								=						[nn.LayerNorm]

__lowerCamelCase								=						logging.get_logger(__name__)

__lowerCamelCase								=						version.parse(version.parse(torch.__version__).base_version)

__lowerCamelCase								=						parsed_torch_version_base >= version.parse("2.0")
__lowerCamelCase								=						parsed_torch_version_base >= version.parse("1.12")
__lowerCamelCase								=						parsed_torch_version_base >= version.parse("1.11")
__lowerCamelCase								=						parsed_torch_version_base < version.parse("1.11")



def 				a (						__snake_case     :				int,    __snake_case     :				List[Any],    __snake_case     :				List[str],    __snake_case     :				List[str],    self     :				Union[str, Any]  ):



    '''simple docstring'''





    from torch import _softmax_backward_data

    if is_torch_less_than_1_11:
        return _softmax_backward_data(__snake_case,    __snake_case,    parent.dim,    self  )
    else:
        return _softmax_backward_data(__snake_case,    __snake_case,    parent.dim,    self.dtype  )



def 				a (						__snake_case     :				nn.Linear,    __snake_case     :				torch.LongTensor,    __snake_case     :				int = 0  ):



    '''simple docstring'''





    UpperCAmelCase_					:int      			=      index.to(layer.weight.device  )
    UpperCAmelCase_					:Dict      			=      layer.weight.index_select(__snake_case,    __snake_case  ).clone().detach()
    if layer.bias is not None:
        if dim == 1:
            UpperCAmelCase_					:Union[str, Any]      			=      layer.bias.clone().detach()
        else:
            UpperCAmelCase_					:List[str]      			=      layer.bias[index].clone().detach()
    UpperCAmelCase_					:Dict      			=      list(layer.weight.size()  )
    UpperCAmelCase_					:List[str]      			=      len(__snake_case  )
    UpperCAmelCase_					:Optional[Any]      			=      nn.Linear(new_size[1],    new_size[0],    bias=layer.bias is not None  ).to(layer.weight.device  )
    UpperCAmelCase_					:str      			=      False
    new_layer.weight.copy_(W.contiguous()  )
    UpperCAmelCase_					:int      			=      True
    if layer.bias is not None:
        UpperCAmelCase_					:Dict      			=      False
        new_layer.bias.copy_(b.contiguous()  )
        UpperCAmelCase_					:Optional[Any]      			=      True
    return new_layer



class  _snake_case				(							nn.Module       ):

    '''simple docstring'''




    def __init__(							self      :  List[Any]					,							snake_case      :  Tuple					,							snake_case      :  Dict     ):
        super().__init__()
        UpperCAmelCase_					:Union[str, Any]      			=      nf
        UpperCAmelCase_					:Union[str, Any]      			=      nn.Parameter(torch.empty(snake_case					,							snake_case     )     )
        UpperCAmelCase_					:str      			=      nn.Parameter(torch.zeros(snake_case     )     )
        nn.init.normal_(self.weight					,							std=0.02     )





    def 				snake_case_ (							self      :  Optional[Any]					,							snake_case      :  Any     ):
        UpperCAmelCase_					:Optional[Any]      			=      x.size()[:-1] + (self.nf,)
        UpperCAmelCase_					:Optional[Any]      			=      torch.addmm(self.bias					,							x.view(-1					,							x.size(-1     )     )					,							self.weight     )
        UpperCAmelCase_					:Tuple      			=      x.view(snake_case     )
        return x



def 				a (						__snake_case     :				ConvaD,    __snake_case     :				torch.LongTensor,    __snake_case     :				int = 1  ):



    '''simple docstring'''





    UpperCAmelCase_					:Any      			=      index.to(layer.weight.device  )
    UpperCAmelCase_					:Union[str, Any]      			=      layer.weight.index_select(__snake_case,    __snake_case  ).clone().detach()
    if dim == 0:
        UpperCAmelCase_					:Optional[int]      			=      layer.bias.clone().detach()
    else:
        UpperCAmelCase_					:str      			=      layer.bias[index].clone().detach()
    UpperCAmelCase_					:List[str]      			=      list(layer.weight.size()  )
    UpperCAmelCase_					:List[Any]      			=      len(__snake_case  )
    UpperCAmelCase_					:Dict      			=      ConvaD(new_size[1],    new_size[0]  ).to(layer.weight.device  )
    UpperCAmelCase_					:Dict      			=      False
    new_layer.weight.copy_(W.contiguous()  )
    UpperCAmelCase_					:str      			=      True
    UpperCAmelCase_					:Tuple      			=      False
    new_layer.bias.copy_(b.contiguous()  )
    UpperCAmelCase_					:int      			=      True
    return new_layer



def 				a (						__snake_case     :				Union[nn.Linear, ConvaD],    __snake_case     :				torch.LongTensor,    __snake_case     :				Optional[int] = None  ):



    '''simple docstring'''





    if isinstance(__snake_case,    nn.Linear  ):
        return prune_linear_layer(__snake_case,    __snake_case,    dim=0 if dim is None else dim  )
    elif isinstance(__snake_case,    __snake_case  ):
        return prune_convad_layer(__snake_case,    __snake_case,    dim=1 if dim is None else dim  )
    else:
        raise ValueError(f'Can\'t prune layer of class {layer.__class__}'  )



def 				a (						__snake_case     :				Callable[..., torch.Tensor],    __snake_case     :				int,    __snake_case     :				int,    *__snake_case     :				List[str]  ):



    '''simple docstring'''





    assert len(__snake_case  ) > 0, f'{input_tensors} has to be a tuple/list of tensors'

    # inspect.signature exist since python 3.5 and is a python method -> no problem with backward compatibility
    UpperCAmelCase_					:int      			=      len(inspect.signature(__snake_case  ).parameters  )
    if num_args_in_forward_chunk_fn != len(__snake_case  ):
        raise ValueError(
            f'forward_chunk_fn expects {num_args_in_forward_chunk_fn} arguments, but only {len(__snake_case  )} input '
            '''tensors are given'''  )

    if chunk_size > 0:
        UpperCAmelCase_					:Union[str, Any]      			=      input_tensors[0].shape[chunk_dim]
        for input_tensor in input_tensors:
            if input_tensor.shape[chunk_dim] != tensor_shape:
                raise ValueError(
                    f'All input tenors have to be of the same shape: {tensor_shape}, '
                    f'found shape {input_tensor.shape[chunk_dim]}'  )

        if input_tensors[0].shape[chunk_dim] % chunk_size != 0:
            raise ValueError(
                f'The dimension to be chunked {input_tensors[0].shape[chunk_dim]} has to be a multiple of the chunk '
                f'size {chunk_size}'  )

        UpperCAmelCase_					:Dict      			=      input_tensors[0].shape[chunk_dim] // chunk_size

        # chunk input tensor into tuples
        UpperCAmelCase_					:str      			=      tuple(input_tensor.chunk(__snake_case,    dim=__snake_case  ) for input_tensor in input_tensors  )
        # apply forward fn to every tuple
        UpperCAmelCase_					:Dict      			=      tuple(forward_fn(*__snake_case  ) for input_tensors_chunk in zip(*__snake_case  )  )
        # concatenate output at same dimension
        return torch.cat(__snake_case,    dim=__snake_case  )

    return forward_fn(*__snake_case  )



def 				a (						__snake_case     :				List[int],    __snake_case     :				int,    __snake_case     :				int,    __snake_case     :				Set[int]  ):



    '''simple docstring'''





    UpperCAmelCase_					:Dict      			=      torch.ones(__snake_case,    __snake_case  )
    UpperCAmelCase_					:Dict      			=      set(__snake_case  ) - already_pruned_heads  # Convert to set and remove already pruned heads
    for head in heads:
        # Compute how many pruned heads are before the head and move the index accordingly
        UpperCAmelCase_					:Tuple      			=      head - sum(1 if h < head else 0 for h in already_pruned_heads  )
        UpperCAmelCase_					:Union[str, Any]      			=      0
    UpperCAmelCase_					:List[Any]      			=      mask.view(-1  ).contiguous().eq(1  )
    UpperCAmelCase_					:torch.LongTensor      			=      torch.arange(len(__snake_case  )  )[mask].long()
    return heads, index



def 				a (						*__snake_case     :				Union[torch.Tensor, List[torch.Tensor]],    __snake_case     :				Optional[str] = None  ):



    '''simple docstring'''





    return torch.meshgrid(*__snake_case,    indexing=__snake_case  )





def 				a (						__snake_case     :				torch.Tensor  ):



    '''simple docstring'''





    return tensor.device, storage_ptr(__snake_case  ), storage_size(__snake_case  )








"""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 				a (						__snake_case     :				torch.Tensor,    __snake_case     :				torch.Tensor,    __snake_case     :				None  ):



				'''simple docstring'''





				...



@overload
def 				a (						__snake_case     :				torch.Tensor,    __snake_case     :				torch.Tensor,    __snake_case     :				torch.Tensor  ):



				'''simple docstring'''





				...



def 				a (						__snake_case     :				List[str],    __snake_case     :				Optional[int],    __snake_case     :				str  ):



				'''simple docstring'''





				UpperCAmelCase_					:int      			=      aatype == rc.restype_order['''G''']
				UpperCAmelCase_					:Optional[Any]      			=      rc.atom_order['''CA''']
				UpperCAmelCase_					:Optional[Any]      			=      rc.atom_order['''CB''']
				UpperCAmelCase_					:Optional[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_					:Any      			=      torch.where(
								    __snake_case,    all_atom_masks[..., ca_idx],    all_atom_masks[..., cb_idx],    )
								return pseudo_beta, pseudo_beta_mask
				else:
								return pseudo_beta



def 				a (						__snake_case     :				torch.Tensor,    __snake_case     :				Dict[str, torch.Tensor]  ):



				'''simple docstring'''





				UpperCAmelCase_					:List[Any]      			=      batched_gather(
				    __snake_case,    batch['''residx_atom37_to_atom14'''],    dim=-2,    no_batch_dims=len(atomaa.shape[:-2]  ),    )

				UpperCAmelCase_					:Optional[Any]      			=      atomaa_data * batch['''atom37_atom_exists'''][..., None]

				return atomaa_data



def 				a (						__snake_case     :				Dict[str, torch.Tensor]  ):



				'''simple docstring'''





				UpperCAmelCase_					:str      			=      template_feats['''template_aatype''']
				UpperCAmelCase_					:Union[str, Any]      			=      template_feats['''template_torsion_angles_sin_cos''']
				UpperCAmelCase_					:Tuple      			=      template_feats['''template_alt_torsion_angles_sin_cos''']
				UpperCAmelCase_					:Tuple      			=      template_feats['''template_torsion_angles_mask''']
				UpperCAmelCase_					:int      			=      torch.cat(
				    [
				        nn.functional.one_hot(__snake_case,    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 				a (						__snake_case     :				Dict[str, torch.Tensor],    __snake_case     :				torch.types.Number,    __snake_case     :				torch.types.Number,    __snake_case     :				int,    __snake_case     :				bool = False,    __snake_case     :				float = 1E-20,    __snake_case     :				float = 1E8,    ):



				'''simple docstring'''





				UpperCAmelCase_					:List[str]      			=      batch['''template_pseudo_beta_mask''']
				UpperCAmelCase_					:Any      			=      template_mask[..., None] * template_mask[..., None, :]

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

				UpperCAmelCase_					:List[str]      			=      [dgram, template_mask_ad[..., None]]

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

				UpperCAmelCase_					:Optional[Any]      			=      batch['''template_aatype'''].shape[-1]
				to_concat.append(aatype_one_hot[..., None, :, :].expand(*aatype_one_hot.shape[:-2],    __snake_case,    -1,    -1  )  )
				to_concat.append(aatype_one_hot[..., None, :].expand(*aatype_one_hot.shape[:-2],    -1,    __snake_case,    -1  )  )

				UpperCAmelCase_			,UpperCAmelCase_			,UpperCAmelCase_					:Optional[int]      			=      [rc.atom_order[a] for a in ['''N''', '''CA''', '''C''']]
				UpperCAmelCase_					:str      			=      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=__snake_case,    )
				UpperCAmelCase_					:Dict      			=      rigids.get_trans()[..., None, :, :]
				UpperCAmelCase_					:Dict      			=      rigids[..., None].invert_apply(__snake_case  )

				UpperCAmelCase_					:Optional[int]      			=      torch.rsqrt(eps + torch.sum(rigid_vec**2,    dim=-1  )  )

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

				UpperCAmelCase_					:str      			=      inv_distance_scalar * template_mask_ad
				UpperCAmelCase_					:List[Any]      			=      rigid_vec * inv_distance_scalar[..., None]

				if not use_unit_vector:
								UpperCAmelCase_					:List[Any]      			=      unit_vector * 0.0

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

				UpperCAmelCase_					:Optional[int]      			=      torch.cat(__snake_case,    dim=-1  )
				UpperCAmelCase_					:Optional[Any]      			=      act * template_mask_ad[..., None]

				return act



def 				a (						__snake_case     :				Dict[str, torch.Tensor]  ):



				'''simple docstring'''





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



def 				a (						__snake_case     :				Rigid,    __snake_case     :				torch.Tensor,    __snake_case     :				torch.Tensor,    __snake_case     :				torch.Tensor,    ):



				'''simple docstring'''





				UpperCAmelCase_					:Optional[int]      			=      rrgdf[aatype, ...]

				# [*, N, 8] transformations, i.e.
				#   One [*, N, 8, 3, 3] rotation matrix and
				#   One [*, N, 8, 3]    translation matrix
				UpperCAmelCase_					:Optional[int]      			=      r.from_tensor_axa(__snake_case  )

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

				# [*, N, 8, 2]
				UpperCAmelCase_					:Tuple      			=      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_					:Any      			=      alpha.new_zeros(default_r.get_rots().get_rot_mats().shape  )
				UpperCAmelCase_					:Optional[Any]      			=      1
				UpperCAmelCase_					:int      			=      alpha[..., 1]
				UpperCAmelCase_					:Optional[int]      			=      -alpha[..., 0]
				UpperCAmelCase_					:int      			=      alpha

				UpperCAmelCase_					:List[str]      			=      default_r.compose(Rigid(Rotation(rot_mats=__snake_case  ),    __snake_case  )  )

				UpperCAmelCase_					:List[str]      			=      all_frames[..., 5]
				UpperCAmelCase_					:str      			=      all_frames[..., 6]
				UpperCAmelCase_					:List[Any]      			=      all_frames[..., 7]

				UpperCAmelCase_					:Tuple      			=      all_frames[..., 4]
				UpperCAmelCase_					:Optional[Any]      			=      chia_frame_to_bb.compose(__snake_case  )
				UpperCAmelCase_					:Optional[Any]      			=      chia_frame_to_bb.compose(__snake_case  )
				UpperCAmelCase_					:Union[str, Any]      			=      chia_frame_to_bb.compose(__snake_case  )

				UpperCAmelCase_					:List[str]      			=      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_					:Any      			=      r[..., None].compose(__snake_case  )

				return all_frames_to_global





def 				a (						__snake_case     :				Rigid,    __snake_case     :				torch.Tensor,    __snake_case     :				torch.Tensor,    __snake_case     :				torch.Tensor,    __snake_case     :				torch.Tensor,    __snake_case     :				torch.Tensor,    ):



				'''simple docstring'''





				UpperCAmelCase_					:Optional[Any]      			=      group_idx[aatype, ...]

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

				# [*, N, 14, 8]
				UpperCAmelCase_					:Dict      			=      r[..., None, :] * group_mask_one_hot

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

				# [*, N, 14, 1]
				UpperCAmelCase_					:List[Any]      			=      atom_mask[aatype, ...].unsqueeze(-1  )

				# [*, N, 14, 3]
				UpperCAmelCase_					:List[Any]      			=      lit_positions[aatype, ...]
				UpperCAmelCase_					:Optional[int]      			=      t_atoms_to_global.apply(__snake_case  )
				UpperCAmelCase_					:int      			=      pred_positions * atom_mask

				return pred_positions


