o
    sik$                     @   s   d dl Zd dlZd dlZd dlmZ g dZedg dZdddZ	dd	d
Z
dddddZddddddZdd Z		dddddZ		dddZdS )    N)perm)get_snr	input_sxr
output_sxrSXRsdrsirsnrFc                 C   s   t jt | |   ||dS )Naxiskeepdims)npsumabsconj)xr   r    r   U/home/ubuntu/.local/lib/python3.10/site-packages/pb_bss_eval/evaluation/sxr_module.py
get_energy   s   r   c                 C   sH   t | } t | rt j| jd | jd  ||dS t j| d ||dS )N   r   )r   arrayiscomplexobjmeanrealimag)Xr   r   r   r   r   !get_variance_for_zero_mean_signal   s   

 r   r   c                C   s.   t | ||d}t |||d}dt||  S )a  
    Return SNR of time signals or STFT signals in dB.
    You can use any input dimension. It will always create the mean SNR of all
    channels, frames, ...

    The SNR in time domain or STFT domain is almost equal.

    Args:
        X: Signal of target image.
        N: Signal of noise image.
        axis:
        keepdims:

    Returns:
        SNR of time signals or STFT signals in dB.

    >>> get_snr([1, 2, 3], [1, 2, 3])
    0.0
    r   
   )r   r   log10)r   Nr   r   power_Xpower_Nr   r   r   r      s   r   T)r   inplacec                C   sF   |du rt | ||dd}d||  d  }|r||9 }dS | || fS )a4  
    Set the SNR of two input images by rescaling the noise signal in place.

    This decision was made, because a quantization error should not deteriorate
    the target signal.

    TODO: Multi-Source
    The single source SNR is the ratio of each source to the noise channel.
    Multi-source environments are not yet implemented.

    Args:
        X: STFT-signal of target image.
        N: STFT-signal of noise image (will be modified in place).
        snr: Single source SNR of STFT signals in dB.
        current_snr:
        axis:
        inplace:
    NTr   r      )r   )r   r    r
   current_snrr   r#   factorr   r   r   set_snr3   s   r'   c                 C   sD   t jdd dt | |  }W d   |S 1 sw   Y  |S )zf Calculate signal to `X` ratio

    :param S: Signal power
    :param X: X power
    :return: SXR
    ignore)divider   N)r   errstater   )Sr   resultr   r   r   _sxrR   s   
r-   )return_dictc                   s  | j \}}}||f|j ksJ ||f| j |j f|dk s!J | j |dk s*J | j t| dd}t||f}	t|dd}
t|D ]!}t|D ] tj| fddt|D |f dd|	 |f< qGqA|rrdd ||	|
fD \}}	}
t||	|
 }t||	}t||
}|rtj|dd}tj|dd}tj|dd}|r|d	u r|||d
S t|t	r|d ||d ||d |iS t
|t|||S )a   Calculate input SXR values according to Tran Vu.

    The SXR definition is inspired by E. Vincent but the
    exact procedure as in his paper is not used. Dang Hai Tran Vu
    recommends this approach. Talk to Lukas Drude for details.

    Take the clean images and the noise at the sensors after applying a
    room impulse response and before mixing.

    :param images: Array of unmixed but reverberated speech in time domain
    :type images: np.ndarray with #speakers x #sensors x #samples
    :param noise: Array of ground truth noise
    :type noise: np.ndarray with #sensors x #samples
    :param average_sources: Logical if SXR is average of speakers
    :type average_sources: bool
    :param return_dict: specifies if the returned value is a list or a dict.
                        If return_dict is a str, it is the prefix for the
                        dict keys (i.e. 'input_').
    :type return_dict: bool or str

    :return: SDR, SIR, SNR or {'sdr': SDR, 'sir': SIR, 'snr': SNR}
    r      r   c                    s   g | ]}| kr|qS r   r   ).0nkr   r   
<listcomp>   s    zinput_sxr.<locals>.<listcomp>r   c                 S   s   g | ]	}t j|d dqS )r0   r1   )r   r   )r2   powerr   r   r   r6      s    Tr   r   r	   r
   )shaper   r   zerosranger   r-   r   
isinstancestr	TypeErrorResultTuple)imagesnoiseaverage_sourcesaverage_channelsr.   KDTr+   Ir    dSDRSIRSNRr   r4   r   r   ^   sB    $


r   c                    s  | j \}}}|j ||fksJ | j |j f|dk s!J | j |j f|dk s-J | j |j ft| dd t|dd}tttjt||dj t|||fks\J j t|||ft	j d }tj d D ]t
 fddt|D |< qkt|}	|	 }
t	|}t	|}t|D ]!} ||
| f ||< t
tj dd|
| f |dd||< q||
 }t||| }t||}t||}|rt|}t|}t|}|d	u r|d	u r|||d
S t|tr|d ||d ||d |iS t|t|||S )a8   Calculate output SXR values.

    The SXR definition is inspired by E. Vincent but the
    exact procedure as in his paper is not used. Dang Hai Tran Vu
    recommends this approach. Talk to Lukas Drude for details.

    The output signal of the system under test can be decomposed in
    contributions due to the speakers and noise. The two input signals
    are the processed images and noise by the complete separation
    system.

    Use the mixed signals to run your algorithm. Save the estimated separation
    parameters (i.e. beamforming vectors, gain functions, ...) and apply the
    algorithm with the fixed parameters to the clean images and ground truth
    noise separately. Evaluate the results with this function to obtain
    intrusive SXR measures.

    :param image_contribution: Put each of the clean images into the
      separation algorithm with fixed parameters. The output of the separation
      algorithm can now be used as `image_contribution`.
    :type image_contribution: #source_speakers x #target_speakers x #samples
    :param noise_contribution: Put the ground truth noise into the separation
      algorithm with fixed parameters. The output is `noise_contribution`.
    :type noise_contribution: #target_speakers x #samples
    :param average_sources: Scalar logical if SXR is average of speakers;
      optional (default: true). If set to true, SXR-values are scalars.
    :param return_dict: specifies if the returned value is a list or a dict.
                        If return_dict is a str, it is the prefix for the
                        dict keys
    :type return_dict: bool or str

    :return SDR: #source_speakers vector of Signal to Distortion Ratios
    :return SIR: #source_speakers vector of Signal to Interference Ratios
    :return SNR: #source_speakers vector of Signal to Noise Ratios

    r   r0   r1   )rr   c                    s    g | ]} ||f f qS r   r   )r2   k_sourcer+   all_target_selectionspr   r   r6      s    zoutput_sxr.<locals>.<listcomp>NTr   r   r	   r
   )r8   r   r   r   list	itertoolspermutationsr:   r   r9   r   argmaxdeleter-   r   r;   r<   r=   r>   )image_contributionnoise_contributionrA   r.   K_sourceK_targetsamplesr    mutual_powermax_idx	selectionSSIIrL   NNrH   rI   rJ   r   rM   r   r      sb   '










r   )NF)N)TT)TF)numpyr   collectionsrQ   scipy.specialr   __all__
namedtupler>   r   r   r   r'   r-   r   r   r   r   r   r   <module>   s&    

	J