acoular 24.5__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 +3 -6
- acoular/configuration.py +20 -13
- acoular/demo/acoular_demo.py +28 -35
- acoular/environments.py +13 -10
- acoular/fastFuncs.py +40 -40
- acoular/fbeamform.py +895 -1088
- acoular/grids.py +5 -5
- acoular/h5cache.py +34 -34
- acoular/h5files.py +13 -13
- acoular/internal.py +3 -3
- acoular/sdinput.py +10 -1
- acoular/signals.py +15 -1
- acoular/sources.py +120 -49
- acoular/spectra.py +5 -5
- acoular/tbeamform.py +5 -6
- acoular/tfastfuncs.py +17 -18
- acoular/tools/aiaa.py +4 -5
- acoular/tprocess.py +82 -82
- acoular/version.py +2 -2
- {acoular-24.5.dist-info → acoular-24.7.dist-info}/METADATA +24 -4
- {acoular-24.5.dist-info → acoular-24.7.dist-info}/RECORD +24 -24
- {acoular-24.5.dist-info → acoular-24.7.dist-info}/WHEEL +1 -1
- {acoular-24.5.dist-info → acoular-24.7.dist-info}/licenses/AUTHORS.rst +0 -0
- {acoular-24.5.dist-info → acoular-24.7.dist-info}/licenses/LICENSE +0 -0
acoular/tbeamform.py
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"""
|
|
19
19
|
|
|
20
20
|
# imports from other packages
|
|
21
|
+
import contextlib
|
|
21
22
|
from warnings import warn
|
|
22
23
|
|
|
23
24
|
from numpy import (
|
|
@@ -201,7 +202,7 @@ class BeamformerTime(TimeInOut):
|
|
|
201
202
|
buffer = CArray(desc='buffer containing microphone signals')
|
|
202
203
|
|
|
203
204
|
# index indicating position of current processing sample. Internal use.
|
|
204
|
-
bufferIndex = Int(desc='index indicating position in buffer')
|
|
205
|
+
bufferIndex = Int(desc='index indicating position in buffer') # noqa: N815
|
|
205
206
|
|
|
206
207
|
# internal identifier
|
|
207
208
|
digest = Property(
|
|
@@ -331,10 +332,8 @@ class BeamformerTime(TimeInOut):
|
|
|
331
332
|
else:
|
|
332
333
|
yield Gamma[:num] ** 2
|
|
333
334
|
self.bufferIndex += num
|
|
334
|
-
|
|
335
|
+
with contextlib.suppress(StopIteration):
|
|
335
336
|
next(fill_buffer_generator)
|
|
336
|
-
except:
|
|
337
|
-
pass
|
|
338
337
|
|
|
339
338
|
def delay_and_sum(self, num, p_res, d_interp2, d_index, amp):
|
|
340
339
|
"""Standard delay-and-sum method."""
|
|
@@ -529,7 +528,7 @@ class BeamformerTimeTraj(BeamformerTime):
|
|
|
529
528
|
self.increase_buffer(num)
|
|
530
529
|
try:
|
|
531
530
|
next(fill_buffer_generator)
|
|
532
|
-
except:
|
|
531
|
+
except StopIteration:
|
|
533
532
|
dflag = False
|
|
534
533
|
samplesleft = self.buffer.shape[0] - self.bufferIndex
|
|
535
534
|
# last block may be shorter
|
|
@@ -602,7 +601,7 @@ class BeamformerTimeTraj(BeamformerTime):
|
|
|
602
601
|
self.bufferIndex += num
|
|
603
602
|
try:
|
|
604
603
|
next(fill_buffer_generator)
|
|
605
|
-
except:
|
|
604
|
+
except StopIteration:
|
|
606
605
|
dflag = False
|
|
607
606
|
|
|
608
607
|
def delay_and_sum(self, num, p_res, d_interp2, d_index, amp):
|
acoular/tfastfuncs.py
CHANGED
|
@@ -6,9 +6,6 @@
|
|
|
6
6
|
import numba as nb
|
|
7
7
|
import numpy as np
|
|
8
8
|
|
|
9
|
-
cachedOption = True # if True: saves the numba func as compiled func in sub directory
|
|
10
|
-
fastOption = True # fastmath options
|
|
11
|
-
|
|
12
9
|
|
|
13
10
|
@nb.njit(
|
|
14
11
|
[
|
|
@@ -46,11 +43,11 @@ def _delayandsum4(data, offsets, ifactor2, steeramp, out, autopower):
|
|
|
46
43
|
"""
|
|
47
44
|
gridsize, numchannels = offsets.shape
|
|
48
45
|
num = out.shape[0]
|
|
49
|
-
|
|
46
|
+
zero_constant = data.dtype.type(0.0)
|
|
50
47
|
for n in nb.prange(num):
|
|
51
48
|
for gi in nb.prange(gridsize):
|
|
52
|
-
out[n, gi] =
|
|
53
|
-
autopower[n, gi] =
|
|
49
|
+
out[n, gi] = zero_constant
|
|
50
|
+
autopower[n, gi] = zero_constant
|
|
54
51
|
for mi in range(numchannels):
|
|
55
52
|
ind = (gi, mi)
|
|
56
53
|
r = (
|
|
@@ -105,14 +102,16 @@ def _delayandsum5(data, offsets, ifactor2, steeramp, out, autopower):
|
|
|
105
102
|
num, gridsize, numchannels = offsets.shape
|
|
106
103
|
num = out.shape[0]
|
|
107
104
|
# ZERO = data.dtype.type(0.)
|
|
108
|
-
|
|
105
|
+
one_constant = data.dtype.type(1.0)
|
|
109
106
|
for n in nb.prange(num):
|
|
110
107
|
for gi in nb.prange(gridsize):
|
|
111
108
|
out[n, gi] = 0
|
|
112
109
|
autopower[n, gi] = 0
|
|
113
110
|
for mi in range(numchannels):
|
|
114
111
|
ind = offsets[n, gi, mi] + n
|
|
115
|
-
r = (
|
|
112
|
+
r = (
|
|
113
|
+
data[ind, mi] * (one_constant - ifactor2[n, gi, mi]) + data[ind + 1, mi] * ifactor2[n, gi, mi]
|
|
114
|
+
) * steeramp[
|
|
116
115
|
n,
|
|
117
116
|
gi,
|
|
118
117
|
mi,
|
|
@@ -130,14 +129,14 @@ def _delayandsum5(data, offsets, ifactor2, steeramp, out, autopower):
|
|
|
130
129
|
parallel=True,
|
|
131
130
|
fastmath=True,
|
|
132
131
|
)
|
|
133
|
-
def _steer_I(rm, r0, amp): # noqa: ARG001
|
|
132
|
+
def _steer_I(rm, r0, amp): # noqa: ARG001, N802
|
|
134
133
|
num, gridsize, numchannels = rm.shape
|
|
135
134
|
amp[0, 0, 0] = 1.0 / numchannels # to get the same type for rm2 as for rm
|
|
136
|
-
|
|
135
|
+
nr = amp[0, 0, 0]
|
|
137
136
|
for n in nb.prange(num):
|
|
138
137
|
for gi in nb.prange(gridsize):
|
|
139
138
|
for mi in nb.prange(numchannels):
|
|
140
|
-
amp[n, gi, mi] =
|
|
139
|
+
amp[n, gi, mi] = nr
|
|
141
140
|
|
|
142
141
|
|
|
143
142
|
@nb.njit(
|
|
@@ -149,13 +148,13 @@ def _steer_I(rm, r0, amp): # noqa: ARG001
|
|
|
149
148
|
parallel=True,
|
|
150
149
|
fastmath=True,
|
|
151
150
|
)
|
|
152
|
-
def _steer_II(rm, r0, amp):
|
|
151
|
+
def _steer_II(rm, r0, amp): # noqa: N802
|
|
153
152
|
num, gridsize, numchannels = rm.shape
|
|
154
153
|
amp[0, 0, 0] = 1.0 / numchannels # to get the same type for rm2 as for rm
|
|
155
|
-
|
|
154
|
+
nr = amp[0, 0, 0]
|
|
156
155
|
for n in nb.prange(num):
|
|
157
156
|
for gi in nb.prange(gridsize):
|
|
158
|
-
rm2 = np.divide(
|
|
157
|
+
rm2 = np.divide(nr, r0[n, gi])
|
|
159
158
|
for mi in nb.prange(numchannels):
|
|
160
159
|
amp[n, gi, mi] = rm[n, gi, mi] * rm2
|
|
161
160
|
|
|
@@ -169,7 +168,7 @@ def _steer_II(rm, r0, amp):
|
|
|
169
168
|
parallel=True,
|
|
170
169
|
fastmath=True,
|
|
171
170
|
)
|
|
172
|
-
def _steer_III(rm, r0, amp):
|
|
171
|
+
def _steer_III(rm, r0, amp): # noqa: N802
|
|
173
172
|
num, gridsize, numchannels = rm.shape
|
|
174
173
|
rm20 = rm[0, 0, 0] - rm[0, 0, 0] # to get the same type for rm2 as for rm
|
|
175
174
|
rm1 = rm[0, 0, 0] / rm[0, 0, 0]
|
|
@@ -192,10 +191,10 @@ def _steer_III(rm, r0, amp):
|
|
|
192
191
|
parallel=True,
|
|
193
192
|
fastmath=True,
|
|
194
193
|
)
|
|
195
|
-
def _steer_IV(rm, r0, amp): # noqa: ARG001
|
|
194
|
+
def _steer_IV(rm, r0, amp): # noqa: ARG001, N802
|
|
196
195
|
num, gridsize, numchannels = rm.shape
|
|
197
196
|
amp[0, 0, 0] = np.sqrt(1.0 / numchannels) # to get the same type for rm2 as for rm
|
|
198
|
-
|
|
197
|
+
nr = amp[0, 0, 0]
|
|
199
198
|
rm1 = rm[0, 0, 0] / rm[0, 0, 0]
|
|
200
199
|
rm20 = rm[0, 0, 0] - rm[0, 0, 0] # to get the same type for rm2 as for rm
|
|
201
200
|
for n in nb.prange(num):
|
|
@@ -205,7 +204,7 @@ def _steer_IV(rm, r0, amp): # noqa: ARG001
|
|
|
205
204
|
rm2 += np.divide(rm1, np.square(rm[n, gi, mi]))
|
|
206
205
|
rm2 = np.sqrt(rm2)
|
|
207
206
|
for mi in nb.prange(numchannels):
|
|
208
|
-
amp[n, gi, mi] = np.divide(
|
|
207
|
+
amp[n, gi, mi] = np.divide(nr, rm[n, gi, mi] * rm2)
|
|
209
208
|
|
|
210
209
|
|
|
211
210
|
@nb.njit(
|
acoular/tools/aiaa.py
CHANGED
|
@@ -12,8 +12,8 @@ the framework.
|
|
|
12
12
|
|
|
13
13
|
Examples
|
|
14
14
|
--------
|
|
15
|
-
>>> micgeom = MicAIAABenchmark(name='some_benchmarkdata.h5')
|
|
16
|
-
>>> timedata = TimeSamplesAIAABenchmark(name='some_benchmarkdata.h5')
|
|
15
|
+
>>> micgeom = MicAIAABenchmark(name='some_benchmarkdata.h5') # doctest: +SKIP
|
|
16
|
+
>>> timedata = TimeSamplesAIAABenchmark(name='some_benchmarkdata.h5') # doctest: +SKIP
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
.. autosummary::
|
|
@@ -25,6 +25,7 @@ Examples
|
|
|
25
25
|
MicAIAABenchmark
|
|
26
26
|
"""
|
|
27
27
|
|
|
28
|
+
import contextlib
|
|
28
29
|
from os import path
|
|
29
30
|
|
|
30
31
|
from numpy import array
|
|
@@ -118,10 +119,8 @@ class CsmAIAABenchmark(PowerSpectraImport):
|
|
|
118
119
|
# no file there
|
|
119
120
|
raise OSError('No such file: %s' % self.name)
|
|
120
121
|
if self.h5f is not None:
|
|
121
|
-
|
|
122
|
+
with contextlib.suppress(OSError):
|
|
122
123
|
self.h5f.close()
|
|
123
|
-
except OSError:
|
|
124
|
-
pass
|
|
125
124
|
file = _get_h5file_class()
|
|
126
125
|
self.h5f = file(self.name)
|
|
127
126
|
|
acoular/tprocess.py
CHANGED
|
@@ -467,20 +467,20 @@ class Trigger(TimeInOut):
|
|
|
467
467
|
def _get_trigger_data(self):
|
|
468
468
|
self._check_trigger_existence()
|
|
469
469
|
triggerFunc = {'dirac': self._trigger_dirac, 'rect': self._trigger_rect}[self.trigger_type]
|
|
470
|
-
|
|
471
|
-
threshold = self._threshold(
|
|
470
|
+
num = 2048 # number samples for result-method of source
|
|
471
|
+
threshold = self._threshold(num)
|
|
472
472
|
|
|
473
473
|
# get all samples which surpasse the threshold
|
|
474
474
|
peakLoc = array([], dtype='int') # all indices which surpasse the threshold
|
|
475
|
-
|
|
475
|
+
trigger_data = array([])
|
|
476
476
|
x0 = []
|
|
477
477
|
dSamples = 0
|
|
478
|
-
for triggerSignal in self.source.result(
|
|
478
|
+
for triggerSignal in self.source.result(num):
|
|
479
479
|
localTrigger = flatnonzero(triggerFunc(x0, triggerSignal, threshold))
|
|
480
480
|
if len(localTrigger) != 0:
|
|
481
481
|
peakLoc = append(peakLoc, localTrigger + dSamples)
|
|
482
|
-
|
|
483
|
-
dSamples +=
|
|
482
|
+
trigger_data = append(trigger_data, triggerSignal[localTrigger])
|
|
483
|
+
dSamples += num
|
|
484
484
|
x0 = triggerSignal[-1]
|
|
485
485
|
if len(peakLoc) <= 1:
|
|
486
486
|
msg = 'Not enough trigger info. Check *threshold* sign and value!'
|
|
@@ -498,12 +498,12 @@ class Trigger(TimeInOut):
|
|
|
498
498
|
peakLocHelp = multiplePeaksWithinHunk[0]
|
|
499
499
|
indHelp = [peakLocHelp, peakLocHelp + 1]
|
|
500
500
|
if self.multiple_peaks_in_hunk == 'extremum':
|
|
501
|
-
values =
|
|
501
|
+
values = trigger_data[indHelp]
|
|
502
502
|
deleteInd = indHelp[argmin(abs(values))]
|
|
503
503
|
elif self.multiple_peaks_in_hunk == 'first':
|
|
504
504
|
deleteInd = indHelp[1]
|
|
505
505
|
peakLoc = delete(peakLoc, deleteInd)
|
|
506
|
-
|
|
506
|
+
trigger_data = delete(trigger_data, deleteInd)
|
|
507
507
|
peakDist = peakLoc[1:] - peakLoc[:-1]
|
|
508
508
|
multiplePeaksWithinHunk = flatnonzero(peakDist < self.hunk_length * maxPeakDist)
|
|
509
509
|
|
|
@@ -520,7 +520,7 @@ class Trigger(TimeInOut):
|
|
|
520
520
|
)
|
|
521
521
|
return peakLoc, max(peakDist), min(peakDist)
|
|
522
522
|
|
|
523
|
-
def _trigger_dirac(self, x0, x, threshold):
|
|
523
|
+
def _trigger_dirac(self, x0, x, threshold): # noqa: ARG002
|
|
524
524
|
# x0 not needed here, but needed in _trigger_rect
|
|
525
525
|
return self._trigger_value_comp(x, threshold)
|
|
526
526
|
|
|
@@ -530,20 +530,20 @@ class Trigger(TimeInOut):
|
|
|
530
530
|
# indPeakHunk = abs(xNew[1:] - xNew[:-1]) > abs(threshold) # with this line: every edge would be located
|
|
531
531
|
return self._trigger_value_comp(xNew[1:] - xNew[:-1], threshold)
|
|
532
532
|
|
|
533
|
-
def _trigger_value_comp(self,
|
|
534
|
-
return
|
|
533
|
+
def _trigger_value_comp(self, trigger_data, threshold):
|
|
534
|
+
return trigger_data > threshold if threshold > 0.0 else trigger_data < threshold
|
|
535
535
|
|
|
536
|
-
def _threshold(self,
|
|
536
|
+
def _threshold(self, num):
|
|
537
537
|
if self.threshold is None: # take a guessed threshold
|
|
538
538
|
# get max and min values of whole trigger signal
|
|
539
539
|
maxVal = -inf
|
|
540
540
|
minVal = inf
|
|
541
541
|
meanVal = 0
|
|
542
542
|
cntMean = 0
|
|
543
|
-
for
|
|
544
|
-
maxVal = max(maxVal,
|
|
545
|
-
minVal = min(minVal,
|
|
546
|
-
meanVal +=
|
|
543
|
+
for trigger_data in self.source.result(num):
|
|
544
|
+
maxVal = max(maxVal, trigger_data.max())
|
|
545
|
+
minVal = min(minVal, trigger_data.min())
|
|
546
|
+
meanVal += trigger_data.mean()
|
|
547
547
|
cntMean += 1
|
|
548
548
|
meanVal /= cntMean
|
|
549
549
|
|
|
@@ -642,18 +642,18 @@ class AngleTracker(MaskedTimeInOut):
|
|
|
642
642
|
# init
|
|
643
643
|
ind = 0
|
|
644
644
|
# trigger data
|
|
645
|
-
peakloc, maxdist, mindist = self.trigger.
|
|
645
|
+
peakloc, maxdist, mindist = self.trigger.trigger_data()
|
|
646
646
|
TriggerPerRevo = self.trigger_per_revo
|
|
647
647
|
rotDirection = self.rot_direction
|
|
648
|
-
|
|
648
|
+
num = self.source.numsamples
|
|
649
649
|
samplerate = self.source.sample_freq
|
|
650
|
-
self._rpm = zeros(
|
|
651
|
-
self._angle = zeros(
|
|
650
|
+
self._rpm = zeros(num)
|
|
651
|
+
self._angle = zeros(num)
|
|
652
652
|
# number of spline points
|
|
653
653
|
InterpPoints = self.interp_points
|
|
654
654
|
|
|
655
655
|
# loop over alle timesamples
|
|
656
|
-
while ind <
|
|
656
|
+
while ind < num:
|
|
657
657
|
# when starting spline forward
|
|
658
658
|
if ind < peakloc[InterpPoints]:
|
|
659
659
|
peakdist = (
|
|
@@ -716,7 +716,7 @@ class AngleTracker(MaskedTimeInOut):
|
|
|
716
716
|
|
|
717
717
|
"""
|
|
718
718
|
# trigger indices data
|
|
719
|
-
peakloc = self.trigger.
|
|
719
|
+
peakloc = self.trigger.trigger_data()[0]
|
|
720
720
|
# calculation of average rpm in 1/min
|
|
721
721
|
return (len(peakloc) - 1) / (peakloc[-1] - peakloc[0]) / self.trigger_per_revo * self.source.sample_freq * 60
|
|
722
722
|
|
|
@@ -784,7 +784,7 @@ class SpatialInterpolator(TimeInOut):
|
|
|
784
784
|
#: The transformation is done via [x,y,z]_mod = Q * [x,y,z]. (default is Identity).
|
|
785
785
|
Q = CArray(dtype=float64, shape=(3, 3), value=identity(3))
|
|
786
786
|
|
|
787
|
-
num_IDW = Trait(3, dtype=int, desc='number of neighboring microphones, DEFAULT=3')
|
|
787
|
+
num_IDW = Trait(3, dtype=int, desc='number of neighboring microphones, DEFAULT=3') # noqa: N815
|
|
788
788
|
|
|
789
789
|
p_weight = Trait(
|
|
790
790
|
2,
|
|
@@ -793,7 +793,7 @@ class SpatialInterpolator(TimeInOut):
|
|
|
793
793
|
)
|
|
794
794
|
|
|
795
795
|
#: Stores the output of :meth:`_virtNewCoord_func`; Read-Only
|
|
796
|
-
_virtNewCoord_func = Property(
|
|
796
|
+
_virtNewCoord_func = Property( # noqa: N815
|
|
797
797
|
depends_on=['mics.digest', 'mics_virtual.digest', 'method', 'array_dimension', 'interp_at_zero'],
|
|
798
798
|
)
|
|
799
799
|
|
|
@@ -818,21 +818,21 @@ class SpatialInterpolator(TimeInOut):
|
|
|
818
818
|
return digest(self)
|
|
819
819
|
|
|
820
820
|
@cached_property
|
|
821
|
-
def _get_virtNewCoord(self):
|
|
821
|
+
def _get_virtNewCoord(self): # noqa N802
|
|
822
822
|
return self._virtNewCoord_func(self.mics.mpos, self.mics_virtual.mpos, self.method, self.array_dimension)
|
|
823
823
|
|
|
824
824
|
def sinc_mic(self, r):
|
|
825
825
|
"""Modified Sinc function for Radial Basis function approximation."""
|
|
826
826
|
return sinc((r * self.mics_virtual.mpos.shape[1]) / (pi))
|
|
827
827
|
|
|
828
|
-
def _virtNewCoord_func(self,
|
|
829
|
-
"""Core functionality for getting the
|
|
828
|
+
def _virtNewCoord_func(self, mpos, mpos_virt, method, array_dimension): # noqa N802
|
|
829
|
+
"""Core functionality for getting the interpolation.
|
|
830
830
|
|
|
831
831
|
Parameters
|
|
832
832
|
----------
|
|
833
|
-
|
|
833
|
+
mpos : float[3, nPhysicalMics]
|
|
834
834
|
The mic positions of the physical (really existing) mics
|
|
835
|
-
|
|
835
|
+
mpos_virt : float[3, nVirtualMics]
|
|
836
836
|
The mic positions of the virtual mics
|
|
837
837
|
method : string
|
|
838
838
|
The Interpolation method to use
|
|
@@ -864,11 +864,11 @@ class SpatialInterpolator(TimeInOut):
|
|
|
864
864
|
|
|
865
865
|
"""
|
|
866
866
|
# init positions of virtual mics in cyl coordinates
|
|
867
|
-
nVirtMics =
|
|
867
|
+
nVirtMics = mpos_virt.shape[1]
|
|
868
868
|
virtNewCoord = zeros((3, nVirtMics))
|
|
869
869
|
virtNewCoord.fill(nan)
|
|
870
870
|
# init real positions in cyl coordinates
|
|
871
|
-
nMics =
|
|
871
|
+
nMics = mpos.shape[1]
|
|
872
872
|
newCoord = zeros((3, nMics))
|
|
873
873
|
newCoord.fill(nan)
|
|
874
874
|
# empty mesh object
|
|
@@ -876,24 +876,24 @@ class SpatialInterpolator(TimeInOut):
|
|
|
876
876
|
|
|
877
877
|
if self.array_dimension == '1D' or self.array_dimension == 'ring':
|
|
878
878
|
# get projections onto new coordinate, for real mics
|
|
879
|
-
projectionOnNewAxis = cartToCyl(
|
|
879
|
+
projectionOnNewAxis = cartToCyl(mpos, self.Q)[0]
|
|
880
880
|
indReorderHelp = argsort(projectionOnNewAxis)
|
|
881
881
|
mesh.append([projectionOnNewAxis[indReorderHelp], indReorderHelp])
|
|
882
882
|
|
|
883
883
|
# new coordinates of real mics
|
|
884
|
-
indReorderHelp = argsort(cartToCyl(
|
|
885
|
-
newCoord = (cartToCyl(
|
|
884
|
+
indReorderHelp = argsort(cartToCyl(mpos, self.Q)[0])
|
|
885
|
+
newCoord = (cartToCyl(mpos, self.Q).T)[indReorderHelp].T
|
|
886
886
|
|
|
887
887
|
# and for virtual mics
|
|
888
|
-
virtNewCoord = cartToCyl(
|
|
888
|
+
virtNewCoord = cartToCyl(mpos_virt)
|
|
889
889
|
|
|
890
890
|
elif self.array_dimension == '2D': # 2d case0
|
|
891
891
|
# get virtual mic projections on new coord system
|
|
892
|
-
virtNewCoord = cartToCyl(
|
|
892
|
+
virtNewCoord = cartToCyl(mpos_virt, self.Q)
|
|
893
893
|
|
|
894
894
|
# new coordinates of real mics
|
|
895
|
-
indReorderHelp = argsort(cartToCyl(
|
|
896
|
-
newCoord = cartToCyl(
|
|
895
|
+
indReorderHelp = argsort(cartToCyl(mpos, self.Q)[0])
|
|
896
|
+
newCoord = cartToCyl(mpos, self.Q)
|
|
897
897
|
|
|
898
898
|
# scipy delauney triangulation
|
|
899
899
|
# Delaunay
|
|
@@ -929,10 +929,10 @@ class SpatialInterpolator(TimeInOut):
|
|
|
929
929
|
|
|
930
930
|
elif self.array_dimension == '3D': # 3d case
|
|
931
931
|
# get virtual mic projections on new coord system
|
|
932
|
-
virtNewCoord = cartToCyl(
|
|
932
|
+
virtNewCoord = cartToCyl(mpos_virt, self.Q)
|
|
933
933
|
# get real mic projections on new coord system
|
|
934
|
-
indReorderHelp = argsort(cartToCyl(
|
|
935
|
-
newCoord = cartToCyl(
|
|
934
|
+
indReorderHelp = argsort(cartToCyl(mpos, self.Q)[0])
|
|
935
|
+
newCoord = cartToCyl(mpos, self.Q)
|
|
936
936
|
# Delaunay
|
|
937
937
|
tri = Delaunay(newCoord.T, incremental=True) # , incremental=True,qhull_options = "Qc QJ Q12"
|
|
938
938
|
|
|
@@ -966,14 +966,14 @@ class SpatialInterpolator(TimeInOut):
|
|
|
966
966
|
|
|
967
967
|
return mesh, virtNewCoord, newCoord
|
|
968
968
|
|
|
969
|
-
def _result_core_func(self, p,
|
|
969
|
+
def _result_core_func(self, p, phi_delay=None, period=None, Q=Q, interp_at_zero=False): # noqa: N803, ARG002 (see #226)
|
|
970
970
|
"""Performs the actual Interpolation.
|
|
971
971
|
|
|
972
972
|
Parameters
|
|
973
973
|
----------
|
|
974
|
-
p : float[
|
|
974
|
+
p : float[num, nMicsReal]
|
|
975
975
|
The pressure field of the yielded sample at real mics.
|
|
976
|
-
|
|
976
|
+
phi_delay : empty list (default) or float[num]
|
|
977
977
|
If passed (rotational case), this list contains the angular delay
|
|
978
978
|
of each sample in rad.
|
|
979
979
|
period : None (default) or float
|
|
@@ -982,12 +982,12 @@ class SpatialInterpolator(TimeInOut):
|
|
|
982
982
|
|
|
983
983
|
Returns
|
|
984
984
|
-------
|
|
985
|
-
pInterp : float[
|
|
985
|
+
pInterp : float[num, nMicsVirtual]
|
|
986
986
|
The interpolated time data at the virtual mics
|
|
987
987
|
|
|
988
988
|
"""
|
|
989
|
-
if
|
|
990
|
-
|
|
989
|
+
if phi_delay is None:
|
|
990
|
+
phi_delay = []
|
|
991
991
|
# number of time samples
|
|
992
992
|
nTime = p.shape[0]
|
|
993
993
|
# number of virtual mixcs
|
|
@@ -1015,9 +1015,9 @@ class SpatialInterpolator(TimeInOut):
|
|
|
1015
1015
|
|
|
1016
1016
|
# Interpolation for 1D Arrays
|
|
1017
1017
|
if self.array_dimension == '1D' or self.array_dimension == 'ring':
|
|
1018
|
-
# for rotation add
|
|
1019
|
-
if not array_equal(
|
|
1020
|
-
xInterpHelp = repmat(virtNewCoord[0, :], nTime, 1) + repmat(
|
|
1018
|
+
# for rotation add phi_delay
|
|
1019
|
+
if not array_equal(phi_delay, []):
|
|
1020
|
+
xInterpHelp = repmat(virtNewCoord[0, :], nTime, 1) + repmat(phi_delay, virtNewCoord.shape[1], 1).T
|
|
1021
1021
|
xInterp = ((xInterpHelp + pi) % (2 * pi)) - pi # shifting phi cootrdinate into feasible area [-pi, pi]
|
|
1022
1022
|
# if no rotation given
|
|
1023
1023
|
else:
|
|
@@ -1074,8 +1074,8 @@ class SpatialInterpolator(TimeInOut):
|
|
|
1074
1074
|
# Interpolation for arbitrary 2D Arrays
|
|
1075
1075
|
elif self.array_dimension == '2D':
|
|
1076
1076
|
# check rotation
|
|
1077
|
-
if not array_equal(
|
|
1078
|
-
xInterpHelp = repmat(virtNewCoord[0, :], nTime, 1) + repmat(
|
|
1077
|
+
if not array_equal(phi_delay, []):
|
|
1078
|
+
xInterpHelp = repmat(virtNewCoord[0, :], nTime, 1) + repmat(phi_delay, virtNewCoord.shape[1], 1).T
|
|
1079
1079
|
xInterp = ((xInterpHelp + pi) % (2 * pi)) - pi # shifting phi cootrdinate into feasible area [-pi, pi]
|
|
1080
1080
|
else:
|
|
1081
1081
|
xInterp = repmat(virtNewCoord[0, :], nTime, 1)
|
|
@@ -1153,8 +1153,8 @@ class SpatialInterpolator(TimeInOut):
|
|
|
1153
1153
|
# Interpolation for arbitrary 3D Arrays
|
|
1154
1154
|
elif self.array_dimension == '3D':
|
|
1155
1155
|
# check rotation
|
|
1156
|
-
if not array_equal(
|
|
1157
|
-
xInterpHelp = repmat(virtNewCoord[0, :], nTime, 1) + repmat(
|
|
1156
|
+
if not array_equal(phi_delay, []):
|
|
1157
|
+
xInterpHelp = repmat(virtNewCoord[0, :], nTime, 1) + repmat(phi_delay, virtNewCoord.shape[1], 1).T
|
|
1158
1158
|
xInterp = ((xInterpHelp + pi) % (2 * pi)) - pi # shifting phi cootrdinate into feasible area [-pi, pi]
|
|
1159
1159
|
else:
|
|
1160
1160
|
xInterp = repmat(virtNewCoord[0, :], nTime, 1)
|
|
@@ -1253,12 +1253,12 @@ class SpatialInterpolatorRotation(SpatialInterpolator):
|
|
|
1253
1253
|
# period for rotation
|
|
1254
1254
|
period = 2 * pi
|
|
1255
1255
|
# get angle
|
|
1256
|
-
angle = self.angle_source.
|
|
1256
|
+
angle = self.angle_source.angle()
|
|
1257
1257
|
# counter to track angle position in time for each block
|
|
1258
1258
|
count = 0
|
|
1259
1259
|
for timeData in self.source.result(num):
|
|
1260
|
-
|
|
1261
|
-
interpVal = self._result_core_func(timeData,
|
|
1260
|
+
phi_delay = angle[count : count + num]
|
|
1261
|
+
interpVal = self._result_core_func(timeData, phi_delay, period, self.Q, interp_at_zero=False)
|
|
1262
1262
|
yield interpVal
|
|
1263
1263
|
count += num
|
|
1264
1264
|
|
|
@@ -1311,9 +1311,9 @@ class SpatialInterpolatorConstantRotation(SpatialInterpolator):
|
|
|
1311
1311
|
phiOffset = 0.0
|
|
1312
1312
|
for timeData in self.source.result(num):
|
|
1313
1313
|
nTime = timeData.shape[0]
|
|
1314
|
-
|
|
1315
|
-
interpVal = self._result_core_func(timeData,
|
|
1316
|
-
phiOffset =
|
|
1314
|
+
phi_delay = phiOffset + linspace(0, nTime / self.sample_freq * omega, nTime, endpoint=False)
|
|
1315
|
+
interpVal = self._result_core_func(timeData, phi_delay, period, self.Q, interp_at_zero=False)
|
|
1316
|
+
phiOffset = phi_delay[-1] + omega / self.sample_freq
|
|
1317
1317
|
yield interpVal
|
|
1318
1318
|
|
|
1319
1319
|
|
|
@@ -1522,13 +1522,13 @@ class TimeReverse(TimeInOut):
|
|
|
1522
1522
|
The last block may be shorter than num.
|
|
1523
1523
|
|
|
1524
1524
|
"""
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
temp = empty_like(
|
|
1528
|
-
h =
|
|
1525
|
+
result_list = []
|
|
1526
|
+
result_list.extend(self.source.result(num))
|
|
1527
|
+
temp = empty_like(result_list[0])
|
|
1528
|
+
h = result_list.pop()
|
|
1529
1529
|
nsh = h.shape[0]
|
|
1530
1530
|
temp[:nsh] = h[::-1]
|
|
1531
|
-
for h in
|
|
1531
|
+
for h in result_list[::-1]:
|
|
1532
1532
|
temp[nsh:] = h[: nsh - 1 : -1]
|
|
1533
1533
|
yield temp
|
|
1534
1534
|
temp[:nsh] = h[nsh - 1 :: -1]
|
|
@@ -2142,7 +2142,7 @@ class WriteH5(TimeInOut):
|
|
|
2142
2142
|
break
|
|
2143
2143
|
try:
|
|
2144
2144
|
data = next(source_gen)
|
|
2145
|
-
except:
|
|
2145
|
+
except StopIteration:
|
|
2146
2146
|
break
|
|
2147
2147
|
f5h.append_data(ac, data[:anz])
|
|
2148
2148
|
yield data
|
|
@@ -2376,13 +2376,13 @@ class TimeConvolve(TimeInOut):
|
|
|
2376
2376
|
L = self.kernel.shape[0]
|
|
2377
2377
|
N = self.source.numchannels
|
|
2378
2378
|
M = self.source.numsamples
|
|
2379
|
-
|
|
2379
|
+
numblocks_kernel = int(ceil(L / num)) # number of kernel blocks
|
|
2380
2380
|
Q = int(ceil(M / num)) # number of signal blocks
|
|
2381
2381
|
R = int(ceil((L + M - 1) / num)) # number of output blocks
|
|
2382
2382
|
last_size = (L + M - 1) % num # size of final block
|
|
2383
2383
|
|
|
2384
2384
|
idx = 0
|
|
2385
|
-
|
|
2385
|
+
fdl = zeros([numblocks_kernel, num + 1, N], dtype='complex128')
|
|
2386
2386
|
buff = zeros([2 * num, N]) # time-domain input buffer
|
|
2387
2387
|
spec_sum = zeros([num + 1, N], dtype='complex128')
|
|
2388
2388
|
|
|
@@ -2392,16 +2392,16 @@ class TimeConvolve(TimeInOut):
|
|
|
2392
2392
|
|
|
2393
2393
|
# for very short signals, we are already done
|
|
2394
2394
|
if R == 1:
|
|
2395
|
-
|
|
2396
|
-
spec_sum = _spectral_sum(spec_sum,
|
|
2395
|
+
_append_to_fdl(fdl, idx, numblocks_kernel, rfft(buff, axis=0))
|
|
2396
|
+
spec_sum = _spectral_sum(spec_sum, fdl, self._kernel_blocks)
|
|
2397
2397
|
# truncate s.t. total length is L+M-1 (like numpy convolve w/ mode="full")
|
|
2398
2398
|
yield irfft(spec_sum, axis=0)[num : last_size + num]
|
|
2399
2399
|
return
|
|
2400
2400
|
|
|
2401
2401
|
# stream processing of source signal
|
|
2402
2402
|
for temp in signal_blocks:
|
|
2403
|
-
|
|
2404
|
-
spec_sum = _spectral_sum(spec_sum,
|
|
2403
|
+
_append_to_fdl(fdl, idx, numblocks_kernel, rfft(buff, axis=0))
|
|
2404
|
+
spec_sum = _spectral_sum(spec_sum, fdl, self._kernel_blocks)
|
|
2405
2405
|
yield irfft(spec_sum, axis=0)[num:]
|
|
2406
2406
|
buff = concatenate(
|
|
2407
2407
|
[buff[num:], zeros([num, N])],
|
|
@@ -2410,33 +2410,33 @@ class TimeConvolve(TimeInOut):
|
|
|
2410
2410
|
buff[num : num + temp.shape[0]] = temp # append new time-data
|
|
2411
2411
|
|
|
2412
2412
|
for _ in range(R - Q):
|
|
2413
|
-
|
|
2414
|
-
spec_sum = _spectral_sum(spec_sum,
|
|
2413
|
+
_append_to_fdl(fdl, idx, numblocks_kernel, rfft(buff, axis=0))
|
|
2414
|
+
spec_sum = _spectral_sum(spec_sum, fdl, self._kernel_blocks)
|
|
2415
2415
|
yield irfft(spec_sum, axis=0)[num:]
|
|
2416
2416
|
buff = concatenate(
|
|
2417
2417
|
[buff[num:], zeros([num, N])],
|
|
2418
2418
|
axis=0,
|
|
2419
2419
|
) # shift input buffer to the left
|
|
2420
2420
|
|
|
2421
|
-
|
|
2422
|
-
spec_sum = _spectral_sum(spec_sum,
|
|
2421
|
+
_append_to_fdl(fdl, idx, numblocks_kernel, rfft(buff, axis=0))
|
|
2422
|
+
spec_sum = _spectral_sum(spec_sum, fdl, self._kernel_blocks)
|
|
2423
2423
|
# truncate s.t. total length is L+M-1 (like numpy convolve w/ mode="full")
|
|
2424
2424
|
yield irfft(spec_sum, axis=0)[num : last_size + num]
|
|
2425
2425
|
|
|
2426
2426
|
|
|
2427
2427
|
@nb.jit(nopython=True, cache=True)
|
|
2428
|
-
def
|
|
2429
|
-
|
|
2430
|
-
idx = int(idx + 1 %
|
|
2428
|
+
def _append_to_fdl(fdl, idx, numblocks_kernel, buff):
|
|
2429
|
+
fdl[idx] = buff
|
|
2430
|
+
idx = int(idx + 1 % numblocks_kernel)
|
|
2431
2431
|
|
|
2432
2432
|
|
|
2433
2433
|
@nb.jit(nopython=True, cache=True)
|
|
2434
|
-
def _spectral_sum(out,
|
|
2435
|
-
P, B, N =
|
|
2434
|
+
def _spectral_sum(out, fdl, kb):
|
|
2435
|
+
P, B, N = kb.shape
|
|
2436
2436
|
for n in range(N):
|
|
2437
2437
|
for b in range(B):
|
|
2438
2438
|
out[b, n] = 0
|
|
2439
2439
|
for i in range(P):
|
|
2440
|
-
out[b, n] +=
|
|
2440
|
+
out[b, n] += fdl[i, b, n] * kb[i, b, n]
|
|
2441
2441
|
|
|
2442
2442
|
return out
|
acoular/version.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: acoular
|
|
3
|
-
Version: 24.
|
|
3
|
+
Version: 24.7
|
|
4
4
|
Summary: Python library for acoustic beamforming
|
|
5
5
|
Project-URL: homepage, https://acoular.org
|
|
6
6
|
Project-URL: documentation, https://acoular.org
|
|
@@ -50,11 +50,25 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
50
50
|
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
51
51
|
Requires-Python: <=12,>=3.8
|
|
52
52
|
Requires-Dist: numba
|
|
53
|
-
Requires-Dist: numpy
|
|
53
|
+
Requires-Dist: numpy<2.0
|
|
54
54
|
Requires-Dist: scikit-learn
|
|
55
55
|
Requires-Dist: scipy>=1.1.0
|
|
56
56
|
Requires-Dist: tables>=3.4.4
|
|
57
57
|
Requires-Dist: traits>=6.0
|
|
58
|
+
Provides-Extra: dev
|
|
59
|
+
Requires-Dist: graphviz; extra == 'dev'
|
|
60
|
+
Requires-Dist: hatch; extra == 'dev'
|
|
61
|
+
Requires-Dist: ipython; extra == 'dev'
|
|
62
|
+
Requires-Dist: matplotlib; extra == 'dev'
|
|
63
|
+
Requires-Dist: numpydoc; extra == 'dev'
|
|
64
|
+
Requires-Dist: pickleshare; extra == 'dev'
|
|
65
|
+
Requires-Dist: pylops; extra == 'dev'
|
|
66
|
+
Requires-Dist: pytest; extra == 'dev'
|
|
67
|
+
Requires-Dist: ruff==0.4.1; extra == 'dev'
|
|
68
|
+
Requires-Dist: sounddevice; extra == 'dev'
|
|
69
|
+
Requires-Dist: sphinx; extra == 'dev'
|
|
70
|
+
Requires-Dist: sphinx-gallery; extra == 'dev'
|
|
71
|
+
Requires-Dist: traitsui; extra == 'dev'
|
|
58
72
|
Provides-Extra: full
|
|
59
73
|
Requires-Dist: matplotlib; extra == 'full'
|
|
60
74
|
Requires-Dist: pylops; extra == 'full'
|
|
@@ -135,12 +149,17 @@ For more detailed installation instructions, see the [documentation](https://aco
|
|
|
135
149
|
# Documentation and help
|
|
136
150
|
Documentation is available [here](https://acoular.org) with a
|
|
137
151
|
[getting started](https://acoular.org/get_started/index.html) section and
|
|
138
|
-
[examples](https://acoular.org/
|
|
152
|
+
[examples](https://acoular.org/auto_examples/index.html).
|
|
139
153
|
|
|
140
154
|
The Acoular [blog](https://acoular.github.io/blog/) contains some tutorials.
|
|
141
155
|
|
|
142
156
|
If you discover problems with the Acoular software, please report them using the [issue tracker](https://github.com/acoular/acoular/issues) on GitHub. Please use the [Acoular discussions forum](https://github.com/acoular/acoular/discussions) for practical questions, discussions, and demos.
|
|
143
157
|
|
|
158
|
+
# Contributing
|
|
159
|
+
|
|
160
|
+
We are always happy to welcome new contributors to the project.
|
|
161
|
+
If you are interested in contributing, have a look at the [CONTRIBUTING.md](CONTRIBUTING.md) file.
|
|
162
|
+
|
|
144
163
|
# Example
|
|
145
164
|
This reads data from 64 microphone channels and computes a beamforming map for the 8kHz third octave band:
|
|
146
165
|
|
|
@@ -176,5 +195,6 @@ interpolation='bicubic')
|
|
|
176
195
|
colorbar()
|
|
177
196
|
```
|
|
178
197
|
|
|
179
|
-
|
|
180
198
|

|
|
199
|
+
|
|
200
|
+
|