acoular 24.3__py3-none-any.whl → 24.5__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.
Files changed (139) hide show
  1. acoular/__init__.py +118 -50
  2. acoular/calib.py +29 -38
  3. acoular/configuration.py +116 -73
  4. acoular/demo/__init__.py +10 -4
  5. acoular/demo/acoular_demo.py +78 -53
  6. acoular/environments.py +265 -262
  7. acoular/fastFuncs.py +361 -191
  8. acoular/fbeamform.py +1460 -1404
  9. acoular/grids.py +501 -545
  10. acoular/h5cache.py +50 -59
  11. acoular/h5files.py +154 -137
  12. acoular/internal.py +10 -11
  13. acoular/microphones.py +57 -53
  14. acoular/sdinput.py +47 -52
  15. acoular/signals.py +167 -179
  16. acoular/sources.py +818 -693
  17. acoular/spectra.py +349 -359
  18. acoular/tbeamform.py +414 -413
  19. acoular/tfastfuncs.py +178 -101
  20. acoular/tools/__init__.py +25 -0
  21. acoular/tools/aiaa.py +186 -0
  22. acoular/tools/helpers.py +189 -0
  23. acoular/tools/metrics.py +165 -0
  24. acoular/tprocess.py +1201 -1143
  25. acoular/traitsviews.py +513 -501
  26. acoular/trajectory.py +50 -52
  27. acoular/version.py +5 -6
  28. acoular/xml/minidsp_uma-16.xml +20 -0
  29. acoular/xml/{minidsp_uma16.xml → minidsp_uma-16_mirrored.xml} +3 -0
  30. {acoular-24.3.dist-info → acoular-24.5.dist-info}/METADATA +45 -46
  31. acoular-24.5.dist-info/RECORD +50 -0
  32. {acoular-24.3.dist-info → acoular-24.5.dist-info}/WHEEL +1 -1
  33. acoular-24.5.dist-info/licenses/LICENSE +28 -0
  34. acoular/fileimport.py +0 -380
  35. acoular/nidaqimport.py +0 -273
  36. acoular/tests/reference_data/BeamformerBase.npy +0 -0
  37. acoular/tests/reference_data/BeamformerBaseFalse1.npy +0 -0
  38. acoular/tests/reference_data/BeamformerBaseFalse2.npy +0 -0
  39. acoular/tests/reference_data/BeamformerBaseFalse3.npy +0 -0
  40. acoular/tests/reference_data/BeamformerBaseFalse4.npy +0 -0
  41. acoular/tests/reference_data/BeamformerBaseTrue1.npy +0 -0
  42. acoular/tests/reference_data/BeamformerBaseTrue2.npy +0 -0
  43. acoular/tests/reference_data/BeamformerBaseTrue3.npy +0 -0
  44. acoular/tests/reference_data/BeamformerBaseTrue4.npy +0 -0
  45. acoular/tests/reference_data/BeamformerCMFLassoLarsBIC.npy +0 -0
  46. acoular/tests/reference_data/BeamformerCMFNNLS.npy +0 -0
  47. acoular/tests/reference_data/BeamformerCapon.npy +0 -0
  48. acoular/tests/reference_data/BeamformerClean.npy +0 -0
  49. acoular/tests/reference_data/BeamformerCleansc.npy +0 -0
  50. acoular/tests/reference_data/BeamformerCleant.npy +0 -0
  51. acoular/tests/reference_data/BeamformerCleantSq.npy +0 -0
  52. acoular/tests/reference_data/BeamformerCleantSqTraj.npy +0 -0
  53. acoular/tests/reference_data/BeamformerCleantTraj.npy +0 -0
  54. acoular/tests/reference_data/BeamformerDamas.npy +0 -0
  55. acoular/tests/reference_data/BeamformerDamasPlus.npy +0 -0
  56. acoular/tests/reference_data/BeamformerEig.npy +0 -0
  57. acoular/tests/reference_data/BeamformerEigFalse1.npy +0 -0
  58. acoular/tests/reference_data/BeamformerEigFalse2.npy +0 -0
  59. acoular/tests/reference_data/BeamformerEigFalse3.npy +0 -0
  60. acoular/tests/reference_data/BeamformerEigFalse4.npy +0 -0
  61. acoular/tests/reference_data/BeamformerEigTrue1.npy +0 -0
  62. acoular/tests/reference_data/BeamformerEigTrue2.npy +0 -0
  63. acoular/tests/reference_data/BeamformerEigTrue3.npy +0 -0
  64. acoular/tests/reference_data/BeamformerEigTrue4.npy +0 -0
  65. acoular/tests/reference_data/BeamformerFunctional.npy +0 -0
  66. acoular/tests/reference_data/BeamformerGIB.npy +0 -0
  67. acoular/tests/reference_data/BeamformerGridlessOrth.npy +0 -0
  68. acoular/tests/reference_data/BeamformerMusic.npy +0 -0
  69. acoular/tests/reference_data/BeamformerOrth.npy +0 -0
  70. acoular/tests/reference_data/BeamformerSODIX.npy +0 -0
  71. acoular/tests/reference_data/BeamformerTime.npy +0 -0
  72. acoular/tests/reference_data/BeamformerTimeSq.npy +0 -0
  73. acoular/tests/reference_data/BeamformerTimeSqTraj.npy +0 -0
  74. acoular/tests/reference_data/BeamformerTimeTraj.npy +0 -0
  75. acoular/tests/reference_data/Environment.npy +0 -0
  76. acoular/tests/reference_data/Example1_numerical_values_testsum.h5 +0 -0
  77. acoular/tests/reference_data/FiltFiltOctave__.npy +0 -0
  78. acoular/tests/reference_data/FiltFiltOctave_band_100_0_fraction_Thirdoctave_.npy +0 -0
  79. acoular/tests/reference_data/FiltFreqWeight_weight_A_.npy +0 -0
  80. acoular/tests/reference_data/FiltFreqWeight_weight_C_.npy +0 -0
  81. acoular/tests/reference_data/FiltFreqWeight_weight_Z_.npy +0 -0
  82. acoular/tests/reference_data/FiltOctave__.npy +0 -0
  83. acoular/tests/reference_data/FiltOctave_band_100_0_fraction_Thirdoctave_.npy +0 -0
  84. acoular/tests/reference_data/Filter__.npy +0 -0
  85. acoular/tests/reference_data/GeneralFlowEnvironment.npy +0 -0
  86. acoular/tests/reference_data/OctaveFilterBank__.npy +0 -0
  87. acoular/tests/reference_data/OpenJet.npy +0 -0
  88. acoular/tests/reference_data/PointSource.npy +0 -0
  89. acoular/tests/reference_data/PowerSpectra_csm.npy +0 -0
  90. acoular/tests/reference_data/PowerSpectra_ev.npy +0 -0
  91. acoular/tests/reference_data/RotatingFlow.npy +0 -0
  92. acoular/tests/reference_data/SlotJet.npy +0 -0
  93. acoular/tests/reference_data/TimeAverage__.npy +0 -0
  94. acoular/tests/reference_data/TimeCumAverage__.npy +0 -0
  95. acoular/tests/reference_data/TimeExpAverage_weight_F_.npy +0 -0
  96. acoular/tests/reference_data/TimeExpAverage_weight_I_.npy +0 -0
  97. acoular/tests/reference_data/TimeExpAverage_weight_S_.npy +0 -0
  98. acoular/tests/reference_data/TimeInOut__.npy +0 -0
  99. acoular/tests/reference_data/TimePower__.npy +0 -0
  100. acoular/tests/reference_data/TimeReverse__.npy +0 -0
  101. acoular/tests/reference_data/UniformFlowEnvironment.npy +0 -0
  102. acoular/tests/reference_data/beamformer_traj_time_data.h5 +0 -0
  103. acoular/tests/run_tests.sh +0 -18
  104. acoular/tests/run_tests_osx.sh +0 -16
  105. acoular/tests/test.npy +0 -0
  106. acoular/tests/test_beamformer_results.py +0 -213
  107. acoular/tests/test_classes.py +0 -60
  108. acoular/tests/test_digest.py +0 -125
  109. acoular/tests/test_environments.py +0 -73
  110. acoular/tests/test_example1.py +0 -124
  111. acoular/tests/test_grid.py +0 -92
  112. acoular/tests/test_integrate.py +0 -102
  113. acoular/tests/test_signals.py +0 -60
  114. acoular/tests/test_sources.py +0 -65
  115. acoular/tests/test_spectra.py +0 -38
  116. acoular/tests/test_timecache.py +0 -35
  117. acoular/tests/test_tprocess.py +0 -90
  118. acoular/tests/test_traj_beamformer_results.py +0 -164
  119. acoular/tests/unsupported/SpeedComparison/OvernightTestcasesBeamformer_nMics32_nGridPoints100_nFreqs4_nTrials10.png +0 -0
  120. acoular/tests/unsupported/SpeedComparison/cythonBeamformer.pyx +0 -237
  121. acoular/tests/unsupported/SpeedComparison/mainForCython.py +0 -103
  122. acoular/tests/unsupported/SpeedComparison/mainForParallelJit.py +0 -143
  123. acoular/tests/unsupported/SpeedComparison/setupCythonOpenMP.py +0 -63
  124. acoular/tests/unsupported/SpeedComparison/sharedFunctions.py +0 -153
  125. acoular/tests/unsupported/SpeedComparison/timeOverNMics_AllImportantMethods.png +0 -0
  126. acoular/tests/unsupported/SpeedComparison/timeOverNMics_faverage.png +0 -0
  127. acoular/tests/unsupported/SpeedComparison/vglOptimierungFAverage.py +0 -204
  128. acoular/tests/unsupported/SpeedComparison/vglOptimierungGaussSeidel.py +0 -182
  129. acoular/tests/unsupported/SpeedComparison/vglOptimierungR_BEAMFULL_INVERSE.py +0 -764
  130. acoular/tests/unsupported/SpeedComparison/vglOptimierungR_BEAM_OS.py +0 -231
  131. acoular/tests/unsupported/SpeedComparison/whatsFastestWayFor_absASquared.py +0 -48
  132. acoular/tests/unsupported/functionalBeamformer.py +0 -123
  133. acoular/tests/unsupported/precisionTest.py +0 -153
  134. acoular/tests/unsupported/validationOfBeamformerFuncsPOSTAcoularIntegration.py +0 -254
  135. acoular/tests/unsupported/validationOfBeamformerFuncsPREeAcoularIntegration.py +0 -531
  136. acoular/tools.py +0 -422
  137. acoular-24.3.dist-info/RECORD +0 -148
  138. acoular-24.3.dist-info/licenses/LICENSE +0 -29
  139. {acoular-24.3.dist-info → acoular-24.5.dist-info}/licenses/AUTHORS.rst +0 -0
