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.
Files changed (139) hide show
  1. acoular/__init__.py +119 -54
  2. acoular/calib.py +29 -38
  3. acoular/configuration.py +132 -82
  4. acoular/demo/__init__.py +10 -4
  5. acoular/demo/acoular_demo.py +73 -55
  6. acoular/environments.py +270 -264
  7. acoular/fastFuncs.py +366 -196
  8. acoular/fbeamform.py +1797 -1934
  9. acoular/grids.py +504 -548
  10. acoular/h5cache.py +74 -83
  11. acoular/h5files.py +159 -142
  12. acoular/internal.py +13 -14
  13. acoular/microphones.py +57 -53
  14. acoular/sdinput.py +57 -53
  15. acoular/signals.py +180 -178
  16. acoular/sources.py +920 -724
  17. acoular/spectra.py +353 -363
  18. acoular/tbeamform.py +416 -416
  19. acoular/tfastfuncs.py +180 -104
  20. acoular/tools/__init__.py +25 -0
  21. acoular/tools/aiaa.py +185 -0
  22. acoular/tools/helpers.py +189 -0
  23. acoular/tools/metrics.py +165 -0
  24. acoular/tprocess.py +1240 -1182
  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.7.dist-info}/METADATA +58 -39
  31. acoular-24.7.dist-info/RECORD +50 -0
  32. {acoular-24.3.dist-info → acoular-24.7.dist-info}/WHEEL +1 -1
  33. acoular-24.7.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.7.dist-info}/licenses/AUTHORS.rst +0 -0
acoular/fastFuncs.py CHANGED
@@ -1,41 +1,47 @@
1
- #!/usr/bin/env python2
2
- # -*- coding: utf-8 -*-
3
- #------------------------------------------------------------------------------
1
+ # ------------------------------------------------------------------------------
4
2
  # Copyright (c) Acoular Development Team.
5
- #------------------------------------------------------------------------------
6
- """
7
- This file contains all the functionalities which are very expansive, regarding
3
+ # ------------------------------------------------------------------------------
4
+ """Contains all the functionalities which are very expansive, regarding
8
5
  computational costs. All functionalities are optimized via NUMBA.
9
6
  """
10
- import numpy as np
7
+
11
8
  import numba as nb
9
+ import numpy as np
12
10
 
13
- cachedOption = True # if True: saves the numba func as compiled func in sub directory
14
- parallelOption = 'parallel' # if numba.guvectorize is used: 'CPU' for single threading; 'parallel' for multithreading; 'cuda' for calculating on GPU
15
- fastOption = True # fastmath options
11
+ CACHED_OPTION = True # if True: saves the numba func as compiled func in sub directory
12
+ PARALLEL_OPTION = 'parallel' # if numba.guvectorize is used: 'CPU' for single threading; 'parallel' for multithreading; 'cuda' for calculating on GPU
13
+ FAST_OPTION = True # fastmath options
16
14
 
17
15
 
18
16
  # Formerly known as 'faverage'
19
- @nb.njit([nb.complex128[:,:,::1](nb.complex128[:,:,::1], nb.complex128[:,::1]),
20
- nb.complex64[:,:,::1](nb.complex64[:,:,::1], nb.complex64[:,::1])], cache=cachedOption, parallel=True, fastmath=fastOption)
17
+ @nb.njit(
18
+ [
19
+ nb.complex128[:, :, ::1](nb.complex128[:, :, ::1], nb.complex128[:, ::1]),
20
+ nb.complex64[:, :, ::1](nb.complex64[:, :, ::1], nb.complex64[:, ::1]),
21
+ ],
22
+ cache=CACHED_OPTION,
23
+ parallel=True,
24
+ fastmath=FAST_OPTION,
25
+ )
21
26
  def calcCSM(csm, SpecAllMics):
22
- """ Adds a given spectrum to the Cross-Spectral-Matrix (CSM).
27
+ """Adds a given spectrum to the Cross-Spectral-Matrix (CSM).
23
28
  Here only the upper triangular matrix of the CSM is calculated. After
24
- averaging over the various ensembles, the whole CSM is created via complex
25
- conjugation transposing. This happens outside
26
- (in :class:`PowerSpectra<acoular.spectra.PowerSpectra>`).
29
+ averaging over the various ensembles, the whole CSM is created via complex
30
+ conjugation transposing. This happens outside
31
+ (in :class:`PowerSpectra<acoular.spectra.PowerSpectra>`).
27
32
  This method was called 'faverage' in acoular versions <= 16.5.
28
-
33
+
29
34
  Parameters
30
35
  ----------
31
- csm : complex128[nFreqs, nMics, nMics]
36
+ csm : complex128[nFreqs, nMics, nMics]
32
37
  The cross spectral matrix which gets updated with the spectrum of the ensemble.
33
- SpecAllMics : complex128[nFreqs, nMics]
38
+ SpecAllMics : complex128[nFreqs, nMics]
34
39
  Spectrum of the added ensemble at all Mics.
35
-
40
+
36
41
  Returns
37
42
  -------
38
43
  None : as the input csm gets overwritten.
44
+
39
45
  """
40
46
  nFreqs = csm.shape[0]
41
47
  nMics = csm.shape[1]
@@ -46,9 +52,9 @@ def calcCSM(csm, SpecAllMics):
46
52
  csm[cntFreq, cntRow, cntColumn] += temp * SpecAllMics[cntFreq, cntRow]
47
53
  return csm
48
54
 
49
-
55
+
50
56
  def beamformerFreq(steerVecType, boolRemovedDiagOfCSM, normFactor, inputTupleSteer, inputTupleCsm):
51
- """ Conventional beamformer in frequency domain. Use either a predefined
57
+ r"""Conventional beamformer in frequency domain. Use either a predefined
52
58
  steering vector formulation (see Sarradj 2012) or pass your own
53
59
  steering vector.
54
60
 
