from typing import Dict

import numpy as np
import torch

from . import residue_constants as rc
from .tensor_utils import tensor_tree_map, tree_map






def __lowerCAmelCase			(							UpperCamelCase__    )     ->   Dict[str, torch.Tensor]:
    __lowerCamelCase          =  []
    __lowerCamelCase          =  []
    __lowerCamelCase          =  []

    for rt in rc.restypes:
        __lowerCamelCase          =  rc.restype_name_to_atomaa_names[rc.restype_atoa[rt]]
        restype_atomaa_to_atomaa_list.append([(rc.atom_order[name] if name else 0) for name in atom_names]    )
        __lowerCamelCase          =  {name: i for i, name in enumerate(_UpperCAmelCase    )}
        restype_atomaa_to_atomaa_list.append(
            [(atom_name_to_idxaa[name] if name in atom_name_to_idxaa else 0) for name in rc.atom_types]    )

        restype_atomaa_mask_list.append([(1.0 if name else 0.0) for name in atom_names]    )

    # Add dummy mapping for restype 'UNK'
    restype_atomaa_to_atomaa_list.append([0] * 14    )
    restype_atomaa_to_atomaa_list.append([0] * 37    )
    restype_atomaa_mask_list.append([0.0] * 14    )

    __lowerCamelCase          =  torch.tensor(
        _UpperCAmelCase    ,  dtype=torch.intaa    ,  device=protein['''aatype'''].device    ,  )
    __lowerCamelCase          =  torch.tensor(
        _UpperCAmelCase    ,  dtype=torch.intaa    ,  device=protein['''aatype'''].device    ,  )
    __lowerCamelCase          =  torch.tensor(
        _UpperCAmelCase    ,  dtype=torch.floataa    ,  device=protein['''aatype'''].device    ,  )
    __lowerCamelCase          =  protein['aatype'].to(torch.long    )

    # create the mapping for (residx, atom14) --> atom37, i.e. an array
    # with shape (num_res, 14) containing the atom37 indices for this protein
    __lowerCamelCase          =  restype_atomaa_to_atomaa[protein_aatype]
    __lowerCamelCase          =  restype_atomaa_mask[protein_aatype]

    __lowerCamelCase          =  residx_atomaa_mask
    __lowerCamelCase          =  residx_atomaa_to_atomaa.long()

    # create the gather indices for mapping back
    __lowerCamelCase          =  restype_atomaa_to_atomaa[protein_aatype]
    __lowerCamelCase          =  residx_atomaa_to_atomaa.long()

    # create the corresponding mask
    __lowerCamelCase          =  torch.zeros([21, 37]    ,  dtype=torch.floataa    ,  device=protein['''aatype'''].device    )
    for restype, restype_letter in enumerate(rc.restypes    ):
        __lowerCamelCase          =  rc.restype_atoa[restype_letter]
        __lowerCamelCase          =  rc.residue_atoms[restype_name]
        for atom_name in atom_names:
            __lowerCamelCase          =  rc.atom_order[atom_name]
            __lowerCamelCase          =  1

    __lowerCamelCase          =  restype_atomaa_mask[protein_aatype]
    __lowerCamelCase          =  residx_atomaa_mask

    return protein






def __lowerCAmelCase			(							UpperCamelCase__    )     ->   Dict[str, np.ndarray]:
    __lowerCamelCase          =  tree_map(lambda UpperCamelCase__    : torch.tensor(_UpperCAmelCase    ,  device=batch['''aatype'''].device    )    ,  _UpperCAmelCase    ,  np.ndarray    )
    __lowerCamelCase          =  tensor_tree_map(lambda UpperCamelCase__    : np.array(_UpperCAmelCase    )    ,  make_atomaa_masks(_UpperCAmelCase    )    )
    return out

'''simple docstring'''




def __lowerCAmelCase			(							UpperCamelCase__    ,  UpperCamelCase__    ,  UpperCamelCase__    )     ->   float:
    if principal <= 0:
        raise Exception('''Principal borrowed must be > 0'''    )
    if rate_per_annum < 0:
        raise Exception('''Rate of interest must be >= 0'''    )
    if years_to_repay <= 0 or not isinstance(UpperCamelCase__    ,  UpperCamelCase__    ):
        raise Exception('''Years to repay must be an integer > 0'''    )

    # Yearly rate is divided by 12 to get monthly rate
    __lowerCamelCase          =  rate_per_annum / 12

    # Years to repay is multiplied by 12 to get number of payments as payment is monthly
    __lowerCamelCase          =  years_to_repay * 12

    return (
        principal
        * rate_per_month
        * (1 + rate_per_month) ** number_of_payments
        / ((1 + rate_per_month) ** number_of_payments - 1)
    )


if __name__ == "__main__":
  import doctest

  doctest.testmod()
