# Path: echotorch/utils/error_measures.py
# def nrmse(outputs, targets):
#     """
#     Normalized root-mean square error
#     :param outputs: Module's outputs
#     :param targets: Target signal to be learned
#     :return: Normalized root-mean square deviation
#     """
#     # Flatten tensors
#     outputs = outputs.view(outputs.nelement())
#     targets = targets.view(targets.nelement())
# 
#     # Check dim
#     if outputs.size() != targets.size():
#         raise ValueError(u"Ouputs and targets tensors don have the same number of elements")
#     # end if
# 
#     # Normalization with N-1
#     var = torch.std(targets) ** 2
# 
#     # Error
#     error = (targets - outputs) ** 2
# 
#     # Return
#     return float(math.sqrt(torch.mean(error) / var))
# 
# def generalized_squared_cosine(Sa, Ua, Sb, Ub):
#     """
#     Generalized square cosine
#     :param Sa:
#     :param Ua:
#     :param Sb:
#     :param Ub:
#     :return:
#     """
#     # Diag
#     Sa = torch.diag(Sa)
#     Sb = torch.diag(Sb)
# 
#     # Compute Va and Vb
#     Va = torch.sqrt(Sa).mm(Ua.t())
#     Vb = Ub.mm(torch.sqrt(Sb))
# 
#     # Vab
#     Vab = Va.mm(Vb)
# 
#     # Num
#     num = torch.pow(torch.norm(Vab), 2)
# 
#     # Den
#     den = torch.norm(torch.diag(Sa), p=2) * torch.norm(torch.diag(Sb), p=2)
# 
#     return num / den


import torch
import numpy as np
import numpy.linalg as lin
from .error_measures import nrmse, generalized_squared_cosine
from scipy.interpolate import interp1d
    max_index = torch.argmax(-phasematches)
    # Matching phase
    y_aligned = y_int[np.arange(max_index, max_index + interpolation_rate * p_length, interpolation_rate)]

    # Original phase
    original_phase = np.ceil(max_index / interpolation_rate)

    # Error after alignment
    error_aligned = error_measure(y_aligned.reshape(1, -1), p.reshape(1, -1))

    return p, y_aligned, original_phase, error_aligned
# end find_phase_shift


# Compute similarity matrix
def compute_similarity_matrix(svd_list):
    """
    Compute similarity matrix
    :param svd_list:
    :return:
    """
    # N samples
    n_samples = len(svd_list)

    # Similarity matrix
    sim_matrix = torch.zeros(n_samples, n_samples)

    # For each combinasion
    for i, (Sa, Ua) in enumerate(svd_list):
        for j, (Sb, Ub) in enumerate(svd_list):

# Path: echotorch/utils/error_measures.py
# def nrmse(outputs, targets):
#     """
#     Normalized root-mean square error
#     :param outputs: Module's outputs
#     :param targets: Target signal to be learned
#     :return: Normalized root-mean square deviation
#     """
#     # Flatten tensors
#     outputs = outputs.view(outputs.nelement())
#     targets = targets.view(targets.nelement())
# 
#     # Check dim
#     if outputs.size() != targets.size():
#         raise ValueError(u"Ouputs and targets tensors don have the same number of elements")
#     # end if
# 
#     # Normalization with N-1
#     var = torch.std(targets) ** 2
# 
#     # Error
#     error = (targets - outputs) ** 2
# 
#     # Return
#     return float(math.sqrt(torch.mean(error) / var))
# 
# def generalized_squared_cosine(Sa, Ua, Sb, Ub):
#     """
#     Generalized square cosine
#     :param Sa:
#     :param Ua:
#     :param Sb:
#     :param Ub:
#     :return:
#     """
#     # Diag
#     Sa = torch.diag(Sa)
#     Sb = torch.diag(Sb)
# 
#     # Compute Va and Vb
#     Va = torch.sqrt(Sa).mm(Ua.t())
#     Vb = Ub.mm(torch.sqrt(Sb))
# 
#     # Vab
#     Vab = Va.mm(Vb)
# 
#     # Num
#     num = torch.pow(torch.norm(Vab), 2)
# 
#     # Den
#     den = torch.norm(torch.diag(Sa), p=2) * torch.norm(torch.diag(Sb), p=2)
# 
#     return num / den


# Path: echotorch/utils/utility_functions.py
import torch
import numpy as np
import numpy.linalg as lin
from .error_measures import nrmse, generalized_squared_cosine
from scipy.interpolate import interp1d

    max_index = torch.argmax(-phasematches)
    # Matching phase
    y_aligned = y_int[np.arange(max_index, max_index + interpolation_rate * p_length, interpolation_rate)]

    # Original phase
    original_phase = np.ceil(max_index / interpolation_rate)

    # Error after alignment
    error_aligned = error_measure(y_aligned.reshape(1, -1), p.reshape(1, -1))

    return p, y_aligned, original_phase, error_aligned
# end find_phase_shift


# Compute similarity matrix
def compute_similarity_matrix(svd_list):
    """
    Compute similarity matrix
    :param svd_list:
    :return:
    """
    # N samples
    n_samples = len(svd_list)

    # Similarity matrix
    sim_matrix = torch.zeros(n_samples, n_samples)

    # For each combinasion
    for i, (Sa, Ua) in enumerate(svd_list):
        for j, (Sb, Ub) in enumerate(svd_list):

            sim_matrix[i, j] = generalized_squared_cosine(Sa, Ua, Sb, Ub)