Source code for zounds.spectral.weighting

import numpy as np
from .frequencyadaptive import FrequencyAdaptive


class FrequencyWeighting(object):
    def __init__(self):
        super(FrequencyWeighting, self).__init__()

    def __numpy_ufunc__(self, *args, **kwargs):
        raise NotImplementedError()

    def _wdata(self, scale):
        return np.ones(len(scale))

    def weights(self, other):
        """
        Compute weights, given a scale or time-frequency representation
        :param other: A time-frequency representation, or a scale
        :return: a numpy array of weights
        """
        try:
            return self._wdata(other)
        except AttributeError:
            frequency_dim = other.dimensions[-1]
            return self._wdata(frequency_dim.scale)

    def _get_factors(self, arr):
        for i, d in enumerate(arr.dimensions):
            try:
                weights = self._wdata(d.scale)
                expanded = d.weights(weights, arr, i)
                return expanded
            except AttributeError as e:
                pass

        raise ValueError('arr must have a frequency dimension')

    def __array_ufunc__(self, ufunc, method, *args, **kwargs):
        if ufunc == np.multiply or ufunc == np.divide:
            if args[0] is self:
                first_arg = self._get_factors(args[1])
                second_arg = args[1]
            else:
                first_arg = args[0]
                second_arg = self._get_factors(args[0])
            return getattr(ufunc, method)(first_arg, second_arg, **kwargs)
        else:
            return NotImplemented


[docs]class AWeighting(FrequencyWeighting): """ An A-weighting (https://en.wikipedia.org/wiki/A-weighting) that can be applied to a frequency axis via multiplication. Examples: >>> from zounds import ArrayWithUnits, GeometricScale >>> from zounds import FrequencyDimension, AWeighting >>> import numpy as np >>> scale = GeometricScale(20, 20000, 0.05, 10) >>> raw = np.ones(len(scale)) >>> arr = ArrayWithUnits(raw, [FrequencyDimension(scale)]) >>> arr * AWeighting() ArrayWithUnits([ 1. , 18.3172567 , 31.19918106, 40.54760374, 47.15389876, 51.1554151 , 52.59655479, 52.24516649, 49.39906912, 42.05409205]) """ def __init__(self): super(AWeighting, self).__init__() def _wdata(self, scale): center_frequencies = np.array(list(scale.center_frequencies)) ** 2 a = (12200 ** 2) * (center_frequencies ** 2) b = center_frequencies + (20.6 ** 2) c = center_frequencies + (107.7 ** 2) d = center_frequencies + (737.9 ** 2) e = center_frequencies + (12200 ** 2) f = a / (b * np.sqrt(c * d) * e) result = 2.0 + (20 * np.log10(f)) return 1 + (result - np.min(result))