acoular 23.6__py3-none-any.whl → 24.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- acoular/__init__.py +2 -2
- acoular/configuration.py +37 -1
- acoular/environments.py +15 -9
- acoular/fastFuncs.py +199 -472
- acoular/fbeamform.py +168 -109
- acoular/grids.py +33 -114
- acoular/sources.py +77 -3
- acoular/spectra.py +2 -2
- acoular/tbeamform.py +15 -8
- acoular/tests/reference_data/BeamformerBaseFalse1.npy +0 -0
- acoular/tests/reference_data/BeamformerBaseFalse2.npy +0 -0
- acoular/tests/reference_data/BeamformerBaseFalse3.npy +0 -0
- acoular/tests/reference_data/BeamformerBaseFalse4.npy +0 -0
- acoular/tests/reference_data/BeamformerBaseTrue1.npy +0 -0
- acoular/tests/reference_data/BeamformerBaseTrue2.npy +0 -0
- acoular/tests/reference_data/BeamformerBaseTrue3.npy +0 -0
- acoular/tests/reference_data/BeamformerBaseTrue4.npy +0 -0
- acoular/tests/reference_data/BeamformerCMFLassoLarsBIC.npy +0 -0
- acoular/tests/reference_data/BeamformerCMFNNLS.npy +0 -0
- acoular/tests/reference_data/BeamformerCleantSqTraj.npy +0 -0
- acoular/tests/reference_data/BeamformerCleantTraj.npy +0 -0
- acoular/tests/reference_data/BeamformerEigFalse1.npy +0 -0
- acoular/tests/reference_data/BeamformerEigFalse2.npy +0 -0
- acoular/tests/reference_data/BeamformerEigFalse3.npy +0 -0
- acoular/tests/reference_data/BeamformerEigFalse4.npy +0 -0
- acoular/tests/reference_data/BeamformerEigTrue1.npy +0 -0
- acoular/tests/reference_data/BeamformerEigTrue2.npy +0 -0
- acoular/tests/reference_data/BeamformerEigTrue3.npy +0 -0
- acoular/tests/reference_data/BeamformerEigTrue4.npy +0 -0
- acoular/tests/reference_data/BeamformerGIB.npy +0 -0
- acoular/tests/reference_data/BeamformerSODIX.npy +0 -0
- acoular/tests/reference_data/FiltFiltOctave__.npy +0 -0
- acoular/tests/reference_data/FiltFiltOctave_band_100_0_fraction_Thirdoctave_.npy +0 -0
- acoular/tests/reference_data/FiltFreqWeight_weight_A_.npy +0 -0
- acoular/tests/reference_data/FiltFreqWeight_weight_C_.npy +0 -0
- acoular/tests/reference_data/FiltFreqWeight_weight_Z_.npy +0 -0
- acoular/tests/reference_data/FiltOctave__.npy +0 -0
- acoular/tests/reference_data/FiltOctave_band_100_0_fraction_Thirdoctave_.npy +0 -0
- acoular/tests/reference_data/Filter__.npy +0 -0
- acoular/tests/reference_data/OctaveFilterBank__.npy +0 -0
- acoular/tests/reference_data/TimeAverage__.npy +0 -0
- acoular/tests/reference_data/TimeCumAverage__.npy +0 -0
- acoular/tests/reference_data/TimeExpAverage_weight_F_.npy +0 -0
- acoular/tests/reference_data/TimeExpAverage_weight_I_.npy +0 -0
- acoular/tests/reference_data/TimeExpAverage_weight_S_.npy +0 -0
- acoular/tests/reference_data/TimeInOut__.npy +0 -0
- acoular/tests/reference_data/TimePower__.npy +0 -0
- acoular/tests/reference_data/TimeReverse__.npy +0 -0
- acoular/tests/test_beamformer_results.py +39 -8
- acoular/tests/test_grid.py +92 -0
- acoular/tests/test_integrate.py +102 -0
- acoular/tests/test_tprocess.py +52 -0
- acoular/tests/test_traj_beamformer_results.py +2 -2
- acoular/tfastfuncs.py +24 -25
- acoular/tools.py +144 -2
- acoular/tprocess.py +91 -102
- acoular/version.py +2 -2
- acoular-24.3.dist-info/METADATA +181 -0
- {acoular-23.6.dist-info → acoular-24.3.dist-info}/RECORD +62 -25
- {acoular-23.6.dist-info → acoular-24.3.dist-info}/WHEEL +1 -1
- {acoular-23.6.dist-info → acoular-24.3.dist-info}/licenses/LICENSE +1 -1
- acoular/tests/reference_data/BeamformerCMF.npy +0 -0
- acoular-23.6.dist-info/METADATA +0 -82
- {acoular-23.6.dist-info → acoular-24.3.dist-info}/licenses/AUTHORS.rst +0 -0
acoular/tests/test_tprocess.py
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import unittest
|
|
2
|
+
from os.path import join
|
|
3
|
+
import re
|
|
2
4
|
import numpy as np
|
|
3
5
|
from acoular import (
|
|
4
6
|
config,
|
|
@@ -6,11 +8,46 @@ from acoular import (
|
|
|
6
8
|
WNoiseGenerator,
|
|
7
9
|
PointSource,
|
|
8
10
|
MicGeom,
|
|
11
|
+
MaskedTimeSamples,
|
|
9
12
|
tools
|
|
10
13
|
)
|
|
14
|
+
from acoular.tprocess import *
|
|
15
|
+
|
|
16
|
+
WRITE_NEW_REFERENCE_DATA = False
|
|
11
17
|
|
|
12
18
|
config.global_caching = "none"
|
|
19
|
+
datafile = join('..','..','examples','example_data.h5')
|
|
20
|
+
t1 = MaskedTimeSamples(name=datafile)
|
|
21
|
+
t1.start = 0 # first sample, default
|
|
22
|
+
t1.stop = 500 # last valid sample = 15999
|
|
23
|
+
invalid = list(range(4,64)) # list of invalid channels
|
|
24
|
+
t1.invalid_channels = invalid # use four channels
|
|
25
|
+
|
|
26
|
+
# these are tested
|
|
27
|
+
test_list = (
|
|
28
|
+
"TimeInOut()",
|
|
29
|
+
"TimePower()",
|
|
30
|
+
"TimeAverage()",
|
|
31
|
+
"TimeCumAverage()",
|
|
32
|
+
"TimeReverse()",
|
|
33
|
+
"Filter()",
|
|
34
|
+
"FiltFiltOctave(band = 100.0, fraction = 'Third octave')",
|
|
35
|
+
"FiltFiltOctave()",
|
|
36
|
+
"FiltOctave(band = 100.0, fraction = 'Third octave')",
|
|
37
|
+
"FiltOctave()",
|
|
38
|
+
"TimeExpAverage(weight = 'F')",
|
|
39
|
+
"TimeExpAverage(weight = 'S')",
|
|
40
|
+
"TimeExpAverage(weight = 'I')",
|
|
41
|
+
"FiltFreqWeight(weight = 'A')",
|
|
42
|
+
"FiltFreqWeight(weight = 'C')",
|
|
43
|
+
"FiltFreqWeight(weight = 'Z')",
|
|
44
|
+
"OctaveFilterBank()"
|
|
45
|
+
)
|
|
13
46
|
|
|
47
|
+
def fname(s):
|
|
48
|
+
"""converts string to file name removing unsafe characters"""
|
|
49
|
+
s1 = re.sub(r'[,.()=]', '_', s)
|
|
50
|
+
return re.sub(r'[/\\:*?"<>|\' ]', '', s1)
|
|
14
51
|
|
|
15
52
|
class TprocessTest(unittest.TestCase):
|
|
16
53
|
"""
|
|
@@ -34,5 +71,20 @@ class TprocessTest(unittest.TestCase):
|
|
|
34
71
|
REF = np.convolve(np.squeeze(KERNEL), np.squeeze(SIG[:,i]))
|
|
35
72
|
np.testing.assert_allclose(np.squeeze(RES[:,i]), REF, rtol=1e-5, atol=1e-8)
|
|
36
73
|
|
|
74
|
+
#@unittest.skip
|
|
75
|
+
def test_tprocess_results(self):
|
|
76
|
+
"""compare results with reference results"""
|
|
77
|
+
for s in test_list:
|
|
78
|
+
b = eval(s)
|
|
79
|
+
with self.subTest(s):
|
|
80
|
+
name = join('reference_data',f'{fname(s)}.npy')
|
|
81
|
+
b.source = t1
|
|
82
|
+
# compute with block size 64 and add some extra
|
|
83
|
+
actual_data = tools.return_result(b, nmax=70, num=64)
|
|
84
|
+
if WRITE_NEW_REFERENCE_DATA:
|
|
85
|
+
np.save(name,actual_data)
|
|
86
|
+
ref_data = np.load(name)
|
|
87
|
+
np.testing.assert_allclose(actual_data, ref_data, rtol=1e-5, atol=1e-8)
|
|
88
|
+
|
|
37
89
|
if __name__ == "__main__":
|
|
38
90
|
unittest.main()
|
|
@@ -145,7 +145,7 @@ class BeamformerTimeTest(unittest.TestCase):
|
|
|
145
145
|
if WRITE_NEW_REFERENCE_DATA:
|
|
146
146
|
np.save(name,actual_data)
|
|
147
147
|
ref_data = np.load(name)
|
|
148
|
-
np.testing.assert_allclose(actual_data, ref_data, rtol=
|
|
148
|
+
np.testing.assert_allclose(actual_data, ref_data, rtol=5e-5, atol=5e-6)
|
|
149
149
|
|
|
150
150
|
def test_beamformer_time_result(self):
|
|
151
151
|
"""compare results of time beamformers with fixed focus against previous
|
|
@@ -157,7 +157,7 @@ class BeamformerTimeTest(unittest.TestCase):
|
|
|
157
157
|
if WRITE_NEW_REFERENCE_DATA:
|
|
158
158
|
np.save(name,actual_data)
|
|
159
159
|
ref_data = np.load(name)
|
|
160
|
-
np.testing.assert_allclose(actual_data, ref_data, rtol=
|
|
160
|
+
np.testing.assert_allclose(actual_data, ref_data, rtol=5e-5, atol=5e-6)
|
|
161
161
|
|
|
162
162
|
|
|
163
163
|
if __name__ == '__main__':
|
acoular/tfastfuncs.py
CHANGED
|
@@ -13,14 +13,11 @@ import numpy as np
|
|
|
13
13
|
cachedOption = True # if True: saves the numba func as compiled func in sub directory
|
|
14
14
|
fastOption = True # fastmath options
|
|
15
15
|
|
|
16
|
-
@nb.njit([(nb.float64[
|
|
16
|
+
@nb.njit([(nb.float64[:,::1], nb.int64[:,::1], nb.float64[:,::1], nb.float64[:,::1], nb.float64[:,::1], nb.float64[:,::1])],
|
|
17
17
|
cache=True, parallel=True, fastmath=True)
|
|
18
18
|
def _delayandsum4(data, offsets, ifactor2, steeramp, out, autopower):
|
|
19
19
|
""" Performs one time step of delay and sum with output and additional autopower removal
|
|
20
|
-
|
|
21
|
-
**Note**: parallel could be set to true, but unless the number of gridpoints gets huge, it
|
|
22
|
-
will be _slower_ in parallel mode
|
|
23
|
-
|
|
20
|
+
|
|
24
21
|
Parameters
|
|
25
22
|
----------
|
|
26
23
|
data : float64[nSamples, nMics]
|
|
@@ -38,26 +35,25 @@ def _delayandsum4(data, offsets, ifactor2, steeramp, out, autopower):
|
|
|
38
35
|
"""
|
|
39
36
|
gridsize, numchannels = offsets.shape
|
|
40
37
|
num = out.shape[0]
|
|
38
|
+
ZERO = data.dtype.type(0.)
|
|
39
|
+
ONE = data.dtype.type(1.)
|
|
41
40
|
for n in nb.prange(num):
|
|
42
41
|
for gi in nb.prange(gridsize):
|
|
43
|
-
out[n,gi] =
|
|
44
|
-
autopower[n,gi] =
|
|
42
|
+
out[n,gi] = ZERO
|
|
43
|
+
autopower[n,gi] = ZERO
|
|
45
44
|
for mi in range(numchannels):
|
|
46
|
-
ind =
|
|
47
|
-
r = (data[ind+n,mi] * (1
|
|
48
|
-
+ data[ind+n+1,mi] * ifactor2[
|
|
45
|
+
ind = (gi,mi)
|
|
46
|
+
r = (data[offsets[ind]+n,mi] * (1.-ifactor2[ind]) \
|
|
47
|
+
+ data[offsets[ind]+n+1,mi] * ifactor2[ind]) * steeramp[ind]
|
|
49
48
|
out[n,gi] += r
|
|
50
49
|
autopower[n,gi] += r*r
|
|
51
50
|
|
|
52
|
-
@nb.njit([(nb.float32[
|
|
53
|
-
(nb.float64[
|
|
51
|
+
@nb.njit([(nb.float32[:,::1], nb.int32[:,:,::1], nb.float32[:,:,::1], nb.float32[:,:,::1], nb.float32[:,::1], nb.float32[:,::1]),
|
|
52
|
+
(nb.float64[:,::1], nb.int64[:,:,::1], nb.float64[:,:,::1], nb.float64[:,:,::1], nb.float64[:,::1], nb.float64[:,::1])],
|
|
54
53
|
cache=True, parallel=True, fastmath=True)
|
|
55
54
|
def _delayandsum5(data, offsets, ifactor2, steeramp, out, autopower):
|
|
56
55
|
""" Performs one time step of delay and sum with output and additional autopower removal
|
|
57
|
-
|
|
58
|
-
**Note**: parallel could be set to true, but unless the number of gridpoints gets huge, it
|
|
59
|
-
will be _slower_ in parallel mode
|
|
60
|
-
|
|
56
|
+
|
|
61
57
|
Parameters
|
|
62
58
|
----------
|
|
63
59
|
data : float64[nSamples, nMics]
|
|
@@ -75,13 +71,15 @@ def _delayandsum5(data, offsets, ifactor2, steeramp, out, autopower):
|
|
|
75
71
|
"""
|
|
76
72
|
num, gridsize, numchannels = offsets.shape
|
|
77
73
|
num = out.shape[0]
|
|
74
|
+
#ZERO = data.dtype.type(0.)
|
|
75
|
+
ONE = data.dtype.type(1.)
|
|
78
76
|
for n in nb.prange(num):
|
|
79
77
|
for gi in nb.prange(gridsize):
|
|
80
78
|
out[n,gi] = 0
|
|
81
79
|
autopower[n,gi] = 0
|
|
82
80
|
for mi in range(numchannels):
|
|
83
|
-
ind = offsets[n,gi,mi]
|
|
84
|
-
r = (data[ind,mi] * (
|
|
81
|
+
ind = offsets[n,gi,mi]+n
|
|
82
|
+
r = (data[ind,mi] * (ONE - ifactor2[n,gi,mi]) \
|
|
85
83
|
+ data[ind+1,mi] * ifactor2[n,gi,mi]) * steeramp[n,gi,mi]
|
|
86
84
|
out[n,gi] += r
|
|
87
85
|
autopower[n,gi] += r*r
|
|
@@ -145,18 +143,19 @@ def _steer_IV(rm, r0, amp):
|
|
|
145
143
|
for mi in nb.prange(numchannels):
|
|
146
144
|
amp[n,gi,mi] = np.divide(Nr,rm[n,gi,mi]*rm2)
|
|
147
145
|
|
|
148
|
-
@nb.njit([(nb.float32[
|
|
149
|
-
(nb.float64[
|
|
146
|
+
@nb.njit([(nb.float32[:,:,::1], nb.float32, nb.float32[:,:,::1], nb.int32[:,:,::1]),
|
|
147
|
+
(nb.float64[:,:,::1], nb.float64, nb.float64[:,:,::1], nb.int64[:,:,::1])],
|
|
150
148
|
cache=True, parallel=True, fastmath=True)
|
|
151
|
-
def _delays(rm,
|
|
149
|
+
def _delays(rm, c, interp2, index):
|
|
152
150
|
num, gridsize, numchannels = rm.shape
|
|
151
|
+
invc = 1/c
|
|
152
|
+
intt = index.dtype.type
|
|
153
153
|
for n in nb.prange(num):
|
|
154
154
|
for gi in nb.prange(gridsize):
|
|
155
155
|
for mi in nb.prange(numchannels):
|
|
156
|
-
delays
|
|
157
|
-
index[n,gi,mi] =
|
|
158
|
-
interp2[n,gi,mi] = delays
|
|
159
|
-
|
|
156
|
+
delays = invc * rm[n,gi,mi]
|
|
157
|
+
index[n,gi,mi] = intt(delays)
|
|
158
|
+
interp2[n,gi,mi] = delays - nb.int64(delays)
|
|
160
159
|
|
|
161
160
|
@nb.njit([(nb.float32[:,:,:], nb.float32[:,:,:], nb.int32[:,:,:]),
|
|
162
161
|
(nb.float64[:,:,:], nb.float64[:,:,:], nb.int64[:,:,:])],
|
acoular/tools.py
CHANGED
|
@@ -9,6 +9,7 @@ Implements tools for Acoular.
|
|
|
9
9
|
.. autosummary::
|
|
10
10
|
:toctree: generated/
|
|
11
11
|
|
|
12
|
+
MetricEvaluator
|
|
12
13
|
return_result
|
|
13
14
|
spherical_hn1
|
|
14
15
|
get_radiation_angles
|
|
@@ -17,13 +18,154 @@ Implements tools for Acoular.
|
|
|
17
18
|
bardata
|
|
18
19
|
"""
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
from numpy import array, concatenate, newaxis, where,arctan2,sqrt,pi,mod,zeros
|
|
21
|
+
import acoular as ac
|
|
22
|
+
from numpy import array, concatenate, newaxis, where,arctan2,sqrt,pi,mod,zeros,\
|
|
23
|
+
complex128, ones, inf, minimum, empty
|
|
22
24
|
from numpy.linalg import norm
|
|
23
25
|
from numpy.ma import masked_where
|
|
24
26
|
from .spectra import synthetic
|
|
27
|
+
from traits.api import Bool, CArray, HasPrivateTraits, Instance, Property, Any
|
|
25
28
|
|
|
26
29
|
from scipy.special import spherical_yn, spherical_jn, sph_harm
|
|
30
|
+
from scipy.spatial.distance import cdist
|
|
31
|
+
from copy import copy
|
|
32
|
+
|
|
33
|
+
class MetricEvaluator(HasPrivateTraits):
|
|
34
|
+
"""Evaluate the reconstruction performance of source mapping methods.
|
|
35
|
+
|
|
36
|
+
This class can be used to calculate the following performance metrics
|
|
37
|
+
according to Herold and Sarradj (2017):
|
|
38
|
+
* Specific level error
|
|
39
|
+
* Overall level error
|
|
40
|
+
* Inverse level error
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
#: an array of shape=(nf,ng) containing the squared sound pressure data of the
|
|
44
|
+
#: source mapping. (nf: number of frequencies, ng: number of grid points)
|
|
45
|
+
data = CArray(shape=(None,None),
|
|
46
|
+
desc="Contains the calculated squared sound pressure values in Pa**2.")
|
|
47
|
+
|
|
48
|
+
#: an array of shape=(nf,ns) containing the squared sound pressure data of the
|
|
49
|
+
#: ground-truth sources. (nf: number of frequencies, ns: number of sources)
|
|
50
|
+
target_data = CArray(shape=(None,None),
|
|
51
|
+
desc="Contains the ground-truth squared sound pressure values in Pa**2.")
|
|
52
|
+
|
|
53
|
+
#: :class:`~acoular.grids.Grid`-derived object that provides the grid locations
|
|
54
|
+
#: for the calculated source mapping data.
|
|
55
|
+
grid = Instance(ac.Grid,
|
|
56
|
+
desc="Grid instance that belongs to the calculated data")
|
|
57
|
+
|
|
58
|
+
#: :class:`~acoular.grids.Grid`-derived object that provides the grid locations
|
|
59
|
+
#: for the ground-truth data.
|
|
60
|
+
target_grid = Instance(ac.Grid,
|
|
61
|
+
desc="Grid instance that belongs to the ground-truth data")
|
|
62
|
+
|
|
63
|
+
#: sector type. Currently only circular sectors are supported.
|
|
64
|
+
sector = Instance(ac.CircSector, default=ac.CircSector(),)
|
|
65
|
+
|
|
66
|
+
#: if set True: use shrink integration area if two sources are closer
|
|
67
|
+
#: than 2*r. The radius of the integration area is then set to half the
|
|
68
|
+
#: distance between the two sources.
|
|
69
|
+
adaptive_sector_size = Bool(True,
|
|
70
|
+
desc="adaptive integration area")
|
|
71
|
+
|
|
72
|
+
#: if set `True`, the same amplitude can be assigned to multiple targets if
|
|
73
|
+
#: the integration area overlaps. If set `False`, the amplitude is assigned
|
|
74
|
+
#: to the first target and the other targets are ignored.
|
|
75
|
+
multi_assignment = Bool(True,
|
|
76
|
+
desc="if set True, the same amplitude can be assigned to multiple targets if the integration area overlaps")
|
|
77
|
+
|
|
78
|
+
#: returns the determined sector sizes for each ground-truth source position
|
|
79
|
+
sectors = Property()
|
|
80
|
+
|
|
81
|
+
def _validate_shapes(self):
|
|
82
|
+
if self.data.shape[0] != self.target_data.shape[0]:
|
|
83
|
+
raise ValueError("data and target_data must have the same number of frequencies!")
|
|
84
|
+
if self.data.shape[1] != self.grid.size:
|
|
85
|
+
raise ValueError("data and grid must have the same number of grid points!")
|
|
86
|
+
if self.target_data.shape[1] != self.target_grid.size:
|
|
87
|
+
raise ValueError("target_data and target_grid must have the same number of grid points!")
|
|
88
|
+
|
|
89
|
+
def _get_sector_radii(self):
|
|
90
|
+
ns = self.target_data.shape[1]
|
|
91
|
+
radii = ones(ns)*self.sector.r
|
|
92
|
+
if self.adaptive_sector_size:
|
|
93
|
+
locs = self.target_grid.gpos.T
|
|
94
|
+
intersrcdist = cdist(locs, locs)
|
|
95
|
+
intersrcdist[intersrcdist == 0] = inf
|
|
96
|
+
intersrcdist = intersrcdist.min(0)/2
|
|
97
|
+
radii = minimum(radii,intersrcdist)
|
|
98
|
+
return radii
|
|
99
|
+
|
|
100
|
+
def _get_sectors(self):
|
|
101
|
+
"""Returns a list of CircSector objects for each target location."""
|
|
102
|
+
r = self._get_sector_radii()
|
|
103
|
+
ns = self.target_data.shape[1]
|
|
104
|
+
sectors = []
|
|
105
|
+
for i in range(ns):
|
|
106
|
+
loc = self.target_grid.gpos[:,i]
|
|
107
|
+
sector = copy(self.sector)
|
|
108
|
+
sector.r = r[i]
|
|
109
|
+
sector.x = loc[0]
|
|
110
|
+
sector.y = loc[1]
|
|
111
|
+
sectors.append(sector)
|
|
112
|
+
return sectors
|
|
113
|
+
|
|
114
|
+
def _integrate_sectors(self):
|
|
115
|
+
"""Integrates over target sectors.
|
|
116
|
+
|
|
117
|
+
Returns
|
|
118
|
+
-------
|
|
119
|
+
array (num_freqs,num_sources)
|
|
120
|
+
returns the integrated Pa**2 values for each sector
|
|
121
|
+
"""
|
|
122
|
+
sectors = self.sectors
|
|
123
|
+
results = empty(shape=self.target_data.shape)
|
|
124
|
+
for f in range(self.target_data.shape[0]):
|
|
125
|
+
data = self.data[f]
|
|
126
|
+
for i in range(self.target_data.shape[1]):
|
|
127
|
+
sector = sectors[i]
|
|
128
|
+
results[f,i] = ac.integrate(data,self.grid,sector)
|
|
129
|
+
if not self.multi_assignment:
|
|
130
|
+
indices = self.grid.subdomain(sector)
|
|
131
|
+
data[indices] = 0 # set values to zero (can not be assigned again)
|
|
132
|
+
return results
|
|
133
|
+
|
|
134
|
+
def get_overall_level_error(self):
|
|
135
|
+
"""Returns the overall level error (Herold and Sarradj, 2017).
|
|
136
|
+
|
|
137
|
+
Returns
|
|
138
|
+
-------
|
|
139
|
+
numpy.array
|
|
140
|
+
overall level error of shape=(nf,)
|
|
141
|
+
"""
|
|
142
|
+
self._validate_shapes()
|
|
143
|
+
return ac.L_p(self.data.sum(axis=1)) - ac.L_p(self.target_data.sum(axis=1))
|
|
144
|
+
|
|
145
|
+
def get_specific_level_error(self):
|
|
146
|
+
"""Returns the specific level error (Herold and Sarradj, 2017).
|
|
147
|
+
|
|
148
|
+
Returns
|
|
149
|
+
-------
|
|
150
|
+
numpy.array
|
|
151
|
+
specific level error of shape=(nf,ns). nf: number of frequencies, ns: number of sources
|
|
152
|
+
"""
|
|
153
|
+
self._validate_shapes()
|
|
154
|
+
sector_result = self._integrate_sectors()
|
|
155
|
+
return ac.L_p(sector_result) - ac.L_p(self.target_data)
|
|
156
|
+
|
|
157
|
+
def get_inverse_level_error(self):
|
|
158
|
+
"""Returns the inverse level error (Herold and Sarradj, 2017).
|
|
159
|
+
|
|
160
|
+
Returns
|
|
161
|
+
-------
|
|
162
|
+
numpy.array
|
|
163
|
+
inverse level error of shape=(nf,1)
|
|
164
|
+
"""
|
|
165
|
+
self._validate_shapes()
|
|
166
|
+
sector_result = self._integrate_sectors()
|
|
167
|
+
return ac.L_p(sector_result.sum(axis=1)) - ac.L_p(self.data.sum(axis=1))
|
|
168
|
+
|
|
27
169
|
|
|
28
170
|
|
|
29
171
|
def return_result(source, nmax=-1, num=128):
|