acoular 24.7__py3-none-any.whl → 24.10__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 +17 -8
- acoular/base.py +312 -0
- acoular/configuration.py +3 -3
- acoular/demo/acoular_demo.py +1 -1
- acoular/environments.py +7 -5
- acoular/fbeamform.py +221 -58
- acoular/fprocess.py +368 -0
- acoular/grids.py +31 -17
- acoular/process.py +464 -0
- acoular/sdinput.py +14 -3
- acoular/signals.py +6 -6
- acoular/sources.py +20 -7
- acoular/spectra.py +29 -48
- acoular/tbeamform.py +264 -141
- acoular/tools/__init__.py +2 -0
- acoular/tools/aiaa.py +3 -3
- acoular/tools/helpers.py +2 -2
- acoular/tools/metrics.py +1 -1
- acoular/tools/utils.py +210 -0
- acoular/tprocess.py +89 -453
- acoular/traitsviews.py +5 -3
- acoular/version.py +2 -2
- {acoular-24.7.dist-info → acoular-24.10.dist-info}/METADATA +28 -7
- {acoular-24.7.dist-info → acoular-24.10.dist-info}/RECORD +27 -23
- {acoular-24.7.dist-info → acoular-24.10.dist-info}/WHEEL +0 -0
- {acoular-24.7.dist-info → acoular-24.10.dist-info}/licenses/AUTHORS.rst +0 -0
- {acoular-24.7.dist-info → acoular-24.10.dist-info}/licenses/LICENSE +0 -0
acoular/tools/__init__.py
CHANGED
acoular/tools/aiaa.py
CHANGED
|
@@ -54,13 +54,13 @@ class TimeSamplesAIAABenchmark(TimeSamples):
|
|
|
54
54
|
objects.
|
|
55
55
|
"""
|
|
56
56
|
|
|
57
|
-
def
|
|
57
|
+
def _load_timedata(self):
|
|
58
58
|
"""Loads timedata from .h5 file. Only for internal use."""
|
|
59
59
|
self.data = self.h5f.get_data_by_reference('MicrophoneData/microphoneDataPa')
|
|
60
60
|
self.sample_freq = self.h5f.get_node_attribute(self.data, 'sampleRateHz')
|
|
61
61
|
(self.numsamples, self.numchannels) = self.data.shape
|
|
62
62
|
|
|
63
|
-
def
|
|
63
|
+
def _load_metadata(self):
|
|
64
64
|
"""Loads metadata from .h5 file. Only for internal use."""
|
|
65
65
|
self.metadata = {}
|
|
66
66
|
if '/MetaData' in self.h5f:
|
|
@@ -76,7 +76,7 @@ class TriggerAIAABenchmark(TimeSamplesAIAABenchmark):
|
|
|
76
76
|
and and provides information about this data.
|
|
77
77
|
"""
|
|
78
78
|
|
|
79
|
-
def
|
|
79
|
+
def _load_timedata(self):
|
|
80
80
|
"""Loads timedata from .h5 file. Only for internal use."""
|
|
81
81
|
self.data = self.h5f.get_data_by_reference('TachoData/tachoDataV')
|
|
82
82
|
self.sample_freq = self.h5f.get_node_attribute(self.data, 'sampleRateHz')
|
acoular/tools/helpers.py
CHANGED
|
@@ -24,13 +24,13 @@ from acoular.spectra import synthetic
|
|
|
24
24
|
|
|
25
25
|
def return_result(source, nmax=-1, num=128):
|
|
26
26
|
"""Collects the output from a
|
|
27
|
-
:meth:`SamplesGenerator.result()<acoular.
|
|
27
|
+
:meth:`SamplesGenerator.result()<acoular.base.SamplesGenerator.result>`
|
|
28
28
|
generator and returns an assembled array with all the data.
|
|
29
29
|
|
|
30
30
|
Parameters
|
|
31
31
|
----------
|
|
32
32
|
source: SamplesGenerator or derived object.
|
|
33
|
-
This is the :class:`SamplesGenerator<acoular.
|
|
33
|
+
This is the :class:`SamplesGenerator<acoular.base.SamplesGenerator>` data source.
|
|
34
34
|
nmax: integer
|
|
35
35
|
With this parameter, a maximum number of output samples can be set
|
|
36
36
|
(first dimension of array). If set to -1 (default), samples are
|
acoular/tools/metrics.py
CHANGED
|
@@ -28,7 +28,7 @@ class MetricEvaluator(HasPrivateTraits):
|
|
|
28
28
|
"""Evaluate the reconstruction performance of source mapping methods.
|
|
29
29
|
|
|
30
30
|
This class can be used to calculate the following performance metrics
|
|
31
|
-
according
|
|
31
|
+
according :cite:`Herold2017`:
|
|
32
32
|
* Specific level error
|
|
33
33
|
* Overall level error
|
|
34
34
|
* Inverse level error
|
acoular/tools/utils.py
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
"""Utility classes intended for internal use in Acoular.
|
|
2
|
+
|
|
3
|
+
.. autosummary::
|
|
4
|
+
:toctree: generated/
|
|
5
|
+
|
|
6
|
+
SamplesBuffer
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import numpy as np
|
|
10
|
+
from traits.api import Any, Array, Bool, Enum, Int, Property, Union
|
|
11
|
+
|
|
12
|
+
from acoular.process import InOut
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class SamplesBuffer(InOut):
|
|
16
|
+
"""Handles buffering of samples from a source.
|
|
17
|
+
|
|
18
|
+
This class is used to buffer samples from a source and provide them in blocks
|
|
19
|
+
of a specified size. There are several usecases for this class, as demonstrated in
|
|
20
|
+
the following.
|
|
21
|
+
|
|
22
|
+
Examples
|
|
23
|
+
--------
|
|
24
|
+
Let us assume we want to draw blocks of 16 samples from our source, but we want to make sure
|
|
25
|
+
that we always have twice the number of samples in the buffer. We can achieve this simple behaviour
|
|
26
|
+
by using the following code:
|
|
27
|
+
|
|
28
|
+
>>> import acoular as ac
|
|
29
|
+
>>> import numpy as np
|
|
30
|
+
>>> # create a white noise source with 512 samples
|
|
31
|
+
>>> source = ac.TimeSamples(
|
|
32
|
+
... data=ac.WNoiseGenerator(
|
|
33
|
+
... sample_freq=64,
|
|
34
|
+
... numsamples=512,
|
|
35
|
+
... ).signal()[:, np.newaxis],
|
|
36
|
+
... sample_freq=64,
|
|
37
|
+
... )
|
|
38
|
+
>>> # create a buffer with a size of 32 samples
|
|
39
|
+
>>> buffer = ac.tools.SamplesBuffer(source=source, length=32)
|
|
40
|
+
>>> # get the first block of 16 samples
|
|
41
|
+
>>> block = next(buffer.result(num=16))
|
|
42
|
+
>>> np.testing.assert_array_equal(block, source.data[:16])
|
|
43
|
+
|
|
44
|
+
Here, on the first call to the result method, the buffer will fill up by collecting blocks with same size
|
|
45
|
+
from the source. The buffer will then return the first block of 16 samples. On the next call to the result
|
|
46
|
+
method, the buffer will be filled again and returns the next block of 16 samples.
|
|
47
|
+
|
|
48
|
+
In some cases, we might want to draw a different number of samples from the source than we want to return.
|
|
49
|
+
This can be achieved by setting the `source_num` trait of the buffer. A special case is the return of a variable
|
|
50
|
+
number of samples. This is the case, for example, in the class :class:`~acoular.tbeamform.BeamformerTimeTraj`,
|
|
51
|
+
in which a different number of time samples is required from the buffer for further delay-and-sum processing
|
|
52
|
+
depending on the expected delay, which can be vary for moving sources. At the same time, however, only 'num'
|
|
53
|
+
samples should be written to and removed from the buffer. This behavior can be achieved by setting the
|
|
54
|
+
`shift_index_by` trait to 'num' and by setting the `result_num` trait to the number of samples that should be
|
|
55
|
+
returned by the result function.
|
|
56
|
+
|
|
57
|
+
>>> buffer = ac.tools.SamplesBuffer(source=source, length=32, result_num=20, shift_index_by='num')
|
|
58
|
+
>>> block_sizes = []
|
|
59
|
+
>>> block_sizes.append(
|
|
60
|
+
... next(buffer.result(num=16)).shape[0]
|
|
61
|
+
... ) # this time, the buffer will return 20 samples, but the buffer will only forget the first 16 samples
|
|
62
|
+
>>> buffer.result_num = 24
|
|
63
|
+
>>> block_sizes.append(
|
|
64
|
+
... next(buffer.result(num=16)).shape[0]
|
|
65
|
+
... ) # this time, the buffer will return 24 samples, but the buffer will only forget the first 16 samples
|
|
66
|
+
>>> np.testing.assert_array_equal(block_sizes, [20, 24])
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
#: number of samples that fit in the buffer
|
|
70
|
+
length = Int(desc='number of samples that fit in the buffer')
|
|
71
|
+
|
|
72
|
+
#: number of samples per block to obtain from the source. If 'None', use 'num' argument of result method
|
|
73
|
+
source_num = Union(
|
|
74
|
+
None,
|
|
75
|
+
Int(),
|
|
76
|
+
default_value=None,
|
|
77
|
+
desc='number of samples to return from the source. If "None", use "num" argument of result method',
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
#: number of samples to return from the buffer. If 'None', use 'num' argument of result method
|
|
81
|
+
result_num = Union(
|
|
82
|
+
None,
|
|
83
|
+
Int(),
|
|
84
|
+
default_value=None,
|
|
85
|
+
desc="number of samples to return from the buffer. If 'None', use 'num' argument of result method",
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
#: index shift value for the buffer. If "result_num", buffer will return and forget 'result_num' samples.
|
|
89
|
+
#: If "num", buffer will return 'result_num' samples but will forget 'num' samples
|
|
90
|
+
shift_index_by = Enum(
|
|
91
|
+
('result_num', 'num'),
|
|
92
|
+
desc=(
|
|
93
|
+
'index shift value for the buffer. If "result_num", use "result_num" trait.'
|
|
94
|
+
' If "num", use "num" argument of result method'
|
|
95
|
+
),
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
#: current filling level of buffer
|
|
99
|
+
level = Property(desc='current filling level of buffer')
|
|
100
|
+
|
|
101
|
+
#: data type of the buffer elements
|
|
102
|
+
dtype = Any(desc='data type of the buffer')
|
|
103
|
+
|
|
104
|
+
# flag to indicate that the source is empty, for internal use
|
|
105
|
+
_empty_source = Bool(False, desc='flag to indicate that the source is empty')
|
|
106
|
+
|
|
107
|
+
# the buffer for processing
|
|
108
|
+
_buffer = Array(shape=(None, None), desc='buffer for block processing')
|
|
109
|
+
|
|
110
|
+
# current index in buffer
|
|
111
|
+
_index = Int(desc='current index in buffer')
|
|
112
|
+
|
|
113
|
+
def _get_level(self):
|
|
114
|
+
return self._buffer.shape[0] - self._index
|
|
115
|
+
|
|
116
|
+
def _create_new_buffer(self):
|
|
117
|
+
self._buffer = np.zeros((self.length, self.numchannels), dtype=self.dtype)
|
|
118
|
+
self._index = self.length
|
|
119
|
+
self._empty_source = False
|
|
120
|
+
|
|
121
|
+
def _write_to_buffer(self, data):
|
|
122
|
+
ns = data.shape[0]
|
|
123
|
+
self._buffer[0 : (self.length - ns)] = self._buffer[-(self.length - ns) :]
|
|
124
|
+
self._buffer[-ns:, :] = data.astype(self.dtype)
|
|
125
|
+
self._index -= ns
|
|
126
|
+
|
|
127
|
+
def increase_buffer(self, num):
|
|
128
|
+
"""Increase the buffer by 'num' samples.
|
|
129
|
+
|
|
130
|
+
Returns
|
|
131
|
+
-------
|
|
132
|
+
None
|
|
133
|
+
"""
|
|
134
|
+
ar = np.zeros((num, self.numchannels), dtype=self._buffer.dtype)
|
|
135
|
+
self._buffer = np.concatenate((ar, self._buffer), axis=0)
|
|
136
|
+
self._index += num
|
|
137
|
+
self.length += num
|
|
138
|
+
|
|
139
|
+
def read_from_buffer(self, num):
|
|
140
|
+
"""Read samples from the buffer.
|
|
141
|
+
|
|
142
|
+
Parameters
|
|
143
|
+
----------
|
|
144
|
+
num : int
|
|
145
|
+
number of samples to read from the buffer.
|
|
146
|
+
|
|
147
|
+
Returns
|
|
148
|
+
-------
|
|
149
|
+
numpy.ndarray
|
|
150
|
+
block of samples from the buffer
|
|
151
|
+
|
|
152
|
+
"""
|
|
153
|
+
rnum = num if self.result_num is None else self.result_num
|
|
154
|
+
rnum = rnum if self.level >= rnum else self.level
|
|
155
|
+
data = self._buffer[self._index : self._index + rnum]
|
|
156
|
+
if self.shift_index_by == 'result_num':
|
|
157
|
+
self._index += rnum
|
|
158
|
+
else:
|
|
159
|
+
self._index += num
|
|
160
|
+
return data
|
|
161
|
+
|
|
162
|
+
def fill_buffer(self, snum):
|
|
163
|
+
"""Fill the buffer with samples from the source.
|
|
164
|
+
|
|
165
|
+
Parameters
|
|
166
|
+
----------
|
|
167
|
+
snum : int
|
|
168
|
+
number of samples to return from the source.
|
|
169
|
+
|
|
170
|
+
Yields
|
|
171
|
+
------
|
|
172
|
+
None
|
|
173
|
+
"""
|
|
174
|
+
source_generator = self.source.result(snum)
|
|
175
|
+
while not self._empty_source:
|
|
176
|
+
while self._index >= snum:
|
|
177
|
+
if self.result_num is not None:
|
|
178
|
+
while self.result_num > self.length:
|
|
179
|
+
self.increase_buffer(snum)
|
|
180
|
+
try:
|
|
181
|
+
self._write_to_buffer(next(source_generator))
|
|
182
|
+
except StopIteration:
|
|
183
|
+
self._empty_source = True
|
|
184
|
+
break
|
|
185
|
+
yield
|
|
186
|
+
|
|
187
|
+
def result(self, num):
|
|
188
|
+
"""Return blocks of samples from the buffer.
|
|
189
|
+
|
|
190
|
+
Parameters
|
|
191
|
+
----------
|
|
192
|
+
num : int
|
|
193
|
+
number of samples to return.
|
|
194
|
+
|
|
195
|
+
Yields
|
|
196
|
+
------
|
|
197
|
+
numpy.ndarray
|
|
198
|
+
block of samples from the buffer
|
|
199
|
+
"""
|
|
200
|
+
self._create_new_buffer()
|
|
201
|
+
snum = num
|
|
202
|
+
if self.source_num is not None:
|
|
203
|
+
snum = self.source_num
|
|
204
|
+
for _ in self.fill_buffer(snum):
|
|
205
|
+
if self.level > 0:
|
|
206
|
+
yield self.read_from_buffer(num)
|
|
207
|
+
else:
|
|
208
|
+
break
|
|
209
|
+
while self.level > 0:
|
|
210
|
+
yield self.read_from_buffer(num)
|