acoular 24.7__py3-none-any.whl → 25.1__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 +21 -9
- acoular/aiaa/__init__.py +12 -0
- acoular/{tools → aiaa}/aiaa.py +26 -31
- acoular/base.py +332 -0
- acoular/calib.py +129 -34
- acoular/configuration.py +13 -11
- acoular/demo/__init__.py +1 -0
- acoular/demo/acoular_demo.py +30 -17
- acoular/deprecation.py +85 -0
- acoular/environments.py +38 -24
- acoular/fastFuncs.py +90 -84
- acoular/fbeamform.py +342 -387
- acoular/fprocess.py +376 -0
- acoular/grids.py +122 -150
- acoular/h5cache.py +29 -40
- acoular/h5files.py +2 -6
- acoular/microphones.py +50 -59
- acoular/process.py +771 -0
- acoular/sdinput.py +35 -21
- acoular/signals.py +120 -113
- acoular/sources.py +208 -234
- acoular/spectra.py +59 -254
- acoular/tbeamform.py +280 -280
- acoular/tfastfuncs.py +21 -21
- acoular/tools/__init__.py +3 -7
- acoular/tools/helpers.py +218 -4
- acoular/tools/metrics.py +5 -5
- acoular/tools/utils.py +116 -0
- acoular/tprocess.py +416 -741
- acoular/traitsviews.py +15 -13
- acoular/trajectory.py +7 -10
- acoular/version.py +2 -2
- {acoular-24.7.dist-info → acoular-25.1.dist-info}/METADATA +63 -21
- acoular-25.1.dist-info/RECORD +56 -0
- {acoular-24.7.dist-info → acoular-25.1.dist-info}/WHEEL +1 -1
- acoular-24.7.dist-info/RECORD +0 -50
- {acoular-24.7.dist-info → acoular-25.1.dist-info}/licenses/AUTHORS.rst +0 -0
- {acoular-24.7.dist-info → acoular-25.1.dist-info}/licenses/LICENSE +0 -0
acoular/fastFuncs.py
CHANGED
|
@@ -9,7 +9,9 @@ import numba as nb
|
|
|
9
9
|
import numpy as np
|
|
10
10
|
|
|
11
11
|
CACHED_OPTION = True # if True: saves the numba func as compiled func in sub directory
|
|
12
|
-
|
|
12
|
+
# if numba.guvectorize is used: 'CPU' for single threading; 'parallel' for multithreading; 'cuda'
|
|
13
|
+
# for calculating on GPU
|
|
14
|
+
PARALLEL_OPTION = 'parallel'
|
|
13
15
|
FAST_OPTION = True # fastmath options
|
|
14
16
|
|
|
15
17
|
|
|
@@ -60,17 +62,18 @@ def beamformerFreq(steerVecType, boolRemovedDiagOfCSM, normFactor, inputTupleSte
|
|
|
60
62
|
|
|
61
63
|
Parameters
|
|
62
64
|
----------
|
|
63
|
-
steerVecType : (one of the following strings: 'classic' (I), 'inverse' (II), 'true level' (III),
|
|
64
|
-
Either build the steering vector via the predefined
|
|
65
|
-
I - IV (see :ref:`Sarradj, 2012<Sarradj2012>`) or pass it directly.
|
|
65
|
+
steerVecType : (one of the following strings: 'classic' (I), 'inverse' (II), 'true level' (III),
|
|
66
|
+
'true location' (IV), 'custom') Either build the steering vector via the predefined
|
|
67
|
+
formulations I - IV (see :ref:`Sarradj, 2012<Sarradj2012>`) or pass it directly.
|
|
66
68
|
boolRemovedDiagOfCSM : bool
|
|
67
69
|
Should the diagonal of the csm be removed?
|
|
68
70
|
normFactor : float
|
|
69
71
|
In here both the signalenergy loss factor (due to removal of the csm diagonal) as well as
|
|
70
72
|
beamforming algorithm (music, capon, ...) dependent normalization factors are handled.
|
|
71
|
-
inputTupleSteer : contains the information needed to create the steering vector.
|
|
73
|
+
inputTupleSteer : contains the information needed to create the steering vector. Depends on
|
|
74
|
+
steerVecType. There are 2 cases:
|
|
72
75
|
steerVecType != 'custom' :
|
|
73
|
-
inputTupleSteer = (distGridToArrayCenter, distGridToAllMics, waveNumber)
|
|
76
|
+
inputTupleSteer = (distGridToArrayCenter, distGridToAllMics, waveNumber), with
|
|
74
77
|
distGridToArrayCenter : float64[nGridpoints]
|
|
75
78
|
Distance of all gridpoints to the center of sensor array
|
|
76
79
|
distGridToAllMics : float64[nGridpoints, nMics]
|
|
@@ -92,19 +95,21 @@ def beamformerFreq(steerVecType, boolRemovedDiagOfCSM, normFactor, inputTupleSte
|
|
|
92
95
|
nEV is the number of eigenvalues which should be taken into account.
|
|
93
96
|
All passed eigenvalues will be evaluated.
|
|
94
97
|
eigVectors : complex128[nMics, nEV]
|
|
95
|
-
Eigen vectors corresponding to eigValues. All passed eigenvector slices will be
|
|
98
|
+
Eigen vectors corresponding to eigValues. All passed eigenvector slices will be
|
|
99
|
+
evaluated.
|
|
96
100
|
|
|
97
101
|
Returns
|
|
98
102
|
-------
|
|
99
103
|
*Autopower spectrum beamforming map [nGridPoints]
|
|
100
104
|
|
|
101
|
-
*steer normalization factor [nGridPoints]... contains the values the autopower needs to be
|
|
102
|
-
|
|
105
|
+
*steer normalization factor [nGridPoints]... contains the values the autopower needs to be
|
|
106
|
+
multiplied with, in order to fulfill 'steer^H * steer = 1' as needed for functional beamforming.
|
|
103
107
|
|
|
104
108
|
Some Notes on the optimization of all subroutines
|
|
105
109
|
-------------------------------------------------
|
|
106
110
|
Reducing beamforming equation:
|
|
107
|
-
Let the csm be C and the steering vector be h, than, using Linear Albegra, the conventional
|
|
111
|
+
Let the csm be C and the steering vector be h, than, using Linear Albegra, the conventional
|
|
112
|
+
beamformer can be written as
|
|
108
113
|
|
|
109
114
|
.. math:: B = h^H \\cdot C \\cdot h,
|
|
110
115
|
with ^H meaning the complex conjugated transpose.
|
|
@@ -113,30 +118,34 @@ def beamformerFreq(steerVecType, boolRemovedDiagOfCSM, normFactor, inputTupleSte
|
|
|
113
118
|
.. math:: B = h^H \\cdot C_D \\cdot h + 2 \\cdot Real(h^H \\cdot C_U \\cdot h),
|
|
114
119
|
where C_D and C_U are the diagonal part and upper part of C respectively.
|
|
115
120
|
Steering vector:
|
|
116
|
-
Theoretically the steering vector always includes the term "exp(distMicsGrid -
|
|
117
|
-
but as the steering vector gets
|
|
118
|
-
the constant "distArrayCenterGrid" cancels out -->
|
|
121
|
+
Theoretically the steering vector always includes the term "exp(distMicsGrid -
|
|
122
|
+
distArrayCenterGrid)", but as the steering vector gets multiplied with its complex
|
|
123
|
+
conjugation in all beamformer routines, the constant "distArrayCenterGrid" cancels out -->
|
|
124
|
+
In order to save operations, it is not implemented.
|
|
119
125
|
Spectral decomposition of the CSM:
|
|
120
126
|
In Linear Algebra the spectral decomposition of the CSM matrix would be:
|
|
121
127
|
|
|
122
128
|
.. math:: CSM = \\sum_{i=1}^{nEigenvalues} \\lambda_i (v_i \\cdot v_i^H) ,
|
|
123
129
|
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
|
|
125
|
-
Using this, one must not build the whole CSM (which would be time consuming), but
|
|
126
|
-
steering vector into the sum of the spectral decomp. This saves a lot of
|
|
130
|
+
v_i is the eigenvector[nEigVal,1] belonging to lambda_i and ^H denotes the complex conjugate
|
|
131
|
+
transpose. Using this, one must not build the whole CSM (which would be time consuming), but
|
|
132
|
+
can drag the steering vector into the sum of the spectral decomp. This saves a lot of
|
|
133
|
+
operations.
|
|
127
134
|
Squares:
|
|
128
135
|
Seemingly "a * a" is slightly faster than "a**2" in numba
|
|
129
136
|
Square of abs():
|
|
130
|
-
Even though "a.real**2 + a.imag**2" would have fewer operations, modern processors seem to
|
|
131
|
-
for "a * a.conj" and are slightly faster the latter way. Both Versions are much
|
|
137
|
+
Even though "a.real**2 + a.imag**2" would have fewer operations, modern processors seem to
|
|
138
|
+
be optimized for "a * a.conj" and are slightly faster the latter way. Both Versions are much
|
|
139
|
+
faster than "abs(a)**2".
|
|
132
140
|
Using Cascading Sums:
|
|
133
|
-
When using the Spectral-Decomposition-Beamformer one could use numpys cascading sums for the
|
|
134
|
-
"eigenVec.conj * steeringVector". BUT (at the moment) this only brings
|
|
135
|
-
small range of nMics (approx 250) -->
|
|
136
|
-
|
|
141
|
+
When using the Spectral-Decomposition-Beamformer one could use numpys cascading sums for the
|
|
142
|
+
scalar product "eigenVec.conj * steeringVector". BUT (at the moment) this only brings
|
|
143
|
+
benefits in comp-time for a very small range of nMics (approx 250) --> Therefore it is not
|
|
144
|
+
implemented here.
|
|
137
145
|
"""
|
|
138
146
|
boolIsEigValProb = isinstance(inputTupleCsm, tuple) # len(inputTupleCsm) > 1
|
|
139
|
-
# get the beamformer type
|
|
147
|
+
# get the beamformer type
|
|
148
|
+
# (key-tuple = (isEigValProblem, formulationOfSteeringVector, RemovalOfCSMDiag))
|
|
140
149
|
beamformerDict = {
|
|
141
150
|
(False, 'custom', False): _freqBeamformer_SpecificSteerVec_FullCSM,
|
|
142
151
|
(False, 'custom', True): _freqBeamformer_SpecificSteerVec_CsmRemovedDiag,
|
|
@@ -231,14 +240,16 @@ def _freqBeamformer_FullCSM(
|
|
|
231
240
|
result,
|
|
232
241
|
normalizeSteer,
|
|
233
242
|
):
|
|
234
|
-
# see bottom of information header of 'beamformerFreq' for information on which steps are taken,
|
|
243
|
+
# see bottom of information header of 'beamformerFreq' for information on which steps are taken,
|
|
244
|
+
# in order to gain speed improvements.
|
|
235
245
|
nMics = csm.shape[0]
|
|
236
246
|
st2 = steer_type == 2
|
|
237
247
|
st34 = steer_type == 3 or steer_type == 4
|
|
238
248
|
helpNormalize = 0.0 # just a hint for the compiler
|
|
239
249
|
for gi in nb.prange(distGridToArrayCenter.shape[0]):
|
|
240
250
|
steerVec = np.empty((nMics), np.complex128)
|
|
241
|
-
# building steering vector: in order to save some operation -> some normalization steps are
|
|
251
|
+
# building steering vector: in order to save some operation -> some normalization steps are
|
|
252
|
+
# applied after mat-vec-multipl.
|
|
242
253
|
for cntMics in range(nMics):
|
|
243
254
|
expArg = np.float32(waveNumber * distGridToAllMics[gi, cntMics])
|
|
244
255
|
steerVec[cntMics] = np.cos(expArg) - 1j * np.sin(expArg)
|
|
@@ -246,14 +257,17 @@ def _freqBeamformer_FullCSM(
|
|
|
246
257
|
helpNormalize = 0.0
|
|
247
258
|
for cntMics in range(nMics):
|
|
248
259
|
helpNormalize += distGridToAllMics[gi, cntMics] * distGridToAllMics[gi, cntMics]
|
|
249
|
-
|
|
260
|
+
# r_{t,i}-normalization is handled here
|
|
261
|
+
steerVec[cntMics] *= distGridToAllMics[gi, cntMics]
|
|
250
262
|
if st34:
|
|
251
263
|
helpNormalize = 0.0
|
|
252
264
|
for cntMics in range(nMics):
|
|
253
265
|
helpNormalize += 1.0 / (distGridToAllMics[gi, cntMics] * distGridToAllMics[gi, cntMics])
|
|
254
|
-
|
|
266
|
+
# r_{t,i}-normalization is handled here
|
|
267
|
+
steerVec[cntMics] /= distGridToAllMics[gi, cntMics]
|
|
255
268
|
|
|
256
|
-
# performing matrix-vector-multiplication (see bottom of information header of
|
|
269
|
+
# performing matrix-vector-multiplication (see bottom of information header of
|
|
270
|
+
# 'beamformerFreq)
|
|
257
271
|
scalarProd = 0.0
|
|
258
272
|
for cntMics in range(nMics):
|
|
259
273
|
leftVecMatrixProd = 0.0 + 0.0j
|
|
@@ -322,7 +336,8 @@ def _freqBeamformer_EigValues(
|
|
|
322
336
|
result,
|
|
323
337
|
normalizeSteer,
|
|
324
338
|
):
|
|
325
|
-
# see bottom of information header of 'beamformerFreq' for information on which steps are taken,
|
|
339
|
+
# see bottom of information header of 'beamformerFreq' for information on which steps are taken,
|
|
340
|
+
# in order to gain speed improvements.
|
|
326
341
|
nMics = eigVec.shape[0]
|
|
327
342
|
nEigs = len(eigVal)
|
|
328
343
|
st2 = steer_type == 2
|
|
@@ -330,7 +345,8 @@ def _freqBeamformer_EigValues(
|
|
|
330
345
|
helpNormalize = 0.0 # just a hint for the compiler
|
|
331
346
|
for gi in nb.prange(distGridToArrayCenter.shape[0]):
|
|
332
347
|
steerVec = np.empty((nMics), np.complex128)
|
|
333
|
-
# building steering vector: in order to save some operation -> some normalization steps are
|
|
348
|
+
# building steering vector: in order to save some operation -> some normalization steps are
|
|
349
|
+
# applied after mat-vec-multipl.
|
|
334
350
|
for cntMics in range(nMics):
|
|
335
351
|
expArg = np.float32(waveNumber * distGridToAllMics[gi, cntMics])
|
|
336
352
|
steerVec[cntMics] = np.cos(expArg) - 1j * np.sin(expArg)
|
|
@@ -338,12 +354,14 @@ def _freqBeamformer_EigValues(
|
|
|
338
354
|
helpNormalize = 0.0
|
|
339
355
|
for cntMics in range(nMics):
|
|
340
356
|
helpNormalize += distGridToAllMics[gi, cntMics] * distGridToAllMics[gi, cntMics]
|
|
341
|
-
|
|
357
|
+
# r_{t,i}-normalization is handled here
|
|
358
|
+
steerVec[cntMics] *= distGridToAllMics[gi, cntMics]
|
|
342
359
|
if st34:
|
|
343
360
|
helpNormalize = 0.0
|
|
344
361
|
for cntMics in range(nMics):
|
|
345
362
|
helpNormalize += 1.0 / (distGridToAllMics[gi, cntMics] * distGridToAllMics[gi, cntMics])
|
|
346
|
-
|
|
363
|
+
# r_{t,i}-normalization is handled here
|
|
364
|
+
steerVec[cntMics] /= distGridToAllMics[gi, cntMics]
|
|
347
365
|
|
|
348
366
|
# eigenvalue beamforming
|
|
349
367
|
scalarProd = 0.0
|
|
@@ -394,7 +412,8 @@ def _freqBeamformer_EigValues(
|
|
|
394
412
|
fastmath=FAST_OPTION,
|
|
395
413
|
)
|
|
396
414
|
def _freqBeamformer_SpecificSteerVec_FullCSM(csm, steerVec, signalLossNormalization, result, normalizeSteer):
|
|
397
|
-
# see bottom of information header of 'beamformerFreq' for information on which steps are taken,
|
|
415
|
+
# see bottom of information header of 'beamformerFreq' for information on which steps are taken,
|
|
416
|
+
# in order to gain speed improvements.
|
|
398
417
|
nMics = csm.shape[0]
|
|
399
418
|
|
|
400
419
|
# performing matrix-vector-multiplication (see bottom of information header of 'beamformerFreq')
|
|
@@ -403,7 +422,8 @@ def _freqBeamformer_SpecificSteerVec_FullCSM(csm, steerVec, signalLossNormalizat
|
|
|
403
422
|
for cntMics in range(nMics):
|
|
404
423
|
helpNormalize += steerVec[cntMics] * steerVec[cntMics].conjugate()
|
|
405
424
|
leftVecMatrixProd = 0.0 + 0.0j
|
|
406
|
-
|
|
425
|
+
# calculate 'steer^H * CSM' of upper-triangular-part of csm (without diagonal)
|
|
426
|
+
for cntMics2 in range(cntMics):
|
|
407
427
|
leftVecMatrixProd += csm[cntMics2, cntMics] * steerVec[cntMics2].conjugate()
|
|
408
428
|
scalarProd += (
|
|
409
429
|
2 * (leftVecMatrixProd * steerVec[cntMics]).real
|
|
@@ -424,7 +444,8 @@ def _freqBeamformer_SpecificSteerVec_FullCSM(csm, steerVec, signalLossNormalizat
|
|
|
424
444
|
fastmath=FAST_OPTION,
|
|
425
445
|
)
|
|
426
446
|
def _freqBeamformer_SpecificSteerVec_CsmRemovedDiag(csm, steerVec, signalLossNormalization, result, normalizeSteer):
|
|
427
|
-
# see bottom of information header of 'beamformerFreq' for information on which steps are taken,
|
|
447
|
+
# see bottom of information header of 'beamformerFreq' for information on which steps are taken,
|
|
448
|
+
# in order to gain speed improvements.
|
|
428
449
|
nMics = csm.shape[0]
|
|
429
450
|
|
|
430
451
|
# performing matrix-vector-multiplication (see bottom of information header of 'beamformerFreq')
|
|
@@ -433,7 +454,8 @@ def _freqBeamformer_SpecificSteerVec_CsmRemovedDiag(csm, steerVec, signalLossNor
|
|
|
433
454
|
for cntMics in range(nMics):
|
|
434
455
|
helpNormalize += steerVec[cntMics] * steerVec[cntMics].conjugate()
|
|
435
456
|
leftVecMatrixProd = 0.0 + 0.0j
|
|
436
|
-
|
|
457
|
+
# calculate 'steer^H * CSM' of upper-triangular-part of csm (without diagonal)
|
|
458
|
+
for cntMics2 in range(cntMics):
|
|
437
459
|
leftVecMatrixProd += csm[cntMics2, cntMics] * steerVec[cntMics2].conjugate()
|
|
438
460
|
scalarProd += (
|
|
439
461
|
2 * (leftVecMatrixProd * steerVec[cntMics]).real
|
|
@@ -458,7 +480,8 @@ def _freqBeamformer_EigValProb_SpecificSteerVec_FullCSM(
|
|
|
458
480
|
result,
|
|
459
481
|
normalizeSteer,
|
|
460
482
|
):
|
|
461
|
-
# see bottom of information header of 'beamformerFreq' for information on which steps are taken,
|
|
483
|
+
# see bottom of information header of 'beamformerFreq' for information on which steps are taken,
|
|
484
|
+
# in order to gain speed improvements.
|
|
462
485
|
nMics = eigVec.shape[0]
|
|
463
486
|
|
|
464
487
|
# get h^H * h for normalization
|
|
@@ -466,7 +489,8 @@ def _freqBeamformer_EigValProb_SpecificSteerVec_FullCSM(
|
|
|
466
489
|
for cntMics in range(nMics):
|
|
467
490
|
helpNormalize += steerVec[cntMics] * steerVec[cntMics].conjugate()
|
|
468
491
|
|
|
469
|
-
# performing matrix-vector-
|
|
492
|
+
# performing matrix-vector-multiplication via spectral decomp. (see bottom of information header
|
|
493
|
+
# of 'beamformerFreq')
|
|
470
494
|
scalarProdFullCSM = 0.0
|
|
471
495
|
for cntEigVal in range(len(eigVal)):
|
|
472
496
|
scalarProdFullCSMperEigVal = 0.0 + 0.0j
|
|
@@ -494,7 +518,8 @@ def _freqBeamformer_EigValProb_SpecificSteerVec_CsmRemovedDiag(
|
|
|
494
518
|
result,
|
|
495
519
|
normalizeSteer,
|
|
496
520
|
):
|
|
497
|
-
# see bottom of information header of 'beamformerFreq' for information on which steps are taken,
|
|
521
|
+
# see bottom of information header of 'beamformerFreq' for information on which steps are taken,
|
|
522
|
+
# in order to gain speed improvements.
|
|
498
523
|
nMics = eigVec.shape[0]
|
|
499
524
|
|
|
500
525
|
# get h^H * h for normalization
|
|
@@ -502,7 +527,8 @@ def _freqBeamformer_EigValProb_SpecificSteerVec_CsmRemovedDiag(
|
|
|
502
527
|
for cntMics in range(nMics):
|
|
503
528
|
helpNormalize += steerVec[cntMics] * steerVec[cntMics].conjugate()
|
|
504
529
|
|
|
505
|
-
# performing matrix-vector-
|
|
530
|
+
# performing matrix-vector-multiplication via spectral decomp. (see bottom of information header
|
|
531
|
+
# of 'beamformerFreq')
|
|
506
532
|
scalarProdReducedCSM = 0.0
|
|
507
533
|
for cntEigVal in range(len(eigVal)):
|
|
508
534
|
scalarProdFullCSMperEigVal = 0.0 + 0.0j
|
|
@@ -524,8 +550,9 @@ def calcPointSpreadFunction(steerVecType, distGridToArrayCenter, distGridToAllMi
|
|
|
524
550
|
|
|
525
551
|
Parameters
|
|
526
552
|
----------
|
|
527
|
-
steerVecType : (one of the following strings: 'classic' (I), 'inverse' (II), 'true level' (III),
|
|
528
|
-
One of the predefined formulations I - IV (see :ref:`Sarradj,
|
|
553
|
+
steerVecType : (one of the following strings: 'classic' (I), 'inverse' (II), 'true level' (III),
|
|
554
|
+
'true location' (IV)) One of the predefined formulations I - IV (see :ref:`Sarradj,
|
|
555
|
+
2012<Sarradj2012>`).
|
|
529
556
|
distGridToArrayCenter : float64[nGridpoints]
|
|
530
557
|
Distance of all gridpoints to the center of sensor array
|
|
531
558
|
distGridToAllMics : float64[nGridpoints, nMics]
|
|
@@ -534,7 +561,7 @@ def calcPointSpreadFunction(steerVecType, distGridToArrayCenter, distGridToAllMi
|
|
|
534
561
|
The free field wave number.
|
|
535
562
|
indSource : a LIST of int (e.g. indSource=[5] is fine; indSource=5 doesn't work):
|
|
536
563
|
specifies which gridpoints should be assumed to be sources
|
|
537
|
-
--> a
|
|
564
|
+
--> a separate psf will be calculated for each source
|
|
538
565
|
dtype : either 'float64' or 'float32'
|
|
539
566
|
Determines the precision of the result. For big maps this could be worth downgrading.
|
|
540
567
|
|
|
@@ -545,23 +572,26 @@ def calcPointSpreadFunction(steerVecType, distGridToArrayCenter, distGridToAllMi
|
|
|
545
572
|
Some Notes on the optimization of all subroutines
|
|
546
573
|
-------------------------------------------------
|
|
547
574
|
Reducing beamforming equation:
|
|
548
|
-
Let the steering vector be h
|
|
575
|
+
Let the steering vector be h. Then, the PSF of a SourcePoint S would be
|
|
549
576
|
|
|
550
577
|
.. math:: B = h^H \\cdot (a_S \\cdot a_S^H) \\cdot h,
|
|
551
|
-
with ^H meaning the complex conjugated transpose and a_s the transfer function from source
|
|
552
|
-
The (...)-part equals the CSM that the source would produce via the chosen
|
|
553
|
-
Using (for example) tensor calculus, one can reduce the equation
|
|
578
|
+
with ^H meaning the complex conjugated transpose and a_s the transfer function from source
|
|
579
|
+
to gridpoint. The (...)-part equals the CSM that the source would produce via the chosen
|
|
580
|
+
steering vec formulation. Using (for example) tensor calculus, one can reduce the equation
|
|
581
|
+
to:
|
|
554
582
|
|
|
555
583
|
.. math:: B = \\left| h^H \\cdot a_S \\right| ^ 2.
|
|
556
584
|
Steering vector:
|
|
557
|
-
Theoretically the steering vector always includes the term "exp(distMicsGrid -
|
|
558
|
-
|
|
585
|
+
Theoretically the steering vector always includes the term "exp(distMicsGrid -
|
|
586
|
+
distArrayCenterGrid)", but as the steering vector gets multiplied with its complex
|
|
587
|
+
conjugation in all beamformer routines, the constant "distArrayCenterGrid" cancels out -->
|
|
588
|
+
In order to save operations, it is not implemented.
|
|
559
589
|
Squares:
|
|
560
590
|
Seemingly "a * a" is slightly faster than "a**2" in numba
|
|
561
591
|
Square of abs():
|
|
562
|
-
Even though "a.real**2 + a.imag**^2" would have fewer operations, modern processors seem to
|
|
563
|
-
|
|
564
|
-
|
|
592
|
+
Even though "a.real**2 + a.imag**^2" would have fewer operations, modern processors seem to
|
|
593
|
+
be optimized for "a * a.conj" and are slightly faster the latter way. Both Versions are much
|
|
594
|
+
faster than "abs(a)**2".
|
|
565
595
|
"""
|
|
566
596
|
# get the steering vector formulation
|
|
567
597
|
psfDict = {
|
|
@@ -613,7 +643,8 @@ def _psf_Formulation1AkaClassic(
|
|
|
613
643
|
): # noqa ARG001
|
|
614
644
|
nMics = distGridToAllMics.shape[0]
|
|
615
645
|
for cntSources in range(len(distSourcesToArrayCenter)):
|
|
616
|
-
# see bottom of information header of 'calcPointSpreadFunction' for infos on the PSF
|
|
646
|
+
# see bottom of information header of 'calcPointSpreadFunction' for infos on the PSF
|
|
647
|
+
# calculation and speed improvements.
|
|
617
648
|
scalarProd = 0.0 + 0.0j
|
|
618
649
|
for cntMics in range(nMics):
|
|
619
650
|
expArg = np.float32(
|
|
@@ -646,7 +677,8 @@ def _psf_Formulation2AkaInverse(
|
|
|
646
677
|
):
|
|
647
678
|
nMics = distGridToAllMics.shape[0]
|
|
648
679
|
for cntSources in range(len(distSourcesToArrayCenter)):
|
|
649
|
-
# see bottom of information header of 'calcPointSpreadFunction' for infos on the PSF
|
|
680
|
+
# see bottom of information header of 'calcPointSpreadFunction' for infos on the PSF
|
|
681
|
+
# calculation and speed improvements.
|
|
650
682
|
scalarProd = 0.0 + 0.0j
|
|
651
683
|
for cntMics in range(nMics):
|
|
652
684
|
expArg = np.float32(
|
|
@@ -683,7 +715,8 @@ def _psf_Formulation3AkaTrueLevel(
|
|
|
683
715
|
):
|
|
684
716
|
nMics = distGridToAllMics.shape[0]
|
|
685
717
|
for cntSources in range(len(distSourcesToArrayCenter)):
|
|
686
|
-
# see bottom of information header of 'calcPointSpreadFunction' for infos on the PSF
|
|
718
|
+
# see bottom of information header of 'calcPointSpreadFunction' for infos on the PSF
|
|
719
|
+
# calculation and speed improvements.
|
|
687
720
|
scalarProd = 0.0 + 0.0j
|
|
688
721
|
helpNormalizeGrid = 0.0
|
|
689
722
|
for cntMics in range(nMics):
|
|
@@ -722,7 +755,8 @@ def _psf_Formulation4AkaTrueLocation(
|
|
|
722
755
|
): # noqa ARG001
|
|
723
756
|
nMics = distGridToAllMics.shape[0]
|
|
724
757
|
for cntSources in range(len(distSourcesToArrayCenter)):
|
|
725
|
-
# see bottom of information header of 'calcPointSpreadFunction' for infos on the PSF
|
|
758
|
+
# see bottom of information header of 'calcPointSpreadFunction' for infos on the PSF
|
|
759
|
+
# calculation and speed improvements.
|
|
726
760
|
scalarProd = 0.0 + 0.0j
|
|
727
761
|
helpNormalizeGrid = 0.0
|
|
728
762
|
for cntMics in range(nMics):
|
|
@@ -740,21 +774,6 @@ def _psf_Formulation4AkaTrueLocation(
|
|
|
740
774
|
result[cntSources] = scalarProdAbsSquared * (normalizeFactor * normalizeFactor) / nMics / helpNormalizeGrid
|
|
741
775
|
|
|
742
776
|
|
|
743
|
-
# CURRENTLY NOT NEEDED, AS CUSTOM PSF WILL BE CALCULATED IN fbeamform.SteeringVector WITH THE USE OF Trait transfer
|
|
744
|
-
# @nb.guvectorize([(nb.float64[:], nb.float64[:], nb.float64[:], nb.float64[:,:], nb.float64[:], nb.float64[:]),
|
|
745
|
-
# (nb.float64[:], nb.float64[:], nb.float64[:], nb.float64[:,:], nb.float64[:], nb.float32[:])],
|
|
746
|
-
# '(),(m),(s),(s,m),()->(s)', nopython=True, target=PARALLEL_OPTION, cache=CACHED_OPTION)
|
|
747
|
-
# def _psf_SpecificSteerVec(steerVec, steerVecSources, result):
|
|
748
|
-
# nMics = len(steerVec)
|
|
749
|
-
# for cntSources in range(steerVecSources.shape[0]):
|
|
750
|
-
# # see bottom of information header of 'calcPointSpreadFunction' for infos on the PSF calculation and speed improvements.
|
|
751
|
-
# scalarProd = 0.0 + 0.0j
|
|
752
|
-
# for cntMics in range(nMics):
|
|
753
|
-
# scalarProd += steerVec[cntMics].conjugate() * steerVecSources[cntSources, cntMics]
|
|
754
|
-
# scalarProdAbsSquared = (scalarProd * scalarProd.conjugate()).real
|
|
755
|
-
# result[cntSources] = scalarProdAbsSquared
|
|
756
|
-
|
|
757
|
-
|
|
758
777
|
# %% Damas - Gauss Seidel
|
|
759
778
|
# Formerly known as 'gseidel'
|
|
760
779
|
@nb.guvectorize(
|
|
@@ -791,19 +810,6 @@ def damasSolverGaussSeidel(A, dirtyMap, nIterations, relax, damasSolution):
|
|
|
791
810
|
None : as damasSolution is overwritten with end result of the damas iterative solver.
|
|
792
811
|
|
|
793
812
|
"""
|
|
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
|
|
807
813
|
nGridPoints = len(dirtyMap)
|
|
808
814
|
for _cntIter in range(nIterations[0]):
|
|
809
815
|
for cntGrid in range(nGridPoints):
|