acoular 24.3__py3-none-any.whl → 24.7__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 +119 -54
- acoular/calib.py +29 -38
- acoular/configuration.py +132 -82
- acoular/demo/__init__.py +10 -4
- acoular/demo/acoular_demo.py +73 -55
- acoular/environments.py +270 -264
- acoular/fastFuncs.py +366 -196
- acoular/fbeamform.py +1797 -1934
- acoular/grids.py +504 -548
- acoular/h5cache.py +74 -83
- acoular/h5files.py +159 -142
- acoular/internal.py +13 -14
- acoular/microphones.py +57 -53
- acoular/sdinput.py +57 -53
- acoular/signals.py +180 -178
- acoular/sources.py +920 -724
- acoular/spectra.py +353 -363
- acoular/tbeamform.py +416 -416
- acoular/tfastfuncs.py +180 -104
- acoular/tools/__init__.py +25 -0
- acoular/tools/aiaa.py +185 -0
- acoular/tools/helpers.py +189 -0
- acoular/tools/metrics.py +165 -0
- acoular/tprocess.py +1240 -1182
- acoular/traitsviews.py +513 -501
- acoular/trajectory.py +50 -52
- acoular/version.py +5 -6
- acoular/xml/minidsp_uma-16.xml +20 -0
- acoular/xml/{minidsp_uma16.xml → minidsp_uma-16_mirrored.xml} +3 -0
- {acoular-24.3.dist-info → acoular-24.7.dist-info}/METADATA +58 -39
- acoular-24.7.dist-info/RECORD +50 -0
- {acoular-24.3.dist-info → acoular-24.7.dist-info}/WHEEL +1 -1
- acoular-24.7.dist-info/licenses/LICENSE +28 -0
- acoular/fileimport.py +0 -380
- acoular/nidaqimport.py +0 -273
- acoular/tests/reference_data/BeamformerBase.npy +0 -0
- 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/BeamformerCapon.npy +0 -0
- acoular/tests/reference_data/BeamformerClean.npy +0 -0
- acoular/tests/reference_data/BeamformerCleansc.npy +0 -0
- acoular/tests/reference_data/BeamformerCleant.npy +0 -0
- acoular/tests/reference_data/BeamformerCleantSq.npy +0 -0
- acoular/tests/reference_data/BeamformerCleantSqTraj.npy +0 -0
- acoular/tests/reference_data/BeamformerCleantTraj.npy +0 -0
- acoular/tests/reference_data/BeamformerDamas.npy +0 -0
- acoular/tests/reference_data/BeamformerDamasPlus.npy +0 -0
- acoular/tests/reference_data/BeamformerEig.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/BeamformerFunctional.npy +0 -0
- acoular/tests/reference_data/BeamformerGIB.npy +0 -0
- acoular/tests/reference_data/BeamformerGridlessOrth.npy +0 -0
- acoular/tests/reference_data/BeamformerMusic.npy +0 -0
- acoular/tests/reference_data/BeamformerOrth.npy +0 -0
- acoular/tests/reference_data/BeamformerSODIX.npy +0 -0
- acoular/tests/reference_data/BeamformerTime.npy +0 -0
- acoular/tests/reference_data/BeamformerTimeSq.npy +0 -0
- acoular/tests/reference_data/BeamformerTimeSqTraj.npy +0 -0
- acoular/tests/reference_data/BeamformerTimeTraj.npy +0 -0
- acoular/tests/reference_data/Environment.npy +0 -0
- acoular/tests/reference_data/Example1_numerical_values_testsum.h5 +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/GeneralFlowEnvironment.npy +0 -0
- acoular/tests/reference_data/OctaveFilterBank__.npy +0 -0
- acoular/tests/reference_data/OpenJet.npy +0 -0
- acoular/tests/reference_data/PointSource.npy +0 -0
- acoular/tests/reference_data/PowerSpectra_csm.npy +0 -0
- acoular/tests/reference_data/PowerSpectra_ev.npy +0 -0
- acoular/tests/reference_data/RotatingFlow.npy +0 -0
- acoular/tests/reference_data/SlotJet.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/reference_data/UniformFlowEnvironment.npy +0 -0
- acoular/tests/reference_data/beamformer_traj_time_data.h5 +0 -0
- acoular/tests/run_tests.sh +0 -18
- acoular/tests/run_tests_osx.sh +0 -16
- acoular/tests/test.npy +0 -0
- acoular/tests/test_beamformer_results.py +0 -213
- acoular/tests/test_classes.py +0 -60
- acoular/tests/test_digest.py +0 -125
- acoular/tests/test_environments.py +0 -73
- acoular/tests/test_example1.py +0 -124
- acoular/tests/test_grid.py +0 -92
- acoular/tests/test_integrate.py +0 -102
- acoular/tests/test_signals.py +0 -60
- acoular/tests/test_sources.py +0 -65
- acoular/tests/test_spectra.py +0 -38
- acoular/tests/test_timecache.py +0 -35
- acoular/tests/test_tprocess.py +0 -90
- acoular/tests/test_traj_beamformer_results.py +0 -164
- acoular/tests/unsupported/SpeedComparison/OvernightTestcasesBeamformer_nMics32_nGridPoints100_nFreqs4_nTrials10.png +0 -0
- acoular/tests/unsupported/SpeedComparison/cythonBeamformer.pyx +0 -237
- acoular/tests/unsupported/SpeedComparison/mainForCython.py +0 -103
- acoular/tests/unsupported/SpeedComparison/mainForParallelJit.py +0 -143
- acoular/tests/unsupported/SpeedComparison/setupCythonOpenMP.py +0 -63
- acoular/tests/unsupported/SpeedComparison/sharedFunctions.py +0 -153
- acoular/tests/unsupported/SpeedComparison/timeOverNMics_AllImportantMethods.png +0 -0
- acoular/tests/unsupported/SpeedComparison/timeOverNMics_faverage.png +0 -0
- acoular/tests/unsupported/SpeedComparison/vglOptimierungFAverage.py +0 -204
- acoular/tests/unsupported/SpeedComparison/vglOptimierungGaussSeidel.py +0 -182
- acoular/tests/unsupported/SpeedComparison/vglOptimierungR_BEAMFULL_INVERSE.py +0 -764
- acoular/tests/unsupported/SpeedComparison/vglOptimierungR_BEAM_OS.py +0 -231
- acoular/tests/unsupported/SpeedComparison/whatsFastestWayFor_absASquared.py +0 -48
- acoular/tests/unsupported/functionalBeamformer.py +0 -123
- acoular/tests/unsupported/precisionTest.py +0 -153
- acoular/tests/unsupported/validationOfBeamformerFuncsPOSTAcoularIntegration.py +0 -254
- acoular/tests/unsupported/validationOfBeamformerFuncsPREeAcoularIntegration.py +0 -531
- acoular/tools.py +0 -422
- acoular-24.3.dist-info/RECORD +0 -148
- acoular-24.3.dist-info/licenses/LICENSE +0 -29
- {acoular-24.3.dist-info → acoular-24.7.dist-info}/licenses/AUTHORS.rst +0 -0
acoular/tfastfuncs.py
CHANGED
|
@@ -1,173 +1,249 @@
|
|
|
1
|
-
#
|
|
2
|
-
#pylint: disable-msg=E0611, E1101, C0103, R0901, R0902, R0903, R0904, W0232
|
|
3
|
-
#------------------------------------------------------------------------------
|
|
1
|
+
# ------------------------------------------------------------------------------
|
|
4
2
|
# Copyright (c) Acoular Development Team.
|
|
5
|
-
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
"""
|
|
3
|
+
# ------------------------------------------------------------------------------
|
|
4
|
+
"""Contains NUMBA accelerated functions for time-domain beamformers."""
|
|
5
|
+
|
|
9
6
|
import numba as nb
|
|
10
7
|
import numpy as np
|
|
11
8
|
|
|
12
9
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
10
|
+
@nb.njit(
|
|
11
|
+
[
|
|
12
|
+
(
|
|
13
|
+
nb.float64[:, ::1],
|
|
14
|
+
nb.int64[:, ::1],
|
|
15
|
+
nb.float64[:, ::1],
|
|
16
|
+
nb.float64[:, ::1],
|
|
17
|
+
nb.float64[:, ::1],
|
|
18
|
+
nb.float64[:, ::1],
|
|
19
|
+
),
|
|
20
|
+
],
|
|
21
|
+
cache=True,
|
|
22
|
+
parallel=True,
|
|
23
|
+
fastmath=True,
|
|
24
|
+
)
|
|
18
25
|
def _delayandsum4(data, offsets, ifactor2, steeramp, out, autopower):
|
|
19
|
-
"""
|
|
20
|
-
|
|
26
|
+
"""Performs one time step of delay and sum with output and additional autopower removal.
|
|
27
|
+
|
|
21
28
|
Parameters
|
|
22
29
|
----------
|
|
23
|
-
data : float64[nSamples, nMics]
|
|
30
|
+
data : float64[nSamples, nMics]
|
|
24
31
|
The time history for all channels.
|
|
25
|
-
offsets : int64[gridSize, nMics]
|
|
32
|
+
offsets : int64[gridSize, nMics]
|
|
26
33
|
Indices for each grid point and each channel.
|
|
27
|
-
ifactor2: float64[gridSize, nMics]
|
|
34
|
+
ifactor2: float64[gridSize, nMics]
|
|
28
35
|
Second interpolation factor, the first one is computed internally.
|
|
29
|
-
steeramp: float64[gridSize, nMics]
|
|
30
|
-
Amplitude factor from steering vector.
|
|
31
|
-
|
|
36
|
+
steeramp: float64[gridSize, nMics]
|
|
37
|
+
Amplitude factor from steering vector.
|
|
38
|
+
|
|
32
39
|
Returns
|
|
33
40
|
-------
|
|
34
41
|
None : as the inputs out and autopower get overwritten.
|
|
42
|
+
|
|
35
43
|
"""
|
|
36
44
|
gridsize, numchannels = offsets.shape
|
|
37
45
|
num = out.shape[0]
|
|
38
|
-
|
|
39
|
-
ONE = data.dtype.type(1.)
|
|
46
|
+
zero_constant = data.dtype.type(0.0)
|
|
40
47
|
for n in nb.prange(num):
|
|
41
48
|
for gi in nb.prange(gridsize):
|
|
42
|
-
out[n,gi] =
|
|
43
|
-
autopower[n,gi] =
|
|
49
|
+
out[n, gi] = zero_constant
|
|
50
|
+
autopower[n, gi] = zero_constant
|
|
44
51
|
for mi in range(numchannels):
|
|
45
|
-
ind = (gi,mi)
|
|
46
|
-
r = (
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
ind = (gi, mi)
|
|
53
|
+
r = (
|
|
54
|
+
data[offsets[ind] + n, mi] * (1.0 - ifactor2[ind]) + data[offsets[ind] + n + 1, mi] * ifactor2[ind]
|
|
55
|
+
) * steeramp[ind]
|
|
56
|
+
out[n, gi] += r
|
|
57
|
+
autopower[n, gi] += r * r
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@nb.njit(
|
|
61
|
+
[
|
|
62
|
+
(
|
|
63
|
+
nb.float32[:, ::1],
|
|
64
|
+
nb.int32[:, :, ::1],
|
|
65
|
+
nb.float32[:, :, ::1],
|
|
66
|
+
nb.float32[:, :, ::1],
|
|
67
|
+
nb.float32[:, ::1],
|
|
68
|
+
nb.float32[:, ::1],
|
|
69
|
+
),
|
|
70
|
+
(
|
|
71
|
+
nb.float64[:, ::1],
|
|
72
|
+
nb.int64[:, :, ::1],
|
|
73
|
+
nb.float64[:, :, ::1],
|
|
74
|
+
nb.float64[:, :, ::1],
|
|
75
|
+
nb.float64[:, ::1],
|
|
76
|
+
nb.float64[:, ::1],
|
|
77
|
+
),
|
|
78
|
+
],
|
|
79
|
+
cache=True,
|
|
80
|
+
parallel=True,
|
|
81
|
+
fastmath=True,
|
|
82
|
+
)
|
|
54
83
|
def _delayandsum5(data, offsets, ifactor2, steeramp, out, autopower):
|
|
55
|
-
"""
|
|
56
|
-
|
|
84
|
+
"""Performs one time step of delay and sum with output and additional autopower removal.
|
|
85
|
+
|
|
57
86
|
Parameters
|
|
58
87
|
----------
|
|
59
|
-
data : float64[nSamples, nMics]
|
|
88
|
+
data : float64[nSamples, nMics]
|
|
60
89
|
The time history for all channels.
|
|
61
|
-
offsets : int64[nBlockSamples, gridSize, nMics]
|
|
90
|
+
offsets : int64[nBlockSamples, gridSize, nMics]
|
|
62
91
|
Indices for each grid point and each channel.
|
|
63
|
-
ifactor2: float64[nBlockSamples,gridSize, nMics]
|
|
92
|
+
ifactor2: float64[nBlockSamples,gridSize, nMics]
|
|
64
93
|
Second interpolation factor, the first one is computed internally.
|
|
65
|
-
steeramp: float64[nBlockSamples,gridSize, nMics]
|
|
66
|
-
Amplitude factor from steering vector.
|
|
67
|
-
|
|
94
|
+
steeramp: float64[nBlockSamples,gridSize, nMics]
|
|
95
|
+
Amplitude factor from steering vector.
|
|
96
|
+
|
|
68
97
|
Returns
|
|
69
98
|
-------
|
|
70
99
|
None : as the inputs out and autopower get overwritten.
|
|
100
|
+
|
|
71
101
|
"""
|
|
72
102
|
num, gridsize, numchannels = offsets.shape
|
|
73
103
|
num = out.shape[0]
|
|
74
|
-
#ZERO = data.dtype.type(0.)
|
|
75
|
-
|
|
104
|
+
# ZERO = data.dtype.type(0.)
|
|
105
|
+
one_constant = data.dtype.type(1.0)
|
|
76
106
|
for n in nb.prange(num):
|
|
77
107
|
for gi in nb.prange(gridsize):
|
|
78
|
-
out[n,gi] = 0
|
|
79
|
-
autopower[n,gi] = 0
|
|
108
|
+
out[n, gi] = 0
|
|
109
|
+
autopower[n, gi] = 0
|
|
80
110
|
for mi in range(numchannels):
|
|
81
|
-
ind = offsets[n,gi,mi]+n
|
|
82
|
-
r = (
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
111
|
+
ind = offsets[n, gi, mi] + n
|
|
112
|
+
r = (
|
|
113
|
+
data[ind, mi] * (one_constant - ifactor2[n, gi, mi]) + data[ind + 1, mi] * ifactor2[n, gi, mi]
|
|
114
|
+
) * steeramp[
|
|
115
|
+
n,
|
|
116
|
+
gi,
|
|
117
|
+
mi,
|
|
118
|
+
]
|
|
119
|
+
out[n, gi] += r
|
|
120
|
+
autopower[n, gi] += r * r
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
@nb.njit(
|
|
124
|
+
[
|
|
125
|
+
(nb.float32[:, :, :], nb.float32[:, :], nb.float32[:, :, :]),
|
|
126
|
+
(nb.float64[:, :, :], nb.float64[:, :], nb.float64[:, :, :]),
|
|
127
|
+
],
|
|
128
|
+
cache=True,
|
|
129
|
+
parallel=True,
|
|
130
|
+
fastmath=True,
|
|
131
|
+
)
|
|
132
|
+
def _steer_I(rm, r0, amp): # noqa: ARG001, N802
|
|
91
133
|
num, gridsize, numchannels = rm.shape
|
|
92
|
-
amp[0,0,0] = 1.0/numchannels# to get the same type for rm2 as for rm
|
|
93
|
-
|
|
94
|
-
for n in nb.prange(num):
|
|
134
|
+
amp[0, 0, 0] = 1.0 / numchannels # to get the same type for rm2 as for rm
|
|
135
|
+
nr = amp[0, 0, 0]
|
|
136
|
+
for n in nb.prange(num):
|
|
95
137
|
for gi in nb.prange(gridsize):
|
|
96
138
|
for mi in nb.prange(numchannels):
|
|
97
|
-
amp[n,gi,mi] =
|
|
139
|
+
amp[n, gi, mi] = nr
|
|
140
|
+
|
|
98
141
|
|
|
99
|
-
@nb.njit(
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
142
|
+
@nb.njit(
|
|
143
|
+
[
|
|
144
|
+
(nb.float32[:, :, :], nb.float32[:, :], nb.float32[:, :, :]),
|
|
145
|
+
(nb.float64[:, :, :], nb.float64[:, :], nb.float64[:, :, :]),
|
|
146
|
+
],
|
|
147
|
+
cache=True,
|
|
148
|
+
parallel=True,
|
|
149
|
+
fastmath=True,
|
|
150
|
+
)
|
|
151
|
+
def _steer_II(rm, r0, amp): # noqa: N802
|
|
103
152
|
num, gridsize, numchannels = rm.shape
|
|
104
|
-
amp[0,0,0] = 1.0/numchannels# to get the same type for rm2 as for rm
|
|
105
|
-
|
|
106
|
-
for n in nb.prange(num):
|
|
153
|
+
amp[0, 0, 0] = 1.0 / numchannels # to get the same type for rm2 as for rm
|
|
154
|
+
nr = amp[0, 0, 0]
|
|
155
|
+
for n in nb.prange(num):
|
|
107
156
|
for gi in nb.prange(gridsize):
|
|
108
|
-
rm2 = np.divide(
|
|
157
|
+
rm2 = np.divide(nr, r0[n, gi])
|
|
109
158
|
for mi in nb.prange(numchannels):
|
|
110
|
-
amp[n,gi,mi] = rm[n,gi,mi]*rm2
|
|
159
|
+
amp[n, gi, mi] = rm[n, gi, mi] * rm2
|
|
111
160
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
161
|
+
|
|
162
|
+
@nb.njit(
|
|
163
|
+
[
|
|
164
|
+
(nb.float32[:, :, :], nb.float32[:, :], nb.float32[:, :, :]),
|
|
165
|
+
(nb.float64[:, :, :], nb.float64[:, :], nb.float64[:, :, :]),
|
|
166
|
+
],
|
|
167
|
+
cache=True,
|
|
168
|
+
parallel=True,
|
|
169
|
+
fastmath=True,
|
|
170
|
+
)
|
|
171
|
+
def _steer_III(rm, r0, amp): # noqa: N802
|
|
116
172
|
num, gridsize, numchannels = rm.shape
|
|
117
|
-
rm20 = rm[0,0,0]-rm[0,0,0]
|
|
118
|
-
rm1 = rm[0,0,0]/rm[0,0,0]
|
|
119
|
-
for n in nb.prange(num):
|
|
173
|
+
rm20 = rm[0, 0, 0] - rm[0, 0, 0] # to get the same type for rm2 as for rm
|
|
174
|
+
rm1 = rm[0, 0, 0] / rm[0, 0, 0]
|
|
175
|
+
for n in nb.prange(num):
|
|
120
176
|
for gi in nb.prange(gridsize):
|
|
121
177
|
rm2 = rm20
|
|
122
178
|
for mi in nb.prange(numchannels):
|
|
123
|
-
rm2 += np.divide(rm1,np.square(rm[n,gi,mi]))
|
|
124
|
-
rm2 *= r0[n,gi]
|
|
179
|
+
rm2 += np.divide(rm1, np.square(rm[n, gi, mi]))
|
|
180
|
+
rm2 *= r0[n, gi]
|
|
125
181
|
for mi in nb.prange(numchannels):
|
|
126
|
-
amp[n,gi,mi] = np.divide(rm1,rm[n,gi,mi]*rm2)
|
|
182
|
+
amp[n, gi, mi] = np.divide(rm1, rm[n, gi, mi] * rm2)
|
|
183
|
+
|
|
127
184
|
|
|
128
|
-
@nb.njit(
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
185
|
+
@nb.njit(
|
|
186
|
+
[
|
|
187
|
+
(nb.float32[:, :, :], nb.float32[:, :], nb.float32[:, :, :]),
|
|
188
|
+
(nb.float64[:, :, :], nb.float64[:, :], nb.float64[:, :, :]),
|
|
189
|
+
],
|
|
190
|
+
cache=True,
|
|
191
|
+
parallel=True,
|
|
192
|
+
fastmath=True,
|
|
193
|
+
)
|
|
194
|
+
def _steer_IV(rm, r0, amp): # noqa: ARG001, N802
|
|
132
195
|
num, gridsize, numchannels = rm.shape
|
|
133
|
-
amp[0,0,0] = np.sqrt(1.0/numchannels)# to get the same type for rm2 as for rm
|
|
134
|
-
|
|
135
|
-
rm1 = rm[0,0,0]/rm[0,0,0]
|
|
136
|
-
rm20 = rm[0,0,0]-rm[0,0,0]
|
|
137
|
-
for n in nb.prange(num):
|
|
196
|
+
amp[0, 0, 0] = np.sqrt(1.0 / numchannels) # to get the same type for rm2 as for rm
|
|
197
|
+
nr = amp[0, 0, 0]
|
|
198
|
+
rm1 = rm[0, 0, 0] / rm[0, 0, 0]
|
|
199
|
+
rm20 = rm[0, 0, 0] - rm[0, 0, 0] # to get the same type for rm2 as for rm
|
|
200
|
+
for n in nb.prange(num):
|
|
138
201
|
for gi in nb.prange(gridsize):
|
|
139
202
|
rm2 = rm20
|
|
140
203
|
for mi in nb.prange(numchannels):
|
|
141
|
-
rm2 += np.divide(rm1,np.square(rm[n,gi,mi]))
|
|
204
|
+
rm2 += np.divide(rm1, np.square(rm[n, gi, mi]))
|
|
142
205
|
rm2 = np.sqrt(rm2)
|
|
143
206
|
for mi in nb.prange(numchannels):
|
|
144
|
-
amp[n,gi,mi] = np.divide(
|
|
207
|
+
amp[n, gi, mi] = np.divide(nr, rm[n, gi, mi] * rm2)
|
|
208
|
+
|
|
145
209
|
|
|
146
|
-
@nb.njit(
|
|
147
|
-
|
|
148
|
-
|
|
210
|
+
@nb.njit(
|
|
211
|
+
[
|
|
212
|
+
(nb.float32[:, :, ::1], nb.float32, nb.float32[:, :, ::1], nb.int32[:, :, ::1]),
|
|
213
|
+
(nb.float64[:, :, ::1], nb.float64, nb.float64[:, :, ::1], nb.int64[:, :, ::1]),
|
|
214
|
+
],
|
|
215
|
+
cache=True,
|
|
216
|
+
parallel=True,
|
|
217
|
+
fastmath=True,
|
|
218
|
+
)
|
|
149
219
|
def _delays(rm, c, interp2, index):
|
|
150
220
|
num, gridsize, numchannels = rm.shape
|
|
151
|
-
invc = 1/c
|
|
221
|
+
invc = 1 / c
|
|
152
222
|
intt = index.dtype.type
|
|
153
|
-
for n in nb.prange(num):
|
|
223
|
+
for n in nb.prange(num):
|
|
154
224
|
for gi in nb.prange(gridsize):
|
|
155
225
|
for mi in nb.prange(numchannels):
|
|
156
|
-
delays = invc * rm[n,gi,mi]
|
|
157
|
-
index[n,gi,mi] = intt(delays)
|
|
158
|
-
interp2[n,gi,mi] = delays - nb.int64(delays)
|
|
226
|
+
delays = invc * rm[n, gi, mi]
|
|
227
|
+
index[n, gi, mi] = intt(delays)
|
|
228
|
+
interp2[n, gi, mi] = delays - nb.int64(delays)
|
|
159
229
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
230
|
+
|
|
231
|
+
@nb.njit(
|
|
232
|
+
[
|
|
233
|
+
(nb.float32[:, :, :], nb.float32[:, :, :], nb.int32[:, :, :]),
|
|
234
|
+
(nb.float64[:, :, :], nb.float64[:, :, :], nb.int64[:, :, :]),
|
|
235
|
+
],
|
|
236
|
+
cache=True,
|
|
237
|
+
parallel=True,
|
|
238
|
+
fastmath=True,
|
|
239
|
+
)
|
|
163
240
|
def _modf(delays, interp2, index):
|
|
164
241
|
num, gridsize, numchannels = delays.shape
|
|
165
|
-
for n in nb.prange(num):
|
|
242
|
+
for n in nb.prange(num):
|
|
166
243
|
for gi in nb.prange(gridsize):
|
|
167
244
|
for mi in nb.prange(numchannels):
|
|
168
|
-
index[n,gi,mi] = int(delays[n,gi,mi])
|
|
169
|
-
interp2[n,gi,mi] = delays[n,gi,mi] - index[n,gi,mi]
|
|
170
|
-
|
|
245
|
+
index[n, gi, mi] = int(delays[n, gi, mi])
|
|
246
|
+
interp2[n, gi, mi] = delays[n, gi, mi] - index[n, gi, mi]
|
|
171
247
|
|
|
172
248
|
|
|
173
249
|
if __name__ == '__main__':
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# ------------------------------------------------------------------------------
|
|
2
|
+
# Copyright (c) Acoular Development Team.
|
|
3
|
+
# ------------------------------------------------------------------------------
|
|
4
|
+
"""Useful tools for Acoular.
|
|
5
|
+
|
|
6
|
+
.. autosummary::
|
|
7
|
+
:toctree: generated/
|
|
8
|
+
|
|
9
|
+
aiaa
|
|
10
|
+
helpers
|
|
11
|
+
metrics
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from .aiaa import (
|
|
15
|
+
CsmAIAABenchmark,
|
|
16
|
+
MicAIAABenchmark,
|
|
17
|
+
TimeSamplesAIAABenchmark,
|
|
18
|
+
TriggerAIAABenchmark,
|
|
19
|
+
)
|
|
20
|
+
from .helpers import (
|
|
21
|
+
bardata,
|
|
22
|
+
barspectrum,
|
|
23
|
+
return_result,
|
|
24
|
+
)
|
|
25
|
+
from .metrics import MetricEvaluator
|
acoular/tools/aiaa.py
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# ------------------------------------------------------------------------------
|
|
2
|
+
# Copyright (c) Acoular Development Team.
|
|
3
|
+
# ------------------------------------------------------------------------------
|
|
4
|
+
"""Classes for importing AIAA Array Benchmarks
|
|
5
|
+
from . import aiaa
|
|
6
|
+
These classes allow importing data from HDF5 files following the specifications of
|
|
7
|
+
the AIAA microphone array methods benchmarking effort:
|
|
8
|
+
https://www-docs.b-tu.de/fg-akustik/public/veroeffentlichungen/ArrayMethodsFileFormatsR2P4Release.pdf .
|
|
9
|
+
|
|
10
|
+
The classes are derived from according Acoular classes so that they can be used directly within
|
|
11
|
+
the framework.
|
|
12
|
+
|
|
13
|
+
Examples
|
|
14
|
+
--------
|
|
15
|
+
>>> micgeom = MicAIAABenchmark(name='some_benchmarkdata.h5') # doctest: +SKIP
|
|
16
|
+
>>> timedata = TimeSamplesAIAABenchmark(name='some_benchmarkdata.h5') # doctest: +SKIP
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
.. autosummary::
|
|
20
|
+
:toctree: generated/
|
|
21
|
+
|
|
22
|
+
TimeSamplesAIAABenchmark
|
|
23
|
+
TriggerAIAABenchmark
|
|
24
|
+
CsmAIAABenchmark
|
|
25
|
+
MicAIAABenchmark
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
import contextlib
|
|
29
|
+
from os import path
|
|
30
|
+
|
|
31
|
+
from numpy import array
|
|
32
|
+
from traits.api import (
|
|
33
|
+
File,
|
|
34
|
+
Instance,
|
|
35
|
+
Property,
|
|
36
|
+
cached_property,
|
|
37
|
+
on_trait_change,
|
|
38
|
+
property_depends_on,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
from acoular.h5files import H5FileBase, _get_h5file_class
|
|
42
|
+
from acoular.internal import digest
|
|
43
|
+
from acoular.microphones import MicGeom
|
|
44
|
+
from acoular.sources import TimeSamples
|
|
45
|
+
from acoular.spectra import PowerSpectraImport
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class TimeSamplesAIAABenchmark(TimeSamples):
|
|
49
|
+
"""Container for AIAA benchmark data in `*.h5` format.
|
|
50
|
+
|
|
51
|
+
This class loads measured data from h5 files in AIAA benchmark format
|
|
52
|
+
and and provides information about this data.
|
|
53
|
+
Objects of this class behave similar to :class:`~acoular.sources.TimeSamples`
|
|
54
|
+
objects.
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
def load_timedata(self):
|
|
58
|
+
"""Loads timedata from .h5 file. Only for internal use."""
|
|
59
|
+
self.data = self.h5f.get_data_by_reference('MicrophoneData/microphoneDataPa')
|
|
60
|
+
self.sample_freq = self.h5f.get_node_attribute(self.data, 'sampleRateHz')
|
|
61
|
+
(self.numsamples, self.numchannels) = self.data.shape
|
|
62
|
+
|
|
63
|
+
def load_metadata(self):
|
|
64
|
+
"""Loads metadata from .h5 file. Only for internal use."""
|
|
65
|
+
self.metadata = {}
|
|
66
|
+
if '/MetaData' in self.h5f:
|
|
67
|
+
self.metadata = self.h5f.node_to_dict('/MetaData')
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class TriggerAIAABenchmark(TimeSamplesAIAABenchmark):
|
|
71
|
+
"""Container for tacho data in `*.h5` format.
|
|
72
|
+
|
|
73
|
+
This class loads tacho data from h5 files as specified in
|
|
74
|
+
"Microphone Array Benchmark b11: Rotating Point Sources"
|
|
75
|
+
(https://doi.org/10.14279/depositonce-8460)
|
|
76
|
+
and and provides information about this data.
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
def load_timedata(self):
|
|
80
|
+
"""Loads timedata from .h5 file. Only for internal use."""
|
|
81
|
+
self.data = self.h5f.get_data_by_reference('TachoData/tachoDataV')
|
|
82
|
+
self.sample_freq = self.h5f.get_node_attribute(self.data, 'sampleRateHz')
|
|
83
|
+
(self.numsamples, self.numchannels) = self.data.shape
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class CsmAIAABenchmark(PowerSpectraImport):
|
|
87
|
+
"""Class to load the CSM that is stored in AIAA Benchmark HDF5 file."""
|
|
88
|
+
|
|
89
|
+
#: Full name of the .h5 file with data
|
|
90
|
+
name = File(filter=['*.h5'], desc='name of data file')
|
|
91
|
+
|
|
92
|
+
#: Basename of the .h5 file with data, is set automatically.
|
|
93
|
+
basename = Property(
|
|
94
|
+
depends_on='name',
|
|
95
|
+
desc='basename of data file',
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
#: number of channels
|
|
99
|
+
numchannels = Property()
|
|
100
|
+
|
|
101
|
+
#: HDF5 file object
|
|
102
|
+
h5f = Instance(H5FileBase, transient=True)
|
|
103
|
+
|
|
104
|
+
# internal identifier
|
|
105
|
+
digest = Property(depends_on=['basename', '_csmsum'])
|
|
106
|
+
|
|
107
|
+
@cached_property
|
|
108
|
+
def _get_digest(self):
|
|
109
|
+
return digest(self)
|
|
110
|
+
|
|
111
|
+
@cached_property
|
|
112
|
+
def _get_basename(self):
|
|
113
|
+
return path.splitext(path.basename(self.name))[0]
|
|
114
|
+
|
|
115
|
+
@on_trait_change('basename')
|
|
116
|
+
def load_data(self):
|
|
117
|
+
"""Open the .h5 file and set attributes."""
|
|
118
|
+
if not path.isfile(self.name):
|
|
119
|
+
# no file there
|
|
120
|
+
raise OSError('No such file: %s' % self.name)
|
|
121
|
+
if self.h5f is not None:
|
|
122
|
+
with contextlib.suppress(OSError):
|
|
123
|
+
self.h5f.close()
|
|
124
|
+
file = _get_h5file_class()
|
|
125
|
+
self.h5f = file(self.name)
|
|
126
|
+
|
|
127
|
+
# @property_depends_on( 'block_size, ind_low, ind_high' )
|
|
128
|
+
def _get_indices(self):
|
|
129
|
+
try:
|
|
130
|
+
return range(self.fftfreq().shape[0]) # [ self.ind_low: self.ind_high ]
|
|
131
|
+
except IndexError:
|
|
132
|
+
return range(0)
|
|
133
|
+
|
|
134
|
+
@property_depends_on('digest')
|
|
135
|
+
def _get_numchannels(self):
|
|
136
|
+
try:
|
|
137
|
+
attrs = self.h5f.get_data_by_reference('MetaData/ArrayAttributes')
|
|
138
|
+
return self.h5f.get_node_attribute(attrs, 'microphoneCount')
|
|
139
|
+
except IndexError:
|
|
140
|
+
return 0
|
|
141
|
+
|
|
142
|
+
@property_depends_on('digest')
|
|
143
|
+
def _get_csm(self):
|
|
144
|
+
"""Loads cross spectral matrix from file."""
|
|
145
|
+
csmre = self.h5f.get_data_by_reference('/CsmData/csmReal')[:].transpose((2, 0, 1))
|
|
146
|
+
csmim = self.h5f.get_data_by_reference('/CsmData/csmImaginary')[:].transpose((2, 0, 1))
|
|
147
|
+
csmdatagroup = self.h5f.get_data_by_reference('/CsmData')
|
|
148
|
+
sign = self.h5f.get_node_attribute(csmdatagroup, 'fftSign')
|
|
149
|
+
return csmre + sign * 1j * csmim
|
|
150
|
+
|
|
151
|
+
def fftfreq(self):
|
|
152
|
+
"""Return the Discrete Fourier Transform sample frequencies.
|
|
153
|
+
|
|
154
|
+
Returns
|
|
155
|
+
-------
|
|
156
|
+
ndarray
|
|
157
|
+
Array of length *block_size/2+1* containing the sample frequencies.
|
|
158
|
+
"""
|
|
159
|
+
return array(self.h5f.get_data_by_reference('/CsmData/binCenterFrequenciesHz')[:].flatten(), dtype=float)
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
class MicAIAABenchmark(MicGeom):
|
|
163
|
+
"""Provides the geometric arrangement of microphones in the array.
|
|
164
|
+
|
|
165
|
+
In contrast to standard Acoular microphone geometries, the AIAA
|
|
166
|
+
benchmark format includes the array geometry as metadata in the
|
|
167
|
+
file containing the measurement data.
|
|
168
|
+
"""
|
|
169
|
+
|
|
170
|
+
#: Name of the .h5-file from wich to read the data.
|
|
171
|
+
from_file = File(filter=['*.h5'], desc='name of the h5 file containing the microphone geometry')
|
|
172
|
+
|
|
173
|
+
@on_trait_change('basename')
|
|
174
|
+
def import_mpos(self):
|
|
175
|
+
"""Import the microphone positions from .h5 file.
|
|
176
|
+
Called when :attr:`basename` changes.
|
|
177
|
+
"""
|
|
178
|
+
if not path.isfile(self.from_file):
|
|
179
|
+
# no file there
|
|
180
|
+
raise OSError('No such file: %s' % self.from_file)
|
|
181
|
+
|
|
182
|
+
file = _get_h5file_class()
|
|
183
|
+
h5f = file(self.from_file, mode='r')
|
|
184
|
+
self.mpos_tot = h5f.get_data_by_reference('MetaData/ArrayAttributes/microphonePositionsM')[:].swapaxes(0, 1)
|
|
185
|
+
h5f.close()
|