Module wavelet.util.utility
Utility functions
Expand source code
"""Utility functions"""
from math import log, pow
import numpy as np
from wavelet.exceptions import WaveletException
def getExponent(value):
"""Returns the exponent for the data Ex: 8 -> 3 [2 ^ 3]"""
return int(log(value) / log(2.))
def scalb(f, scaleFactor):
"""Return the scale for the factor"""
return f * pow(2., scaleFactor)
def isPowerOf2(number):
"""Checks if the length is equal to the power of 2"""
power = getExponent(number)
result = scalb(1., power)
return result == number
def decomposeArbitraryLength(number):
"""
Returns decomposition for the numbers
Examples
--------
number 42 : 32 + 8 + 2
powers : 5, 3, 1
"""
if number < 1:
raise WaveletException("Number should be greater than 1")
tempArray = list()
current = number
position = 0
while current >= 1.:
power = getExponent(current)
tempArray.append(power)
current = current - scalb(1., power)
position += 1
return tempArray[:position]
def threshold(data, value, substitute=0):
"""Soft thresholding"""
magnitude = np.absolute(data)
with np.errstate(divide='ignore'):
# divide by zero okay as np.inf values get clipped, so ignore warning.
thresholded = (1 - value / magnitude)
thresholded.clip(min=0, max=None, out=thresholded)
thresholded = data * thresholded
if substitute == 0:
return thresholded
else:
cond = np.less(magnitude, value)
return np.where(cond, substitute, thresholded)
def mad(data):
"""
Median Absolute Deviation: a "Robust" version of standard deviation.
Indices variability of the sample.
https://en.wikipedia.org/wiki/Median_absolute_deviation
"""
data = np.ma.array(data).compressed()
med = np.median(data)
return np.median(np.abs(data - med))
def snr(data, axis=0, ddof=0):
"""
Signal to Noise ratio
simply given by mean / standard deviation
"""
a = np.asanyarray(data)
m = a.mean(axis)
sd = a.std(axis=axis, ddof=ddof)
return np.where(sd == 0, 0, m / sd)
def amp_to_db(S, ref=1.0, min_value=1e-5, top_db=80.0):
"""
Convert an amplitude spectrogram to dB-scaled spectrogram.
This is equivalent to ``power_to_db(S**2)``
Parameters
----------
S : array_like
input amplitude
ref : scalar
If scalar, the amplitude `abs(S)` is scaled relative to `ref`:
`20 * log10(S / ref)`.
Zeros in the output correspond to positions where `S == ref`.
min_value : float > 0 [scalar]
minimum threshold for `S` and `ref`
top_db : float >= 0 [scalar]
threshold the output at `top_db` below the peak:
``max(20 * log10(S)) - top_db``
Returns
-------
S_db : np.ndarray
``S`` measured in dB
"""
S = np.asarray(S)
magnitude = np.abs(S)
ref_value = np.abs(ref)
power = np.square(magnitude, out=magnitude)
return power_to_db(power, ref=ref_value ** 2, min_value=min_value ** 2,
top_db=top_db)
def power_to_db(S, ref=1.0, min_value=1e-10, top_db=80.0):
"""
Convert a power spectrogram (amplitude squared) to decibel (dB) units
This computes the scaling ``10 * log10(S / ref)`` in a numerically
stable way.
Parameters
----------
S : np.ndarray
input power
ref : scalar
If scalar, the amplitude `abs(S)` is scaled relative to `ref`:
`10 * log10(S / ref)`.
Zeros in the output correspond to positions where `S == ref`.
min_value : float > 0 [scalar]
minimum threshold for `abs(S)` and `ref`
top_db : float >= 0 [scalar]
threshold the output at `top_db` below the peak:
``max(10 * log10(S)) - top_db``
Returns
-------
S_db : np.ndarray
``S_db ~= 10 * log10(S) - 10 * log10(ref)``
"""
S = np.asarray(S)
if min_value <= 0:
raise Exception('min must be strictly positive')
if np.issubdtype(S.dtype, np.complexfloating):
magnitude = np.abs(S)
else:
magnitude = S
ref_value = np.abs(ref)
log_spec = 10.0 * np.log10(np.maximum(min_value, magnitude))
log_spec -= 10.0 * np.log10(np.maximum(min_value, ref_value))
# scaling based on the top db
if top_db is not None:
if top_db < 0:
raise Exception('top_db must be non-negative')
log_spec = np.maximum(log_spec, log_spec.max() - top_db)
return log_spec
Functions
def amp_to_db(S, ref=1.0, min_value=1e-05, top_db=80.0)
-
Convert an amplitude spectrogram to dB-scaled spectrogram.
This is equivalent to
power_to_db(S**2)
Parameters
S
:array_like
- input amplitude
ref
:scalar
- If scalar, the amplitude
abs(S)
is scaled relative toref
:20 * log10(S / ref)
. Zeros in the output correspond to positions whereS == ref
. min_value
:float > 0 [scalar]
- minimum threshold for
S
andref
top_db
:float >= 0 [scalar]
- threshold the output at
top_db
below the peak:max(20 * log10(S)) - top_db
Returns
S_db
:np.ndarray
S
measured in dB
Expand source code
def amp_to_db(S, ref=1.0, min_value=1e-5, top_db=80.0): """ Convert an amplitude spectrogram to dB-scaled spectrogram. This is equivalent to ``power_to_db(S**2)`` Parameters ---------- S : array_like input amplitude ref : scalar If scalar, the amplitude `abs(S)` is scaled relative to `ref`: `20 * log10(S / ref)`. Zeros in the output correspond to positions where `S == ref`. min_value : float > 0 [scalar] minimum threshold for `S` and `ref` top_db : float >= 0 [scalar] threshold the output at `top_db` below the peak: ``max(20 * log10(S)) - top_db`` Returns ------- S_db : np.ndarray ``S`` measured in dB """ S = np.asarray(S) magnitude = np.abs(S) ref_value = np.abs(ref) power = np.square(magnitude, out=magnitude) return power_to_db(power, ref=ref_value ** 2, min_value=min_value ** 2, top_db=top_db)
def decomposeArbitraryLength(number)
-
Returns decomposition for the numbers
Examples
number 42 : 32 + 8 + 2 powers : 5, 3, 1
Expand source code
def decomposeArbitraryLength(number): """ Returns decomposition for the numbers Examples -------- number 42 : 32 + 8 + 2 powers : 5, 3, 1 """ if number < 1: raise WaveletException("Number should be greater than 1") tempArray = list() current = number position = 0 while current >= 1.: power = getExponent(current) tempArray.append(power) current = current - scalb(1., power) position += 1 return tempArray[:position]
def getExponent(value)
-
Returns the exponent for the data Ex: 8 -> 3 [2 ^ 3]
Expand source code
def getExponent(value): """Returns the exponent for the data Ex: 8 -> 3 [2 ^ 3]""" return int(log(value) / log(2.))
def isPowerOf2(number)
-
Checks if the length is equal to the power of 2
Expand source code
def isPowerOf2(number): """Checks if the length is equal to the power of 2""" power = getExponent(number) result = scalb(1., power) return result == number
def mad(data)
-
Median Absolute Deviation: a "Robust" version of standard deviation. Indices variability of the sample. https://en.wikipedia.org/wiki/Median_absolute_deviation
Expand source code
def mad(data): """ Median Absolute Deviation: a "Robust" version of standard deviation. Indices variability of the sample. https://en.wikipedia.org/wiki/Median_absolute_deviation """ data = np.ma.array(data).compressed() med = np.median(data) return np.median(np.abs(data - med))
def power_to_db(S, ref=1.0, min_value=1e-10, top_db=80.0)
-
Convert a power spectrogram (amplitude squared) to decibel (dB) units
This computes the scaling
10 * log10(S / ref)
in a numerically stable way.Parameters
S
:np.ndarray
- input power
ref
:scalar
- If scalar, the amplitude
abs(S)
is scaled relative toref
:10 * log10(S / ref)
. Zeros in the output correspond to positions whereS == ref
. min_value
:float > 0 [scalar]
- minimum threshold for
abs(S)
andref
top_db
:float >= 0 [scalar]
- threshold the output at
top_db
below the peak:max(10 * log10(S)) - top_db
Returns
S_db : np.ndarray
S_db ~= 10 * log10(S) - 10 * log10(ref)
Expand source code
def power_to_db(S, ref=1.0, min_value=1e-10, top_db=80.0): """ Convert a power spectrogram (amplitude squared) to decibel (dB) units This computes the scaling ``10 * log10(S / ref)`` in a numerically stable way. Parameters ---------- S : np.ndarray input power ref : scalar If scalar, the amplitude `abs(S)` is scaled relative to `ref`: `10 * log10(S / ref)`. Zeros in the output correspond to positions where `S == ref`. min_value : float > 0 [scalar] minimum threshold for `abs(S)` and `ref` top_db : float >= 0 [scalar] threshold the output at `top_db` below the peak: ``max(10 * log10(S)) - top_db`` Returns ------- S_db : np.ndarray ``S_db ~= 10 * log10(S) - 10 * log10(ref)`` """ S = np.asarray(S) if min_value <= 0: raise Exception('min must be strictly positive') if np.issubdtype(S.dtype, np.complexfloating): magnitude = np.abs(S) else: magnitude = S ref_value = np.abs(ref) log_spec = 10.0 * np.log10(np.maximum(min_value, magnitude)) log_spec -= 10.0 * np.log10(np.maximum(min_value, ref_value)) # scaling based on the top db if top_db is not None: if top_db < 0: raise Exception('top_db must be non-negative') log_spec = np.maximum(log_spec, log_spec.max() - top_db) return log_spec
def scalb(f, scaleFactor)
-
Return the scale for the factor
Expand source code
def scalb(f, scaleFactor): """Return the scale for the factor""" return f * pow(2., scaleFactor)
def snr(data, axis=0, ddof=0)
-
Signal to Noise ratio simply given by mean / standard deviation
Expand source code
def snr(data, axis=0, ddof=0): """ Signal to Noise ratio simply given by mean / standard deviation """ a = np.asanyarray(data) m = a.mean(axis) sd = a.std(axis=axis, ddof=ddof) return np.where(sd == 0, 0, m / sd)
def threshold(data, value, substitute=0)
-
Soft thresholding
Expand source code
def threshold(data, value, substitute=0): """Soft thresholding""" magnitude = np.absolute(data) with np.errstate(divide='ignore'): # divide by zero okay as np.inf values get clipped, so ignore warning. thresholded = (1 - value / magnitude) thresholded.clip(min=0, max=None, out=thresholded) thresholded = data * thresholded if substitute == 0: return thresholded else: cond = np.less(magnitude, value) return np.where(cond, substitute, thresholded)