@@ -83,72 +89,76 @@ def beamformerFreq(steerVecType, boolRemovedDiagOfCSM, normFactor, inputTupleSte
83
89
  perform beamformer on eigenvalue decomposition of csm:
84
90
  inputTupleCsm = (eigValues, eigVectors) , with
85
91
  eigValues : float64[nEV]
86
- nEV is the number of eigenvalues which should be taken into account.
92
+ nEV is the number of eigenvalues which should be taken into account.
87
93
  All passed eigenvalues will be evaluated.
88
94
  eigVectors : complex128[nMics, nEV]
89
95
  Eigen vectors corresponding to eigValues. All passed eigenvector slices will be evaluated.
90
96
 
91
97
  Returns
92
98
  -------
93
- *Autopower spectrum beamforming map [nGridPoints]
94
-
95
- *steer normalization factor [nGridPoints]... contains the values the autopower needs to be multiplied with, in order to
96
- fullfill 'steer^H * steer = 1' as needed for functional beamforming.
97
-
99
+ *Autopower spectrum beamforming map [nGridPoints]
100
+
101
+ *steer normalization factor [nGridPoints]... contains the values the autopower needs to be multiplied with, in order to
102
+ fullfill 'steer^H * steer = 1' as needed for functional beamforming.
103
+
98
104
  Some Notes on the optimization of all subroutines
99
105
  -------------------------------------------------
100
106
  Reducing beamforming equation:
101
- Let the csm be C and the steering vector be h, than, using Linear Albegra, the conventional beamformer can be written as
102
-
107
+ Let the csm be C and the steering vector be h, than, using Linear Albegra, the conventional beamformer can be written as
108
+
103
109
  .. math:: B = h^H \\cdot C \\cdot h,
104
110
  with ^H meaning the complex conjugated transpose.
105
111
  When using that C is a hermitian matrix one can reduce the equation to
106
-
112
+
107
113
  .. math:: B = h^H \\cdot C_D \\cdot h + 2 \\cdot Real(h^H \\cdot C_U \\cdot h),
108
114
  where C_D and C_U are the diagonal part and upper part of C respectively.
109
115
  Steering vector:
110
- Theoretically the steering vector always includes the term "exp(distMicsGrid - distArrayCenterGrid)",
111
- but as the steering vector gets multplied with its complex conjugation in all beamformer routines,
116
+ Theoretically the steering vector always includes the term "exp(distMicsGrid - distArrayCenterGrid)",
117
+ but as the steering vector gets multplied with its complex conjugation in all beamformer routines,
112
118
  the constant "distArrayCenterGrid" cancels out --> In order to save operations, it is not implemented.
113
119
  Spectral decomposition of the CSM:
114
120
  In Linear Algebra the spectral decomposition of the CSM matrix would be:
115
-
121
+
116
122
  .. math:: CSM = \\sum_{i=1}^{nEigenvalues} \\lambda_i (v_i \\cdot v_i^H) ,
117
- where lambda_i is the i-th eigenvalue and
118
- v_i is the eigenvector[nEigVal,1] belonging to lambda_i and ^H denotes the complex conjug transpose.
119
- Using this, one must not build the whole CSM (which would be time consuming), but can drag the
123
+ where lambda_i is the i-th eigenvalue and
124
+ v_i is the eigenvector[nEigVal,1] belonging to lambda_i and ^H denotes the complex conjug transpose.
125
+ Using this, one must not build the whole CSM (which would be time consuming), but can drag the
120
126
  steering vector into the sum of the spectral decomp. This saves a lot of operations.
121
127
  Squares:
122
128
  Seemingly "a * a" is slightly faster than "a**2" in numba
123
129
  Square of abs():
124
- Even though "a.real**2 + a.imag**2" would have fewer operations, modern processors seem to be optimized
130
+ Even though "a.real**2 + a.imag**2" would have fewer operations, modern processors seem to be optimized
125
131
  for "a * a.conj" and are slightly faster the latter way. Both Versions are much faster than "abs(a)**2".
126
132
  Using Cascading Sums:
127
- When using the Spectral-Decomposition-Beamformer one could use numpys cascading sums for the scalar product
128
- "eigenVec.conj * steeringVector". BUT (at the moment) this only brings benefits in comp-time for a very
133
+ When using the Spectral-Decomposition-Beamformer one could use numpys cascading sums for the scalar product
134
+ "eigenVec.conj * steeringVector". BUT (at the moment) this only brings benefits in comp-time for a very
129
135
  small range of nMics (approx 250) --> Therefor it is not implemented here.
136
+
130
137
  """
131
- boolIsEigValProb = isinstance(inputTupleCsm, tuple)# len(inputTupleCsm) > 1
138
+ boolIsEigValProb = isinstance(inputTupleCsm, tuple) # len(inputTupleCsm) > 1
132
139
  # get the beamformer type (key-tuple = (isEigValProblem, formulationOfSteeringVector, RemovalOfCSMDiag))
133
- beamformerDict = {(False, 'custom', False) : _freqBeamformer_SpecificSteerVec_FullCSM,
134
- (False, 'custom', True) : _freqBeamformer_SpecificSteerVec_CsmRemovedDiag,
135
- (True, 'custom', False) : _freqBeamformer_EigValProb_SpecificSteerVec_FullCSM,
136
- (True, 'custom', True) : _freqBeamformer_EigValProb_SpecificSteerVec_CsmRemovedDiag}
137
- sth = {'classic':1, 'inverse':2,'true level':3, 'true location':4}
138
-
140
+ beamformerDict = {
141
+ (False, 'custom', False): _freqBeamformer_SpecificSteerVec_FullCSM,
142
+ (False, 'custom', True): _freqBeamformer_SpecificSteerVec_CsmRemovedDiag,
143
+ (True, 'custom', False): _freqBeamformer_EigValProb_SpecificSteerVec_FullCSM,
144
+ (True, 'custom', True): _freqBeamformer_EigValProb_SpecificSteerVec_CsmRemovedDiag,
145
+ }
146
+ sth = {'classic': 1, 'inverse': 2, 'true level': 3, 'true location': 4}
147
+
139
148
  # prepare Input
140
149
  if steerVecType == 'custom': # beamformer with custom steering vector
141
150
  steerVec = inputTupleSteer
142
151
  nGridPoints = steerVec.shape[0]
143
152
  else: # predefined beamformers (Formulation I - IV)
144
153
  distGridToArrayCenter, distGridToAllMics, waveNumber = inputTupleSteer
145
- if not isinstance(waveNumber, np.ndarray): waveNumber = np.array([waveNumber]) #for backward compatibility
154
+ if not isinstance(waveNumber, np.ndarray):
155
+ waveNumber = np.array([waveNumber]) # for backward compatibility
146
156
  nGridPoints = distGridToAllMics.shape[0]
147
157
  if boolIsEigValProb:
148
- eigVal, eigVec = inputTupleCsm#[0], inputTupleCsm[1]
158
+ eigVal, eigVec = inputTupleCsm # [0], inputTupleCsm[1]
149
159
  else:
150
160
  csm = inputTupleCsm
151
-
161
+
152
162
  # beamformer routine: parallelized over Gridpoints
153
163
  beamformOutput = np.zeros(nGridPoints, np.float64)
154
164
  steerNormalizeOutput = np.zeros_like(beamformOutput)
@@ -162,16 +172,34 @@ def beamformerFreq(steerVecType, boolRemovedDiagOfCSM, normFactor, inputTupleSte
162
172
  coreFunc(csm, steerVec, normFactor, result, normalHelp)
163
173
  else: # predefined beamformers (Formulation I - IV)
164
174
  if boolIsEigValProb:
165
- _freqBeamformer_EigValues(eigVal, np.ascontiguousarray(eigVec), distGridToArrayCenter, distGridToAllMics, waveNumber[0], normFactor,
166
- boolRemovedDiagOfCSM, sth[steerVecType],
167
- result, normalHelp)
175
+ _freqBeamformer_EigValues(
176
+ eigVal,
177
+ np.ascontiguousarray(eigVec),
178
+ distGridToArrayCenter,
179
+ distGridToAllMics,
180
+ waveNumber[0],
181
+ normFactor,
182
+ boolRemovedDiagOfCSM,
183
+ sth[steerVecType],
184
+ result,
185
+ normalHelp,
186
+ )
168
187
  else:
169
- _freqBeamformer_FullCSM(csm, distGridToArrayCenter, distGridToAllMics, waveNumber[0], normFactor,
170
- boolRemovedDiagOfCSM, sth[steerVecType],
171
- result, normalHelp)
188
+ _freqBeamformer_FullCSM(
189
+ csm,
190
+ distGridToArrayCenter,
191
+ distGridToAllMics,
192
+ waveNumber[0],
193
+ normFactor,
194
+ boolRemovedDiagOfCSM,
195
+ sth[steerVecType],
196
+ result,
197
+ normalHelp,
198
+ )
172
199
  beamformOutput = result
173
- steerNormalizeOutput = normalHelp
174
- return beamformOutput, steerNormalizeOutput
200
+ steerNormalizeOutput = normalHelp
201
+ return beamformOutput, steerNormalizeOutput
202
+
175
203
 
176
204
  # fast implementation of full matrix beamformers
177
205
  @nb.njit(
@@ -186,11 +214,11 @@ def beamformerFreq(steerVecType, boolRemovedDiagOfCSM, normFactor, inputTupleSte
186
214
  nb.int64,
187
215
  nb.float64[::1],
188
216
  nb.float64[::1],
189
- )
217
+ ),
190
218
  ],
191
- cache=cachedOption,
219
+ cache=CACHED_OPTION,
192
220
  parallel=True,
193
- error_model="numpy"
221
+ error_model='numpy',
194
222
  )
195
223
  def _freqBeamformer_FullCSM(
196
224
  csm,
@@ -205,54 +233,48 @@ def _freqBeamformer_FullCSM(
205
233
  ):
206
234
  # see bottom of information header of 'beamformerFreq' for information on which steps are taken, in order to gain speed improvements.
207
235
  nMics = csm.shape[0]
208
- st2 = (steer_type == 2)
209
- st34 = (steer_type == 3 or steer_type == 4)
210
- helpNormalize = 0.0 # just a hint for the compiler
236
+ st2 = steer_type == 2
237
+ st34 = steer_type == 3 or steer_type == 4
238
+ helpNormalize = 0.0 # just a hint for the compiler
211
239
  for gi in nb.prange(distGridToArrayCenter.shape[0]):
212
240
  steerVec = np.empty((nMics), np.complex128)
213
241
  # building steering vector: in order to save some operation -> some normalization steps are applied after mat-vec-multipl.
214
242
  for cntMics in range(nMics):
215
243
  expArg = np.float32(waveNumber * distGridToAllMics[gi, cntMics])
216
244
  steerVec[cntMics] = np.cos(expArg) - 1j * np.sin(expArg)
217
- if st2:
245
+ if st2:
218
246
  helpNormalize = 0.0
219
247
  for cntMics in range(nMics):
220
- helpNormalize += distGridToAllMics[gi,cntMics] * distGridToAllMics[gi,cntMics]
221
- steerVec[cntMics] *= distGridToAllMics[gi,cntMics] # r_{t,i}-normalization is handled here
248
+ helpNormalize += distGridToAllMics[gi, cntMics] * distGridToAllMics[gi, cntMics]
249
+ steerVec[cntMics] *= distGridToAllMics[gi, cntMics] # r_{t,i}-normalization is handled here
222
250
  if st34:
223
251
  helpNormalize = 0.0
224
252
  for cntMics in range(nMics):
225
- helpNormalize += 1.0 / (distGridToAllMics[gi,cntMics] * distGridToAllMics[gi,cntMics])
226
- steerVec[cntMics] /= distGridToAllMics[gi,cntMics] # r_{t,i}-normalization is handled here
253
+ helpNormalize += 1.0 / (distGridToAllMics[gi, cntMics] * distGridToAllMics[gi, cntMics])
254
+ steerVec[cntMics] /= distGridToAllMics[gi, cntMics] # r_{t,i}-normalization is handled here
227
255
 
228
256
  # performing matrix-vector-multiplication (see bottom of information header of 'beamformerFreq)
229
257
  scalarProd = 0.0
230
258
  for cntMics in range(nMics):
231
259
  leftVecMatrixProd = 0.0 + 0.0j
232
260
  for cntMics2 in range(
233
- cntMics
261
+ cntMics,
234
262
  ): # calculate 'steer^H * CSM' of upper-triangular-part of csm (without diagonal)
235
- leftVecMatrixProd += (
236
- csm[cntMics2, cntMics] * steerVec[cntMics2].conjugate()
237
- )
263
+ leftVecMatrixProd += csm[cntMics2, cntMics] * steerVec[cntMics2].conjugate()
238
264
  scalarProd += (
239
265
  2 * (leftVecMatrixProd * steerVec[cntMics]).real
240
266
  ) # use that csm is Hermitian (lower triangular of csm can be reduced to factor '2')
241
267
  if not r_diag:
242
268
  for cntMics in range(nMics):
243
269
  scalarProd += (
244
- csm[cntMics, cntMics]
245
- * steerVec[cntMics].conjugate()
246
- * steerVec[cntMics]
270
+ csm[cntMics, cntMics] * steerVec[cntMics].conjugate() * steerVec[cntMics]
247
271
  ).real # include diagonal of csm
248
272
 
249
273
  # specific normalzation for different steering vector formulations
250
274
  if steer_type == 1:
251
275
  normalizeFactor = nMics
252
276
  normalizeSteer[gi] = 1.0 / nMics
253
- result[gi] = (
254
- scalarProd / (normalizeFactor * normalizeFactor) * signalLossNormalization
255
- )
277
+ result[gi] = scalarProd / (normalizeFactor * normalizeFactor) * signalLossNormalization
256
278
  elif steer_type == 2:
257
279
  normalizeFactor = nMics * distGridToArrayCenter[gi]
258
280
  normalizeFactorSquared = normalizeFactor * normalizeFactor
@@ -267,6 +289,7 @@ def _freqBeamformer_FullCSM(
267
289
  normalizeSteer[gi] = 1.0 / nMics
268
290
  result[gi] = scalarProd / normalizeFactor * signalLossNormalization
269
291
 
292
+
270
293
  # fast implementation of eigenvalue beamformers
271
294
  @nb.njit(
272
295
  [
@@ -281,11 +304,11 @@ def _freqBeamformer_FullCSM(
281
304
  nb.int64,
282
305
  nb.float64[::1],
283
306
  nb.float64[::1],
284
- )
307
+ ),
285
308
  ],
286
- cache=cachedOption,
309
+ cache=CACHED_OPTION,
287
310
  parallel=True,
288
- error_model="numpy"
311
+ error_model='numpy',
289
312
  )
290
313
  def _freqBeamformer_EigValues(
291
314
  eigVal,
@@ -302,36 +325,36 @@ def _freqBeamformer_EigValues(
302
325
  # see bottom of information header of 'beamformerFreq' for information on which steps are taken, in order to gain speed improvements.
303
326
  nMics = eigVec.shape[0]
304
327
  nEigs = len(eigVal)
305
- st2 = (steer_type == 2)
306
- st34 = (steer_type == 3 or steer_type == 4)
307
- helpNormalize = 0.0 # just a hint for the compiler
328
+ st2 = steer_type == 2
329
+ st34 = steer_type == 3 or steer_type == 4
330
+ helpNormalize = 0.0 # just a hint for the compiler
308
331
  for gi in nb.prange(distGridToArrayCenter.shape[0]):
309
332
  steerVec = np.empty((nMics), np.complex128)
310
333
  # building steering vector: in order to save some operation -> some normalization steps are applied after mat-vec-multipl.
311
334
  for cntMics in range(nMics):
312
335
  expArg = np.float32(waveNumber * distGridToAllMics[gi, cntMics])
313
336
  steerVec[cntMics] = np.cos(expArg) - 1j * np.sin(expArg)
314
- if st2:
337
+ if st2:
315
338
  helpNormalize = 0.0
316
339
  for cntMics in range(nMics):
317
- helpNormalize += distGridToAllMics[gi,cntMics] * distGridToAllMics[gi,cntMics]
318
- steerVec[cntMics] *= distGridToAllMics[gi,cntMics] # r_{t,i}-normalization is handled here
340
+ helpNormalize += distGridToAllMics[gi, cntMics] * distGridToAllMics[gi, cntMics]
341
+ steerVec[cntMics] *= distGridToAllMics[gi, cntMics] # r_{t,i}-normalization is handled here
319
342
  if st34:
320
343
  helpNormalize = 0.0
321
344
  for cntMics in range(nMics):
322
- helpNormalize += 1.0 / (distGridToAllMics[gi,cntMics] * distGridToAllMics[gi,cntMics])
323
- steerVec[cntMics] /= distGridToAllMics[gi,cntMics] # r_{t,i}-normalization is handled here
345
+ helpNormalize += 1.0 / (distGridToAllMics[gi, cntMics] * distGridToAllMics[gi, cntMics])
346
+ steerVec[cntMics] /= distGridToAllMics[gi, cntMics] # r_{t,i}-normalization is handled here
324
347
 
325
- # eigenvalue beamforming
348
+ # eigenvalue beamforming
326
349
  scalarProd = 0.0
327
350
  if r_diag:
328
351
  for cntEigVal in range(len(eigVal)):
329
352
  scalarProdFullCSMperEigVal = 0.0 + 0.0j
330
353
  scalarProdDiagCSMperEigVal = 0.0
331
354
  for cntMics in range(nMics):
332
- temp1 = eigVec[cntMics, cntEigVal].conjugate() * steerVec[cntMics]
355
+ temp1 = eigVec[cntMics, cntEigVal].conjugate() * steerVec[cntMics]
333
356
  scalarProdFullCSMperEigVal += temp1
334
- scalarProdDiagCSMperEigVal += (temp1 * temp1.conjugate()).real
357
+ scalarProdDiagCSMperEigVal += (temp1 * temp1.conjugate()).real
335
358
  scalarProdFullCSMAbsSquared = (scalarProdFullCSMperEigVal * scalarProdFullCSMperEigVal.conjugate()).real
336
359
  scalarProd += (scalarProdFullCSMAbsSquared - scalarProdDiagCSMperEigVal) * eigVal[cntEigVal]
337
360
  else:
@@ -339,16 +362,14 @@ def _freqBeamformer_EigValues(
339
362
  scalarProdFullCSMperEigVal = 0.0 + 0.0j
340
363
  for cntMics in range(nMics):
341
364
  scalarProdFullCSMperEigVal += eigVec[cntMics, cntEigVal].conjugate() * steerVec[cntMics]
342
- scalarProdFullCSMAbsSquared = (scalarProdFullCSMperEigVal * scalarProdFullCSMperEigVal.conjugate()).real
365
+ scalarProdFullCSMAbsSquared = (scalarProdFullCSMperEigVal * scalarProdFullCSMperEigVal.conjugate()).real
343
366
  scalarProd += scalarProdFullCSMAbsSquared * eigVal[cntEigVal]
344
367
 
345
368
  # specific normalzation for different steering vector formulations
346
369
  if steer_type == 1:
347
370
  normalizeFactor = nMics
348
371
  normalizeSteer[gi] = 1.0 / nMics
349
- result[gi] = (
350
- scalarProd / (normalizeFactor * normalizeFactor) * signalLossNormalization
351
- )
372
+ result[gi] = scalarProd / (normalizeFactor * normalizeFactor) * signalLossNormalization
352
373
  elif steer_type == 2:
353
374
  normalizeFactor = nMics * distGridToArrayCenter[gi]
354
375
  normalizeFactorSquared = normalizeFactor * normalizeFactor
@@ -363,8 +384,15 @@ def _freqBeamformer_EigValues(
363
384
  normalizeSteer[gi] = 1.0 / nMics
364
385
  result[gi] = scalarProd / normalizeFactor * signalLossNormalization
365
386
 
366
- @nb.guvectorize([(nb.complex128[:,:], nb.complex128[:], nb.float64[:], nb.float64[:], nb.float64[:])],
367
- '(m,m),(m),()->(),()', nopython=True, target=parallelOption, cache=cachedOption, fastmath=fastOption)
387
+
388
+ @nb.guvectorize(
389
+ [(nb.complex128[:, :], nb.complex128[:], nb.float64[:], nb.float64[:], nb.float64[:])],
390
+ '(m,m),(m),()->(),()',
391
+ nopython=True,
392
+ target=PARALLEL_OPTION,
393
+ cache=CACHED_OPTION,
394
+ fastmath=FAST_OPTION,
395
+ )
368
396
  def _freqBeamformer_SpecificSteerVec_FullCSM(csm, steerVec, signalLossNormalization, result, normalizeSteer):
369
397
  # see bottom of information header of 'beamformerFreq' for information on which steps are taken, in order to gain speed improvements.
370
398
  nMics = csm.shape[0]
@@ -377,14 +405,24 @@ def _freqBeamformer_SpecificSteerVec_FullCSM(csm, steerVec, signalLossNormalizat
377
405
  leftVecMatrixProd = 0.0 + 0.0j
378
406
  for cntMics2 in range(cntMics): # calculate 'steer^H * CSM' of upper-triangular-part of csm (without diagonal)
379
407
  leftVecMatrixProd += csm[cntMics2, cntMics] * steerVec[cntMics2].conjugate()
380
- scalarProd += 2 * (leftVecMatrixProd * steerVec[cntMics]).real # use that csm is Hermitian (lower triangular of csm can be reduced to factor '2')
381
- scalarProd += (csm[cntMics, cntMics] * steerVec[cntMics].conjugate() * steerVec[cntMics]).real # include diagonal of csm
408
+ scalarProd += (
409
+ 2 * (leftVecMatrixProd * steerVec[cntMics]).real
410
+ ) # use that csm is Hermitian (lower triangular of csm can be reduced to factor '2')
411
+ scalarProd += (
412
+ csm[cntMics, cntMics] * steerVec[cntMics].conjugate() * steerVec[cntMics]
413
+ ).real # include diagonal of csm
382
414
  normalizeSteer[0] = helpNormalize.real
383
415
  result[0] = scalarProd * signalLossNormalization[0]
384
416
 
385
417
 
386
- @nb.guvectorize([(nb.complex128[:,:], nb.complex128[:], nb.float64[:], nb.float64[:], nb.float64[:])],
387
- '(m,m),(m),()->(),()', nopython=True, target=parallelOption, cache=cachedOption, fastmath=fastOption)
418
+ @nb.guvectorize(
419
+ [(nb.complex128[:, :], nb.complex128[:], nb.float64[:], nb.float64[:], nb.float64[:])],
420
+ '(m,m),(m),()->(),()',
421
+ nopython=True,
422
+ target=PARALLEL_OPTION,
423
+ cache=CACHED_OPTION,
424
+ fastmath=FAST_OPTION,
425
+ )
388
426
  def _freqBeamformer_SpecificSteerVec_CsmRemovedDiag(csm, steerVec, signalLossNormalization, result, normalizeSteer):
389
427
  # see bottom of information header of 'beamformerFreq' for information on which steps are taken, in order to gain speed improvements.
390
428
  nMics = csm.shape[0]
@@ -397,15 +435,32 @@ def _freqBeamformer_SpecificSteerVec_CsmRemovedDiag(csm, steerVec, signalLossNor
397
435
  leftVecMatrixProd = 0.0 + 0.0j
398
436
  for cntMics2 in range(cntMics): # calculate 'steer^H * CSM' of upper-triangular-part of csm (without diagonal)
399
437
  leftVecMatrixProd += csm[cntMics2, cntMics] * steerVec[cntMics2].conjugate()
400
- scalarProd += 2 * (leftVecMatrixProd * steerVec[cntMics]).real # use that csm is Hermitian (lower triangular of csm can be reduced to factor '2')
438
+ scalarProd += (
439
+ 2 * (leftVecMatrixProd * steerVec[cntMics]).real
440
+ ) # use that csm is Hermitian (lower triangular of csm can be reduced to factor '2')
401
441
  normalizeSteer[0] = helpNormalize.real
402
442
  result[0] = scalarProd * signalLossNormalization[0]
403
- @nb.guvectorize([(nb.float64[:], nb.complex128[:,:], nb.complex128[:], nb.float64[:], nb.float64[:], nb.float64[:])],
404
- '(e),(m,e),(m),()->(),()', nopython=True, target=parallelOption, cache=cachedOption, fastmath=fastOption)
405
- def _freqBeamformer_EigValProb_SpecificSteerVec_FullCSM(eigVal, eigVec, steerVec, signalLossNormalization, result, normalizeSteer):
443
+
444
+
445
+ @nb.guvectorize(
446
+ [(nb.float64[:], nb.complex128[:, :], nb.complex128[:], nb.float64[:], nb.float64[:], nb.float64[:])],
447
+ '(e),(m,e),(m),()->(),()',
448
+ nopython=True,
449
+ target=PARALLEL_OPTION,
450
+ cache=CACHED_OPTION,
451
+ fastmath=FAST_OPTION,
452
+ )
453
+ def _freqBeamformer_EigValProb_SpecificSteerVec_FullCSM(
454
+ eigVal,
455
+ eigVec,
456
+ steerVec,
457
+ signalLossNormalization,
458
+ result,
459
+ normalizeSteer,
460
+ ):
406
461
  # see bottom of information header of 'beamformerFreq' for information on which steps are taken, in order to gain speed improvements.
407
462
  nMics = eigVec.shape[0]
408
-
463
+
409
464
  # get h^H * h for normalization
410
465
  helpNormalize = 0.0
411
466
  for cntMics in range(nMics):
@@ -417,18 +472,31 @@ def _freqBeamformer_EigValProb_SpecificSteerVec_FullCSM(eigVal, eigVec, steerVec
417
472
  scalarProdFullCSMperEigVal = 0.0 + 0.0j
418
473
  for cntMics in range(nMics):
419
474
  scalarProdFullCSMperEigVal += eigVec[cntMics, cntEigVal].conjugate() * steerVec[cntMics]
420
- scalarProdFullCSMAbsSquared = (scalarProdFullCSMperEigVal * scalarProdFullCSMperEigVal.conjugate()).real
475
+ scalarProdFullCSMAbsSquared = (scalarProdFullCSMperEigVal * scalarProdFullCSMperEigVal.conjugate()).real
421
476
  scalarProdFullCSM += scalarProdFullCSMAbsSquared * eigVal[cntEigVal]
422
477
  normalizeSteer[0] = helpNormalize.real
423
478
  result[0] = scalarProdFullCSM * signalLossNormalization[0]
424
479
 
425
480
 
426
- @nb.guvectorize([(nb.float64[:], nb.complex128[:,:], nb.complex128[:], nb.float64[:], nb.float64[:], nb.float64[:])],
427
- '(e),(m,e),(m),()->(),()', nopython=True, target=parallelOption, cache=cachedOption, fastmath=fastOption)
428
- def _freqBeamformer_EigValProb_SpecificSteerVec_CsmRemovedDiag(eigVal, eigVec, steerVec, signalLossNormalization, result, normalizeSteer):
481
+ @nb.guvectorize(
482
+ [(nb.float64[:], nb.complex128[:, :], nb.complex128[:], nb.float64[:], nb.float64[:], nb.float64[:])],
483
+ '(e),(m,e),(m),()->(),()',
484
+ nopython=True,
485
+ target=PARALLEL_OPTION,
486
+ cache=CACHED_OPTION,
487
+ fastmath=FAST_OPTION,
488
+ )
489
+ def _freqBeamformer_EigValProb_SpecificSteerVec_CsmRemovedDiag(
490
+ eigVal,
491
+ eigVec,
492
+ steerVec,
493
+ signalLossNormalization,
494
+ result,
495
+ normalizeSteer,
496
+ ):
429
497
  # see bottom of information header of 'beamformerFreq' for information on which steps are taken, in order to gain speed improvements.
430
498
  nMics = eigVec.shape[0]
431
-
499
+
432
500
  # get h^H * h for normalization
433
501
  helpNormalize = 0.0
434
502
  for cntMics in range(nMics):
@@ -442,15 +510,16 @@ def _freqBeamformer_EigValProb_SpecificSteerVec_CsmRemovedDiag(eigVal, eigVec, s
442
510
  for cntMics in range(nMics):
443
511
  temp1 = eigVec[cntMics, cntEigVal].conjugate() * steerVec[cntMics]
444
512
  scalarProdFullCSMperEigVal += temp1
445
- scalarProdDiagCSMperEigVal += (temp1 * temp1.conjugate()).real
513
+ scalarProdDiagCSMperEigVal += (temp1 * temp1.conjugate()).real
446
514
  scalarProdFullCSMAbsSquared = (scalarProdFullCSMperEigVal * scalarProdFullCSMperEigVal.conjugate()).real
447
515
  scalarProdReducedCSM += (scalarProdFullCSMAbsSquared - scalarProdDiagCSMperEigVal) * eigVal[cntEigVal]
448
516
  normalizeSteer[0] = helpNormalize.real
449
517
  result[0] = scalarProdReducedCSM * signalLossNormalization[0]
450
518
 
451
- #%% Point - Spread - Function
519
+
520
+ # %% Point - Spread - Function
452
521
  def calcPointSpreadFunction(steerVecType, distGridToArrayCenter, distGridToAllMics, waveNumber, indSource, dtype):
453
- """ Calculates the Point-Spread-Functions. Use either a predefined steering vector
522
+ r"""Calculates the Point-Spread-Functions. Use either a predefined steering vector
454
523
  formulation (see :ref:`Sarradj, 2012<Sarradj2012>`) or pass it your own steering vector.
455
524
 
456
525
  Parameters
@@ -464,7 +533,7 @@ def calcPointSpreadFunction(steerVecType, distGridToArrayCenter, distGridToAllMi
464
533
  waveNumber : float64
465
534
  The free field wave number.
466
535
  indSource : a LIST of int (e.g. indSource=[5] is fine; indSource=5 doesn't work):
467
- specifies which gridpoints should be assumed to be sources
536
+ specifies which gridpoints should be assumed to be sources
468
537
  --> a seperate psf will be calculated for each source
469
538
  dtype : either 'float64' or 'float32'
470
539
  Determines the precision of the result. For big maps this could be worth downgrading.
@@ -472,177 +541,271 @@ def calcPointSpreadFunction(steerVecType, distGridToArrayCenter, distGridToAllMi
472
541
  Returns
473
542
  -------
474
543
  Autopower spectrum PSF map : [nFreqs, nGridPoints, nSources]
475
-
544
+
476
545
  Some Notes on the optimization of all subroutines
477
546
  -------------------------------------------------
478
547
  Reducing beamforming equation:
479
548
  Let the steering vector be h, than, using Linear Albegra, the PSF of a SourcePoint S would be
480
-
549
+
481
550
  .. math:: B = h^H \\cdot (a_S \\cdot a_S^H) \\cdot h,
482
551
  with ^H meaning the complex conjugated transpose and a_s the transfer function from source to gridpoint.
483
- The (...)-part equals the CSM that the source would produce via the chosen steering vec formulation.
552
+ The (...)-part equals the CSM that the source would produce via the chosen steering vec formulation.
484
553
  Using (for example) tensor calculus, one can reduce the equation to:
485
-
554
+
486
555
  .. math:: B = \\left| h^H \\cdot a_S \\right| ^ 2.
487
556
  Steering vector:
488
- Theoretically the steering vector always includes the term "exp(distMicsGrid - distArrayCenterGrid)", but as the steering vector gets multplied with its complex conjugation in
557
+ Theoretically the steering vector always includes the term "exp(distMicsGrid - distArrayCenterGrid)", but as the steering vector gets multplied with its complex conjugation in
489
558
  all beamformer routines, the constant "distArrayCenterGrid" cancels out --> In order to save operations, it is not implemented.
490
559
  Squares:
491
560
  Seemingly "a * a" is slightly faster than "a**2" in numba
492
561
  Square of abs():
493
562
  Even though "a.real**2 + a.imag**^2" would have fewer operations, modern processors seem to be optimized for "a * a.conj" and are slightly faster the latter way.
494
563
  Both Versions are much faster than "abs(a)**2".
564
+
495
565
  """
496
566
  # get the steering vector formulation
497
- psfDict = {'classic' : _psf_Formulation1AkaClassic,
498
- 'inverse' : _psf_Formulation2AkaInverse,
499
- 'true level' : _psf_Formulation3AkaTrueLevel,
500
- 'true location' : _psf_Formulation4AkaTrueLocation}
567
+ psfDict = {
568
+ 'classic': _psf_Formulation1AkaClassic,
569
+ 'inverse': _psf_Formulation2AkaInverse,
570
+ 'true level': _psf_Formulation3AkaTrueLevel,
571
+ 'true location': _psf_Formulation4AkaTrueLocation,
572
+ }
501
573
  coreFunc = psfDict[steerVecType]
502
574
 
503
575
  # prepare input
504
576
  nGridPoints = distGridToAllMics.shape[0]
505
577
  nSources = len(indSource)
506
- if not isinstance(waveNumber, np.ndarray): waveNumber = np.array([waveNumber])
507
-
578
+ if not isinstance(waveNumber, np.ndarray):
579
+ waveNumber = np.array([waveNumber])
580
+
508
581
  # psf routine: parallelized over Gridpoints
509
582
  psfOutput = np.zeros((nGridPoints, nSources), dtype=dtype)
510
- coreFunc(distGridToArrayCenter,
511
- distGridToAllMics,
512
- distGridToArrayCenter[indSource],
513
- distGridToAllMics[indSource, :],
514
- waveNumber,
515
- psfOutput)
583
+ coreFunc(
584
+ distGridToArrayCenter,
585
+ distGridToAllMics,
586
+ distGridToArrayCenter[indSource],
587
+ distGridToAllMics[indSource, :],
588
+ waveNumber,
589
+ psfOutput,
590
+ )
516
591
 
517
592
  return psfOutput
518
593
 
519
594
 
520
- @nb.guvectorize([(nb.float64[:], nb.float64[:], nb.float64[:], nb.float64[:,:], nb.float64[:], nb.float64[:]),
521
- (nb.float64[:], nb.float64[:], nb.float64[:], nb.float64[:,:], nb.float64[:], nb.float32[:])],
522
- '(),(m),(s),(s,m),()->(s)', nopython=True, target=parallelOption, cache=cachedOption, fastmath=fastOption)
523
- def _psf_Formulation1AkaClassic(distGridToArrayCenter, distGridToAllMics, distSourcesToArrayCenter, distSourcesToAllMics, waveNumber, result):
595
+ @nb.guvectorize(
596
+ [
597
+ (nb.float64[:], nb.float64[:], nb.float64[:], nb.float64[:, :], nb.float64[:], nb.float64[:]),
598
+ (nb.float64[:], nb.float64[:], nb.float64[:], nb.float64[:, :], nb.float64[:], nb.float32[:]),
599
+ ],
600
+ '(),(m),(s),(s,m),()->(s)',
601
+ nopython=True,
602
+ target=PARALLEL_OPTION,
603
+ cache=CACHED_OPTION,
604
+ fastmath=FAST_OPTION,
605
+ )
606
+ def _psf_Formulation1AkaClassic(
607
+ distGridToArrayCenter, # noqa ARG001
608
+ distGridToAllMics,
609
+ distSourcesToArrayCenter,
610
+ distSourcesToAllMics,
611
+ waveNumber,
612
+ result,
613
+ ): # noqa ARG001
524
614
  nMics = distGridToAllMics.shape[0]
525
615
  for cntSources in range(len(distSourcesToArrayCenter)):
526
616
  # see bottom of information header of 'calcPointSpreadFunction' for infos on the PSF calculation and speed improvements.
527
617
  scalarProd = 0.0 + 0.0j
528
618
  for cntMics in range(nMics):
529
- expArg = np.float32(waveNumber[0] * (distGridToAllMics[cntMics] - distSourcesToAllMics[cntSources, cntMics]))
619
+ expArg = np.float32(
620
+ waveNumber[0] * (distGridToAllMics[cntMics] - distSourcesToAllMics[cntSources, cntMics]),
621
+ )
530
622
  scalarProd += (np.cos(expArg) - 1j * np.sin(expArg)) / distSourcesToAllMics[cntSources, cntMics]
531
623
  normalizeFactor = distSourcesToArrayCenter[cntSources] / nMics
532
624
  scalarProdAbsSquared = (scalarProd * scalarProd.conjugate()).real
533
625
  result[cntSources] = scalarProdAbsSquared * (normalizeFactor * normalizeFactor)
534
626
 
535
627
 
536
- @nb.guvectorize([(nb.float64[:], nb.float64[:], nb.float64[:], nb.float64[:,:], nb.float64[:], nb.float64[:]),
537
- (nb.float64[:], nb.float64[:], nb.float64[:], nb.float64[:,:], nb.float64[:], nb.float32[:])],
538
- '(),(m),(s),(s,m),()->(s)', nopython=True, target=parallelOption, cache=cachedOption, fastmath=fastOption)
539
- def _psf_Formulation2AkaInverse(distGridToArrayCenter, distGridToAllMics, distSourcesToArrayCenter, distSourcesToAllMics, waveNumber, result):
628
+ @nb.guvectorize(
629
+ [
630
+ (nb.float64[:], nb.float64[:], nb.float64[:], nb.float64[:, :], nb.float64[:], nb.float64[:]),
631
+ (nb.float64[:], nb.float64[:], nb.float64[:], nb.float64[:, :], nb.float64[:], nb.float32[:]),
632
+ ],
633
+ '(),(m),(s),(s,m),()->(s)',
634
+ nopython=True,
635
+ target=PARALLEL_OPTION,
636
+ cache=CACHED_OPTION,
637
+ fastmath=FAST_OPTION,
638
+ )
639
+ def _psf_Formulation2AkaInverse(
640
+ distGridToArrayCenter,
641
+ distGridToAllMics,
642
+ distSourcesToArrayCenter,
643
+ distSourcesToAllMics,
644
+ waveNumber,
645
+ result,
646
+ ):
540
647
  nMics = distGridToAllMics.shape[0]
541
648
  for cntSources in range(len(distSourcesToArrayCenter)):
542
649
  # see bottom of information header of 'calcPointSpreadFunction' for infos on the PSF calculation and speed improvements.
543
650
  scalarProd = 0.0 + 0.0j
544
651
  for cntMics in range(nMics):
545
- expArg = np.float32(waveNumber[0] * (distGridToAllMics[cntMics] - distSourcesToAllMics[cntSources, cntMics]))
546
- scalarProd += (np.cos(expArg) - 1j * np.sin(expArg)) / distSourcesToAllMics[cntSources, cntMics] * distGridToAllMics[cntMics]
652
+ expArg = np.float32(
653
+ waveNumber[0] * (distGridToAllMics[cntMics] - distSourcesToAllMics[cntSources, cntMics]),
654
+ )
655
+ scalarProd += (
656
+ (np.cos(expArg) - 1j * np.sin(expArg))
657
+ / distSourcesToAllMics[cntSources, cntMics]
658
+ * distGridToAllMics[cntMics]
659
+ )
547
660
  normalizeFactor = distSourcesToArrayCenter[cntSources] / distGridToArrayCenter[0] / nMics
548
- scalarProdAbsSquared = (scalarProd * scalarProd.conjugate()).real
549
- result[cntSources] = scalarProdAbsSquared * (normalizeFactor * normalizeFactor)
661
+ scalarProdAbsSquared = (scalarProd * scalarProd.conjugate()).real
662
+ result[cntSources] = scalarProdAbsSquared * (normalizeFactor * normalizeFactor)
550
663
 
551
664
 
552
- @nb.guvectorize([(nb.float64[:], nb.float64[:], nb.float64[:], nb.float64[:,:], nb.float64[:], nb.float64[:]),
553
- (nb.float64[:], nb.float64[:], nb.float64[:], nb.float64[:,:], nb.float64[:], nb.float32[:])],
554
- '(),(m),(s),(s,m),()->(s)', nopython=True, target=parallelOption, cache=cachedOption, fastmath=fastOption)
555
- def _psf_Formulation3AkaTrueLevel(distGridToArrayCenter, distGridToAllMics, distSourcesToArrayCenter, distSourcesToAllMics, waveNumber, result):
665
+ @nb.guvectorize(
666
+ [
667
+ (nb.float64[:], nb.float64[:], nb.float64[:], nb.float64[:, :], nb.float64[:], nb.float64[:]),
668
+ (nb.float64[:], nb.float64[:], nb.float64[:], nb.float64[:, :], nb.float64[:], nb.float32[:]),
669
+ ],
670
+ '(),(m),(s),(s,m),()->(s)',
671
+ nopython=True,
672
+ target=PARALLEL_OPTION,
673
+ cache=CACHED_OPTION,
674
+ fastmath=FAST_OPTION,
675
+ )
676
+ def _psf_Formulation3AkaTrueLevel(
677
+ distGridToArrayCenter,
678
+ distGridToAllMics,
679
+ distSourcesToArrayCenter,
680
+ distSourcesToAllMics,
681
+ waveNumber,
682
+ result,
683
+ ):
556
684
  nMics = distGridToAllMics.shape[0]
557
685
  for cntSources in range(len(distSourcesToArrayCenter)):
558
686
  # see bottom of information header of 'calcPointSpreadFunction' for infos on the PSF calculation and speed improvements.
559
687
  scalarProd = 0.0 + 0.0j
560
688
  helpNormalizeGrid = 0.0
561
689
  for cntMics in range(nMics):
562
- expArg = np.float32(waveNumber[0] * (distGridToAllMics[cntMics] - distSourcesToAllMics[cntSources, cntMics]))
563
- scalarProd += (np.cos(expArg) - 1j * np.sin(expArg)) / distSourcesToAllMics[cntSources, cntMics] / distGridToAllMics[cntMics]
690
+ expArg = np.float32(
691
+ waveNumber[0] * (distGridToAllMics[cntMics] - distSourcesToAllMics[cntSources, cntMics]),
692
+ )
693
+ scalarProd += (
694
+ (np.cos(expArg) - 1j * np.sin(expArg))
695
+ / distSourcesToAllMics[cntSources, cntMics]
696
+ / distGridToAllMics[cntMics]
697
+ )
564
698
  helpNormalizeGrid += 1.0 / (distGridToAllMics[cntMics] * distGridToAllMics[cntMics])
565
699
  normalizeFactor = distSourcesToArrayCenter[cntSources] / distGridToArrayCenter[0] / helpNormalizeGrid
566
700
  scalarProdAbsSquared = (scalarProd * scalarProd.conjugate()).real
567
701
  result[cntSources] = scalarProdAbsSquared * (normalizeFactor * normalizeFactor)
568
702
 
569
703
 
570
- @nb.guvectorize([(nb.float64[:], nb.float64[:], nb.float64[:], nb.float64[:,:], nb.float64[:], nb.float64[:]),
571
- (nb.float64[:], nb.float64[:], nb.float64[:], nb.float64[:,:], nb.float64[:], nb.float32[:])],
572
- '(),(m),(s),(s,m),()->(s)', nopython=True, target=parallelOption, cache=cachedOption, fastmath=fastOption)
573
- def _psf_Formulation4AkaTrueLocation(distGridToArrayCenter, distGridToAllMics, distSourcesToArrayCenter, distSourcesToAllMics, waveNumber, result):
704
+ @nb.guvectorize(
705
+ [
706
+ (nb.float64[:], nb.float64[:], nb.float64[:], nb.float64[:, :], nb.float64[:], nb.float64[:]),
707
+ (nb.float64[:], nb.float64[:], nb.float64[:], nb.float64[:, :], nb.float64[:], nb.float32[:]),
708
+ ],
709
+ '(),(m),(s),(s,m),()->(s)',
710
+ nopython=True,
711
+ target=PARALLEL_OPTION,
712
+ cache=CACHED_OPTION,
713
+ fastmath=FAST_OPTION,
714
+ )
715
+ def _psf_Formulation4AkaTrueLocation(
716
+ distGridToArrayCenter, # noqa ARG001
717
+ distGridToAllMics,
718
+ distSourcesToArrayCenter,
719
+ distSourcesToAllMics,
720
+ waveNumber,
721
+ result,
722
+ ): # noqa ARG001
574
723
  nMics = distGridToAllMics.shape[0]
575
724
  for cntSources in range(len(distSourcesToArrayCenter)):
576
725
  # see bottom of information header of 'calcPointSpreadFunction' for infos on the PSF calculation and speed improvements.
577
726
  scalarProd = 0.0 + 0.0j
578
727
  helpNormalizeGrid = 0.0
579
728
  for cntMics in range(nMics):
580
- expArg = np.float32(waveNumber[0] * (distGridToAllMics[cntMics] - distSourcesToAllMics[cntSources, cntMics]))
581
- scalarProd += (np.cos(expArg) - 1j * np.sin(expArg)) / distSourcesToAllMics[cntSources, cntMics] / distGridToAllMics[cntMics]
729
+ expArg = np.float32(
730
+ waveNumber[0] * (distGridToAllMics[cntMics] - distSourcesToAllMics[cntSources, cntMics]),
731
+ )
732
+ scalarProd += (
733
+ (np.cos(expArg) - 1j * np.sin(expArg))
734
+ / distSourcesToAllMics[cntSources, cntMics]
735
+ / distGridToAllMics[cntMics]
736
+ )
582
737
  helpNormalizeGrid += 1.0 / (distGridToAllMics[cntMics] * distGridToAllMics[cntMics])
583
738
  normalizeFactor = distSourcesToArrayCenter[cntSources]
584
739
  scalarProdAbsSquared = (scalarProd * scalarProd.conjugate()).real
585
740
  result[cntSources] = scalarProdAbsSquared * (normalizeFactor * normalizeFactor) / nMics / helpNormalizeGrid
586
741
 
742
+
587
743
  # CURRENTLY NOT NEEDED, AS CUSTOM PSF WILL BE CALCULATED IN fbeamform.SteeringVector WITH THE USE OF Trait transfer
588
- #@nb.guvectorize([(nb.float64[:], nb.float64[:], nb.float64[:], nb.float64[:,:], nb.float64[:], nb.float64[:]),
744
+ # @nb.guvectorize([(nb.float64[:], nb.float64[:], nb.float64[:], nb.float64[:,:], nb.float64[:], nb.float64[:]),
589
745
  # (nb.float64[:], nb.float64[:], nb.float64[:], nb.float64[:,:], nb.float64[:], nb.float32[:])],
590
- # '(),(m),(s),(s,m),()->(s)', nopython=True, target=parallelOption, cache=cachedOption)
591
- #def _psf_SpecificSteerVec(steerVec, steerVecSources, result):
746
+ # '(),(m),(s),(s,m),()->(s)', nopython=True, target=PARALLEL_OPTION, cache=CACHED_OPTION)
747
+ # def _psf_SpecificSteerVec(steerVec, steerVecSources, result):
592
748
  # nMics = len(steerVec)
593
749
  # for cntSources in range(steerVecSources.shape[0]):
594
750
  # # see bottom of information header of 'calcPointSpreadFunction' for infos on the PSF calculation and speed improvements.
595
751
  # scalarProd = 0.0 + 0.0j
596
752
  # for cntMics in range(nMics):
597
753
  # scalarProd += steerVec[cntMics].conjugate() * steerVecSources[cntSources, cntMics]
598
- # scalarProdAbsSquared = (scalarProd * scalarProd.conjugate()).real
754
+ # scalarProdAbsSquared = (scalarProd * scalarProd.conjugate()).real
599
755
  # result[cntSources] = scalarProdAbsSquared
600
756
 
601
757
 
602
- #%% Damas - Gauss Seidel
758
+ # %% Damas - Gauss Seidel
603
759
  # Formerly known as 'gseidel'
604
- @nb.guvectorize([#(nb.float32[:,:], nb.float32[:], nb.int64[:], nb.float64[:], nb.float32[:]),
605
- (nb.float64[:,:], nb.float64[:], nb.int64[:], nb.float64[:], nb.float64[:]),
606
- #(nb.float32[:,:], nb.float64[:], nb.int64[:], nb.float64[:], nb.float64[:]),
607
- #(nb.float64[:,:], nb.float32[:], nb.int64[:], nb.float64[:], nb.float32[:])
608
- ],
609
- '(g,g),(g),(),()->(g)', nopython=True, target=parallelOption, cache=cachedOption, fastmath=fastOption)
760
+ @nb.guvectorize(
761
+ [ # (nb.float32[:,:], nb.float32[:], nb.int64[:], nb.float64[:], nb.float32[:]),
762
+ (nb.float64[:, :], nb.float64[:], nb.int64[:], nb.float64[:], nb.float64[:]),
763
+ # (nb.float32[:,:], nb.float64[:], nb.int64[:], nb.float64[:], nb.float64[:]),
764
+ # (nb.float64[:,:], nb.float32[:], nb.int64[:], nb.float64[:], nb.float32[:])
765
+ ],
766
+ '(g,g),(g),(),()->(g)',
767
+ nopython=True,
768
+ target=PARALLEL_OPTION,
769
+ cache=CACHED_OPTION,
770
+ fastmath=FAST_OPTION,
771
+ )
610
772
  def damasSolverGaussSeidel(A, dirtyMap, nIterations, relax, damasSolution):
611
- """ Solves the DAMAS inverse problem via modified gauss seidel.
773
+ """Solves the DAMAS inverse problem via modified gauss seidel.
612
774
  This is the original formulation from :ref:`Brooks and Humphreys, 2006<BrooksHumphreys2006>`.
613
-
775
+
614
776
  Parameters
615
777
  ----------
616
778
  A : float32/float64[nFreqs, nGridpoints, nGridpoints] (or float64[...])
617
779
  The PSF build matrix (see :ref:`Brooks and Humphreys, 2006<BrooksHumphreys2006>`)
618
780
  dirtyMap : float32/float64[nFreqs, nGridpoints] (or float64[...])
619
781
  The conventional beamformer map
620
- nIterations : int64[scalar]
782
+ nIterations : int64[scalar]
621
783
  number of Iterations the damas solver has to go through
622
- relax : int64[scalar]
784
+ relax : int64[scalar]
623
785
  relaxation parameter (=1.0 in :ref:`Brooks and Humphreys, 2006<BrooksHumphreys2006>`)
624
- damasSolution : float32/float64[nFreqs, nGridpoints] (or float64[...])
786
+ damasSolution : float32/float64[nFreqs, nGridpoints] (or float64[...])
625
787
  starting solution
626
-
788
+
627
789
  Returns
628
790
  -------
629
791
  None : as damasSolution is overwritten with end result of the damas iterative solver.
792
+
630
793
  """
631
- # nGridPoints = len(dirtyMap)
632
- # for cntIter in range(nIterations[0]):
633
- # for cntGrid in range(nGridPoints):
634
- # solHelp = np.float32(0)
635
- # for cntGridHelp in range(cntGrid): # lower sum
636
- # solHelp += A[cntGrid, cntGridHelp] * damasSolution[cntGridHelp]
637
- # for cntGridHelp in range(cntGrid + 1, nGridPoints): # upper sum
638
- # solHelp += A[cntGrid, cntGridHelp] * damasSolution[cntGridHelp]
639
- # solHelp = (1 - relax[0]) * damasSolution[cntGrid] + relax[0] * (dirtyMap[cntGrid] - solHelp)
640
- # if solHelp > 0.0:
641
- # damasSolution[cntGrid] = solHelp
642
- # else:
643
- # damasSolution[cntGrid] = 0.0
794
+ # nGridPoints = len(dirtyMap)
795
+ # for cntIter in range(nIterations[0]):
796
+ # for cntGrid in range(nGridPoints):
797
+ # solHelp = np.float32(0)
798
+ # for cntGridHelp in range(cntGrid): # lower sum
799
+ # solHelp += A[cntGrid, cntGridHelp] * damasSolution[cntGridHelp]
800
+ # for cntGridHelp in range(cntGrid + 1, nGridPoints): # upper sum
801
+ # solHelp += A[cntGrid, cntGridHelp] * damasSolution[cntGridHelp]
802
+ # solHelp = (1 - relax[0]) * damasSolution[cntGrid] + relax[0] * (dirtyMap[cntGrid] - solHelp)
803
+ # if solHelp > 0.0:
804
+ # damasSolution[cntGrid] = solHelp
805
+ # else:
806
+ # damasSolution[cntGrid] = 0.0
644
807
  nGridPoints = len(dirtyMap)
645
- for cntIter in range(nIterations[0]):
808
+ for _cntIter in range(nIterations[0]):
646
809
  for cntGrid in range(nGridPoints):
647
810
  solHelp = 0.0
648
811
  for cntGridHelp in range(nGridPoints): # full sum
@@ -655,10 +818,10 @@ def damasSolverGaussSeidel(A, dirtyMap, nIterations, relax, damasSolution):
655
818
  damasSolution[cntGrid] = 0.0
656
819
 
657
820
 
658
- #%% Transfer - Function
821
+ # %% Transfer - Function
659
822
  def calcTransfer(distGridToArrayCenter, distGridToAllMics, waveNumber):
660
- """ Calculates the transfer functions between the various mics and gridpoints.
661
-
823
+ """Calculates the transfer functions between the various mics and gridpoints.
824
+
662
825
  Parameters
663
826
  ----------
664
827
  distGridToArrayCenter : float64[nGridpoints]
@@ -671,6 +834,7 @@ def calcTransfer(distGridToArrayCenter, distGridToAllMics, waveNumber):
671
834
  Returns
672
835
  -------
673
836
  The Transferfunctions in format complex128[nGridPoints, nMics].
837
+
674
838
  """
675
839
  nGridPoints, nMics = distGridToAllMics.shape[0], distGridToAllMics.shape[1]
676
840
  result = np.zeros((nGridPoints, nMics), np.complex128)
@@ -678,11 +842,17 @@ def calcTransfer(distGridToArrayCenter, distGridToAllMics, waveNumber):
678
842
  _transferCoreFunc(distGridToArrayCenter, distGridToAllMics, np.array([waveNumber]), result)
679
843
  return result
680
844
 
681
- @nb.guvectorize([(nb.float64[:], nb.float64[:], nb.float64[:], nb.complex128[:])], '(),(m),()->(m)',
682
- nopython=True, target=parallelOption, cache=cachedOption, fastmath=fastOption)
845
+
846
+ @nb.guvectorize(
847
+ [(nb.float64[:], nb.float64[:], nb.float64[:], nb.complex128[:])],
848
+ '(),(m),()->(m)',
849
+ nopython=True,
850
+ target=PARALLEL_OPTION,
851
+ cache=CACHED_OPTION,
852
+ fastmath=FAST_OPTION,
853
+ )
683
854
  def _transferCoreFunc(distGridToArrayCenter, distGridToAllMics, waveNumber, result):
684
855
  nMics = distGridToAllMics.shape[0]
685
856
  for cntMics in range(nMics):
686
857
  expArg = np.float32(waveNumber[0] * (distGridToAllMics[cntMics] - distGridToArrayCenter[0]))
687
858
  result[cntMics] = (np.cos(expArg) - 1j * np.sin(expArg)) * distGridToArrayCenter[0] / distGridToAllMics[cntMics]
688
-