"""
Module: libfmp.c4.c4s2_threshold
Author: Meinard Müller
License: The MIT license, https://opensource.org/licenses/MIT
This file is part of the FMP Notebooks (https://www.audiolabs-erlangen.de/FMP)
"""
import numpy as np
[docs]def threshold_matrix_relative(S, thresh_rel=0.2, details=False):
"""Treshold matrix in a relative fashion
Notebook: C4/C4S2_SSM-Thresholding.ipynb
Args:
S (np.ndarray): Input matrix
thresh_rel (float): Relative treshold (Default value = 0.2)
details (bool): Print details on thresholding procedure (Default value = False)
Returns:
S_thresh (np.ndarray): Thresholded matrix
thresh_abs (float): Absolute threshold used for thresholding
"""
S_thresh = np.copy(S)
num_cells_below_thresh = int(np.round(S_thresh.size*(1-thresh_rel)))
values_sorted = np.sort(S_thresh.flatten('F'))
thresh_abs = values_sorted[num_cells_below_thresh]
S_thresh[S_thresh < thresh_abs] = 0
if details:
print('thresh_rel=%0.2f, thresh_abs=%d, total_num_cells=%d, num_cells_below_thresh=%d, ' %
(thresh_rel, thresh_abs, S_thresh.size, num_cells_below_thresh))
return S_thresh, thresh_abs
[docs]def threshold_matrix(S, thresh, strategy='absolute', scale=False, penalty=0.0, binarize=False):
"""Treshold matrix in a relative fashion
Notebook: C4/C4S2_SSM-Thresholding.ipynb
Args:
S (np.ndarray): Input matrix
thresh (float or list): Treshold (meaning depends on strategy)
strategy (str): Thresholding strategy ('absolute', 'relative', 'local') (Default value = 'absolute')
scale (bool): If scale=True, then scaling of positive values to range [0,1] (Default value = False)
penalty (float): Set values below treshold to value specified (Default value = 0.0)
binarize (bool): Binarizes final matrix (positive: 1; otherwise: 0) (Default value = False)
Returns:
S_thresh (np.ndarray): Thresholded matrix
"""
if np.min(S) < 0:
raise Exception('All entries of the input matrix must be nonnegative')
S_thresh = np.copy(S)
N, M = S.shape
num_cells = N * M
if strategy == 'absolute':
thresh_abs = thresh
S_thresh[S_thresh < thresh] = 0
if strategy == 'relative':
thresh_rel = thresh
num_cells_below_thresh = int(np.round(S_thresh.size*(1-thresh_rel)))
if num_cells_below_thresh < num_cells:
values_sorted = np.sort(S_thresh.flatten('F'))
thresh_abs = values_sorted[num_cells_below_thresh]
S_thresh[S_thresh < thresh_abs] = 0
else:
S_thresh = np.zeros([N, M])
if strategy == 'local':
thresh_rel_row = thresh[0]
thresh_rel_col = thresh[1]
S_binary_row = np.zeros([N, M])
num_cells_row_below_thresh = int(np.round(M * (1-thresh_rel_row)))
for n in range(N):
row = S[n, :]
values_sorted = np.sort(row)
if num_cells_row_below_thresh < M:
thresh_abs = values_sorted[num_cells_row_below_thresh]
S_binary_row[n, :] = (row >= thresh_abs)
S_binary_col = np.zeros([N, M])
num_cells_col_below_thresh = int(np.round(N * (1-thresh_rel_col)))
for m in range(M):
col = S[:, m]
values_sorted = np.sort(col)
if num_cells_col_below_thresh < N:
thresh_abs = values_sorted[num_cells_col_below_thresh]
S_binary_col[:, m] = (col >= thresh_abs)
S_thresh = S * S_binary_row * S_binary_col
if scale:
cell_val_zero = np.where(S_thresh == 0)
cell_val_pos = np.where(S_thresh > 0)
if len(cell_val_pos[0]) == 0:
min_value = 0
else:
min_value = np.min(S_thresh[cell_val_pos])
max_value = np.max(S_thresh)
# print('min_value = ', min_value, ', max_value = ', max_value)
if max_value > min_value:
S_thresh = np.divide((S_thresh - min_value), (max_value - min_value))
if len(cell_val_zero[0]) > 0:
S_thresh[cell_val_zero] = penalty
else:
print('Condition max_value > min_value is voliated: output zero matrix')
if binarize:
S_thresh[S_thresh > 0] = 1
S_thresh[S_thresh < 0] = 0
return S_thresh