@@ -0,0 +1,189 @@
1
+ # ------------------------------------------------------------------------------
2
+ # Copyright (c) Acoular Development Team.
3
+ # ------------------------------------------------------------------------------
4
+ """Implements some helper functions that are useful for Acoular.
5
+
6
+ .. autosummary::
7
+ :toctree: generated/
8
+
9
+ return_result
10
+ barspectrum
11
+ bardata
12
+ """
13
+
14
+ from numpy import (
15
+ array,
16
+ concatenate,
17
+ newaxis,
18
+ where,
19
+ )
20
+ from numpy.ma import masked_where
21
+
22
+ from acoular.spectra import synthetic
23
+
24
+
25
+ def return_result(source, nmax=-1, num=128):
26
+ """Collects the output from a
27
+ :meth:`SamplesGenerator.result()<acoular.tprocess.SamplesGenerator.result>`
28
+ generator and returns an assembled array with all the data.
29
+
30
+ Parameters
31
+ ----------
32
+ source: SamplesGenerator or derived object.
33
+ This is the :class:`SamplesGenerator<acoular.tprocess.SamplesGenerator>` data source.
34
+ nmax: integer
35
+ With this parameter, a maximum number of output samples can be set
36
+ (first dimension of array). If set to -1 (default), samples are
37
+ collected as long as the generator yields them.
38
+ num : integer
39
+ This parameter defines the size of the blocks that are fetched.
40
+ Defaults to 128.
41
+
42
+ Returns
43
+ -------
44
+ array of floats (number of samples, source.numchannels)
45
+ Array that holds all the data.
46
+
47
+ """
48
+ resulter = (_.copy() for _ in source.result(num))
49
+
50
+ if nmax > 0:
51
+ nblocks = (nmax - 1) // num + 1
52
+ return concatenate([res for _, res in zip(range(nblocks), resulter)])[:nmax]
53
+ return concatenate(list(resulter))
54
+
55
+
56
+ def barspectrum(data, fftfreqs, num=3, bar=True, xoffset=0.0):
57
+ """Returns synthesized frequency band values of spectral data to be plotted
58
+ as bar graph with the matlpotlib plot command.
59
+
60
+
61
+ Parameters
62
+ ----------
63
+ data : array of floats
64
+ The spectral data (sound pressures in Pa) in an array with one value
65
+ per frequency line.
66
+ fftfreqs : array of floats
67
+ Discrete frequencies from FFT.
68
+ num : integer
69
+ Controls the width of the frequency bands considered; defaults to
70
+ 3 (third-octave band).
71
+ bar : bool
72
+ If True, returns bar-like curve. If False, normal plot (direct
73
+ line between data points) is returned.
74
+ xoffset : float
75
+ If bar is True, offset of the perpendicular line (helpful if
76
+ plotting several curves above each other).
77
+
78
+ === =====================
79
+ num frequency band width
80
+ === =====================
81
+ 1 octave band
82
+ 3 third-octave band
83
+ === =====================
84
+
85
+ Returns
86
+ -------
87
+ (flulist, plist, fc)
88
+ flulist : array of floats
89
+ Lower/upper band frequencies in plottable format.
90
+ plist : array of floats
91
+ Corresponding synthesized frequency band values in plottable format.
92
+ fc : array of floats
93
+ Evaluated band center frequencies.
94
+
95
+ """
96
+ if num not in [1, 3]:
97
+ print('Only octave and third-octave bands supported at this moment.')
98
+ return (0, 0, 0)
99
+
100
+ # preferred center freqs after din en iso 266 for third-octave bands
101
+ fcbase = array([31.5, 40, 50, 63, 80, 100, 125, 160, 200, 250])
102
+ # DIN band center frequencies from 31.5 Hz to 25 kHz
103
+ fc = concatenate((fcbase, fcbase * 10.0, fcbase[:] * 100.0))[:: (3 // num)]
104
+
105
+ # exponent for band width calculation
106
+ ep = 1.0 / (2.0 * num)
107
+
108
+ # lowest and highest possible center frequencies
109
+ # for chosen band and sampling frequency
110
+ f_low = fftfreqs[1] * 2**ep
111
+ f_high = fftfreqs[-1] * 2**-ep
112
+ # get possible index range
113
+ i_low = 0 if fc[0] >= f_low else where(fc < f_low)[0][-1]
114
+
115
+ i_high = fc.shape[0] if fc[-1] <= f_high else where(fc > f_high)[0][0]
116
+
117
+ # synthesize sound pressure values
118
+ p = array([synthetic(data, fftfreqs, list(fc[i_low:i_high]), num)])
119
+
120
+ if bar:
121
+ # upper and lower band borders
122
+ flu = concatenate(
123
+ (
124
+ fc[i_low : i_low + 1] * 2**-ep,
125
+ (fc[i_low : i_high - 1] * 2**ep + fc[i_low + 1 : i_high] * 2**-ep) / 2.0,
126
+ fc[i_high - 1 : i_high] * 2**ep,
127
+ ),
128
+ )
129
+ # band borders as coordinates for bar plotting
130
+ flulist = 2 ** (2 * xoffset * ep) * (array([1, 1])[:, newaxis] * flu[newaxis, :]).T.reshape(-1)[1:-1]
131
+ # sound pressures as list for bar plotting
132
+ plist = (array([1, 1])[:, newaxis] * p[newaxis, :]).T.reshape(-1)
133
+ else:
134
+ flulist = fc[i_low:i_high]
135
+ plist = p[0, :]
136
+ # print(flulist.shape, plist.shape)
137
+ return (flulist, plist, fc[i_low:i_high])
138
+
139
+
140
+ def bardata(data, fc, num=3, bar=True, xoffset=0.0, masked=-360):
141
+ """Returns data to be plotted
142
+ as bar graph with the matlpotlib plot command.
143
+
144
+
145
+ Parameters
146
+ ----------
147
+ data : array of floats
148
+ The spectral data
149
+ fc : array of floats
150
+ Band center frequencies
151
+ bar : bool
152
+ If True, returns bar-like curve. If False, normal plot (direct
153
+ line between data points) is returned.
154
+ xoffset : float
155
+ If bar is True, offset of the perpendicular line (helpful if
156
+ plotting several curves above each other).
157
+
158
+ === =====================
159
+ num frequency band width
160
+ === =====================
161
+ 1 octave band
162
+ 3 third-octave band
163
+ === =====================
164
+
165
+ Returns
166
+ -------
167
+ (flulist, plist)
168
+ flulist : array of floats
169
+ Lower/upper band frequencies in plottable format.
170
+ plist : array of floats
171
+ Corresponding values in plottable format.
172
+
173
+ """
174
+ ep = 1.0 / (2.0 * num)
175
+
176
+ if bar:
177
+ # upper and lower band borders
178
+ flu = concatenate((fc[:1] * 2**-ep, (fc[:-1] * 2**ep + fc[1:] * 2**-ep) / 2.0, fc[-1:] * 2**ep))
179
+ # band borders as coordinates for bar plotting
180
+ flulist = 2 ** (xoffset * 1.0 / num) * (array([1, 1])[:, newaxis] * flu[newaxis, :]).T.reshape(-1)[1:-1]
181
+ # sound pressures as list for bar plotting
182
+ plist = (array([1, 1])[:, newaxis] * data[newaxis, :]).T.reshape(-1)
183
+ else:
184
+ flulist = fc
185
+ plist = data
186
+ # print(flulist.shape, plist.shape)
187
+ if masked > -360:
188
+ plist = masked_where(plist <= masked, plist)
189
+ return (flulist, plist)
@@ -0,0 +1,165 @@
1
+ # ------------------------------------------------------------------------------
2
+ # Copyright (c) Acoular Development Team.
3
+ # ------------------------------------------------------------------------------
4
+ """Implements metrics for evaluating signal processing results.
5
+
6
+ .. autosummary::
7
+ :toctree: generated/
8
+
9
+ MetricEvaluator
10
+ """
11
+
12
+ from copy import copy
13
+
14
+ from numpy import (
15
+ empty,
16
+ inf,
17
+ minimum,
18
+ ones,
19
+ )
20
+ from scipy.spatial.distance import cdist
21
+ from traits.api import Bool, CArray, HasPrivateTraits, Instance, Property
22
+
23
+ from acoular.fbeamform import L_p, integrate
24
+ from acoular.grids import CircSector, Grid
25
+
26
+
27
+ class MetricEvaluator(HasPrivateTraits):
28
+ """Evaluate the reconstruction performance of source mapping methods.
29
+
30
+ This class can be used to calculate the following performance metrics
31
+ according to Herold and Sarradj (2017):
32
+ * Specific level error
33
+ * Overall level error
34
+ * Inverse level error
35
+ """
36
+
37
+ #: an array of shape=(nf,ng) containing the squared sound pressure data of the
38
+ #: source mapping. (nf: number of frequencies, ng: number of grid points)
39
+ data = CArray(shape=(None, None), desc='Contains the calculated squared sound pressure values in Pa**2.')
40
+
41
+ #: an array of shape=(nf,ns) containing the squared sound pressure data of the
42
+ #: ground-truth sources. (nf: number of frequencies, ns: number of sources)
43
+ target_data = CArray(shape=(None, None), desc='Contains the ground-truth squared sound pressure values in Pa**2.')
44
+
45
+ #: :class:`~acoular.grids.Grid`-derived object that provides the grid locations
46
+ #: for the calculated source mapping data.
47
+ grid = Instance(Grid, desc='Grid instance that belongs to the calculated data')
48
+
49
+ #: :class:`~acoular.grids.Grid`-derived object that provides the grid locations
50
+ #: for the ground-truth data.
51
+ target_grid = Instance(Grid, desc='Grid instance that belongs to the ground-truth data')
52
+
53
+ #: sector type. Currently only circular sectors are supported.
54
+ sector = Instance(CircSector, default=CircSector())
55
+
56
+ #: if set True: use shrink integration area if two sources are closer
57
+ #: than 2*r. The radius of the integration area is then set to half the
58
+ #: distance between the two sources.
59
+ adaptive_sector_size = Bool(True, desc='adaptive integration area')
60
+
61
+ #: if set `True`, the same amplitude can be assigned to multiple targets if
62
+ #: the integration area overlaps. If set `False`, the amplitude is assigned
63
+ #: to the first target and the other targets are ignored.
64
+ multi_assignment = Bool(
65
+ True,
66
+ desc='if set True, the same amplitude can be assigned to multiple targets if the integration area overlaps',
67
+ )
68
+
69
+ #: returns the determined sector sizes for each ground-truth source position
70
+ sectors = Property()
71
+
72
+ def _validate_shapes(self):
73
+ if self.data.shape[0] != self.target_data.shape[0]:
74
+ msg = 'data and target_data must have the same number of frequencies!'
75
+ raise ValueError(msg)
76
+ if self.data.shape[1] != self.grid.size:
77
+ msg = 'data and grid must have the same number of grid points!'
78
+ raise ValueError(msg)
79
+ if self.target_data.shape[1] != self.target_grid.size:
80
+ msg = 'target_data and target_grid must have the same number of grid points!'
81
+ raise ValueError(msg)
82
+
83
+ def _get_sector_radii(self):
84
+ ns = self.target_data.shape[1]
85
+ radii = ones(ns) * self.sector.r
86
+ if self.adaptive_sector_size:
87
+ locs = self.target_grid.gpos.T
88
+ intersrcdist = cdist(locs, locs)
89
+ intersrcdist[intersrcdist == 0] = inf
90
+ intersrcdist = intersrcdist.min(0) / 2
91
+ radii = minimum(radii, intersrcdist)
92
+ return radii
93
+
94
+ def _get_sectors(self):
95
+ """Returns a list of CircSector objects for each target location."""
96
+ r = self._get_sector_radii()
97
+ ns = self.target_data.shape[1]
98
+ sectors = []
99
+ for i in range(ns):
100
+ loc = self.target_grid.gpos[:, i]
101
+ sector = copy(self.sector)
102
+ sector.r = r[i]
103
+ sector.x = loc[0]
104
+ sector.y = loc[1]
105
+ sectors.append(sector)
106
+ return sectors
107
+
108
+ def _integrate_sectors(self):
109
+ """Integrates over target sectors.
110
+
111
+ Returns
112
+ -------
113
+ array (num_freqs,num_sources)
114
+ returns the integrated Pa**2 values for each sector
115
+
116
+ """
117
+ sectors = self.sectors
118
+ results = empty(shape=self.target_data.shape)
119
+ for f in range(self.target_data.shape[0]):
120
+ data = self.data[f]
121
+ for i in range(self.target_data.shape[1]):
122
+ sector = sectors[i]
123
+ results[f, i] = integrate(data, self.grid, sector)
124
+ if not self.multi_assignment:
125
+ indices = self.grid.subdomain(sector)
126
+ data[indices] = 0 # set values to zero (can not be assigned again)
127
+ return results
128
+
129
+ def get_overall_level_error(self):
130
+ """Returns the overall level error (Herold and Sarradj, 2017).
131
+
132
+ Returns
133
+ -------
134
+ numpy.array
135
+ overall level error of shape=(nf,)
136
+
137
+ """
138
+ self._validate_shapes()
139
+ return L_p(self.data.sum(axis=1)) - L_p(self.target_data.sum(axis=1))
140
+
141
+ def get_specific_level_error(self):
142
+ """Returns the specific level error (Herold and Sarradj, 2017).
143
+
144
+ Returns
145
+ -------
146
+ numpy.array
147
+ specific level error of shape=(nf,ns). nf: number of frequencies, ns: number of sources
148
+
149
+ """
150
+ self._validate_shapes()
151
+ sector_result = self._integrate_sectors()
152
+ return L_p(sector_result) - L_p(self.target_data)
153
+
154
+ def get_inverse_level_error(self):
155
+ """Returns the inverse level error (Herold and Sarradj, 2017).
156
+
157
+ Returns
158
+ -------
159
+ numpy.array
160
+ inverse level error of shape=(nf,1)
161
+
162
+ """
163
+ self._validate_shapes()
164
+ sector_result = self._integrate_sectors()
165
+ return L_p(sector_result.sum(axis=1)) - L_p(self.data.sum(axis=1))