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.
- acoular/__init__.py +119 -54
- acoular/calib.py +29 -38
- acoular/configuration.py +132 -82
- acoular/demo/__init__.py +10 -4
- acoular/demo/acoular_demo.py +73 -55
- acoular/environments.py +270 -264
- acoular/fastFuncs.py +366 -196
- acoular/fbeamform.py +1797 -1934
- acoular/grids.py +504 -548
- acoular/h5cache.py +74 -83
- acoular/h5files.py +159 -142
- acoular/internal.py +13 -14
- acoular/microphones.py +57 -53
- acoular/sdinput.py +57 -53
- acoular/signals.py +180 -178
- acoular/sources.py +920 -724
- acoular/spectra.py +353 -363
- acoular/tbeamform.py +416 -416
- acoular/tfastfuncs.py +180 -104
- acoular/tools/__init__.py +25 -0
- acoular/tools/aiaa.py +185 -0
- acoular/tools/helpers.py +189 -0
- acoular/tools/metrics.py +165 -0
- acoular/tprocess.py +1240 -1182
- acoular/traitsviews.py +513 -501
- acoular/trajectory.py +50 -52
- acoular/version.py +5 -6
- acoular/xml/minidsp_uma-16.xml +20 -0
- acoular/xml/{minidsp_uma16.xml → minidsp_uma-16_mirrored.xml} +3 -0
- {acoular-24.3.dist-info → acoular-24.7.dist-info}/METADATA +58 -39
- acoular-24.7.dist-info/RECORD +50 -0
- {acoular-24.3.dist-info → acoular-24.7.dist-info}/WHEEL +1 -1
- acoular-24.7.dist-info/licenses/LICENSE +28 -0
- acoular/fileimport.py +0 -380
- acoular/nidaqimport.py +0 -273
- acoular/tests/reference_data/BeamformerBase.npy +0 -0
- acoular/tests/reference_data/BeamformerBaseFalse1.npy +0 -0
- acoular/tests/reference_data/BeamformerBaseFalse2.npy +0 -0
- acoular/tests/reference_data/BeamformerBaseFalse3.npy +0 -0
- acoular/tests/reference_data/BeamformerBaseFalse4.npy +0 -0
- acoular/tests/reference_data/BeamformerBaseTrue1.npy +0 -0
- acoular/tests/reference_data/BeamformerBaseTrue2.npy +0 -0
- acoular/tests/reference_data/BeamformerBaseTrue3.npy +0 -0
- acoular/tests/reference_data/BeamformerBaseTrue4.npy +0 -0
- acoular/tests/reference_data/BeamformerCMFLassoLarsBIC.npy +0 -0
- acoular/tests/reference_data/BeamformerCMFNNLS.npy +0 -0
- acoular/tests/reference_data/BeamformerCapon.npy +0 -0
- acoular/tests/reference_data/BeamformerClean.npy +0 -0
- acoular/tests/reference_data/BeamformerCleansc.npy +0 -0
- acoular/tests/reference_data/BeamformerCleant.npy +0 -0
- acoular/tests/reference_data/BeamformerCleantSq.npy +0 -0
- acoular/tests/reference_data/BeamformerCleantSqTraj.npy +0 -0
- acoular/tests/reference_data/BeamformerCleantTraj.npy +0 -0
- acoular/tests/reference_data/BeamformerDamas.npy +0 -0
- acoular/tests/reference_data/BeamformerDamasPlus.npy +0 -0
- acoular/tests/reference_data/BeamformerEig.npy +0 -0
- acoular/tests/reference_data/BeamformerEigFalse1.npy +0 -0
- acoular/tests/reference_data/BeamformerEigFalse2.npy +0 -0
- acoular/tests/reference_data/BeamformerEigFalse3.npy +0 -0
- acoular/tests/reference_data/BeamformerEigFalse4.npy +0 -0
- acoular/tests/reference_data/BeamformerEigTrue1.npy +0 -0
- acoular/tests/reference_data/BeamformerEigTrue2.npy +0 -0
- acoular/tests/reference_data/BeamformerEigTrue3.npy +0 -0
- acoular/tests/reference_data/BeamformerEigTrue4.npy +0 -0
- acoular/tests/reference_data/BeamformerFunctional.npy +0 -0
- acoular/tests/reference_data/BeamformerGIB.npy +0 -0
- acoular/tests/reference_data/BeamformerGridlessOrth.npy +0 -0
- acoular/tests/reference_data/BeamformerMusic.npy +0 -0
- acoular/tests/reference_data/BeamformerOrth.npy +0 -0
- acoular/tests/reference_data/BeamformerSODIX.npy +0 -0
- acoular/tests/reference_data/BeamformerTime.npy +0 -0
- acoular/tests/reference_data/BeamformerTimeSq.npy +0 -0
- acoular/tests/reference_data/BeamformerTimeSqTraj.npy +0 -0
- acoular/tests/reference_data/BeamformerTimeTraj.npy +0 -0
- acoular/tests/reference_data/Environment.npy +0 -0
- acoular/tests/reference_data/Example1_numerical_values_testsum.h5 +0 -0
- acoular/tests/reference_data/FiltFiltOctave__.npy +0 -0
- acoular/tests/reference_data/FiltFiltOctave_band_100_0_fraction_Thirdoctave_.npy +0 -0
- acoular/tests/reference_data/FiltFreqWeight_weight_A_.npy +0 -0
- acoular/tests/reference_data/FiltFreqWeight_weight_C_.npy +0 -0
- acoular/tests/reference_data/FiltFreqWeight_weight_Z_.npy +0 -0
- acoular/tests/reference_data/FiltOctave__.npy +0 -0
- acoular/tests/reference_data/FiltOctave_band_100_0_fraction_Thirdoctave_.npy +0 -0
- acoular/tests/reference_data/Filter__.npy +0 -0
- acoular/tests/reference_data/GeneralFlowEnvironment.npy +0 -0
- acoular/tests/reference_data/OctaveFilterBank__.npy +0 -0
- acoular/tests/reference_data/OpenJet.npy +0 -0
- acoular/tests/reference_data/PointSource.npy +0 -0
- acoular/tests/reference_data/PowerSpectra_csm.npy +0 -0
- acoular/tests/reference_data/PowerSpectra_ev.npy +0 -0
- acoular/tests/reference_data/RotatingFlow.npy +0 -0
- acoular/tests/reference_data/SlotJet.npy +0 -0
- acoular/tests/reference_data/TimeAverage__.npy +0 -0
- acoular/tests/reference_data/TimeCumAverage__.npy +0 -0
- acoular/tests/reference_data/TimeExpAverage_weight_F_.npy +0 -0
- acoular/tests/reference_data/TimeExpAverage_weight_I_.npy +0 -0
- acoular/tests/reference_data/TimeExpAverage_weight_S_.npy +0 -0
- acoular/tests/reference_data/TimeInOut__.npy +0 -0
- acoular/tests/reference_data/TimePower__.npy +0 -0
- acoular/tests/reference_data/TimeReverse__.npy +0 -0
- acoular/tests/reference_data/UniformFlowEnvironment.npy +0 -0
- acoular/tests/reference_data/beamformer_traj_time_data.h5 +0 -0
- acoular/tests/run_tests.sh +0 -18
- acoular/tests/run_tests_osx.sh +0 -16
- acoular/tests/test.npy +0 -0
- acoular/tests/test_beamformer_results.py +0 -213
- acoular/tests/test_classes.py +0 -60
- acoular/tests/test_digest.py +0 -125
- acoular/tests/test_environments.py +0 -73
- acoular/tests/test_example1.py +0 -124
- acoular/tests/test_grid.py +0 -92
- acoular/tests/test_integrate.py +0 -102
- acoular/tests/test_signals.py +0 -60
- acoular/tests/test_sources.py +0 -65
- acoular/tests/test_spectra.py +0 -38
- acoular/tests/test_timecache.py +0 -35
- acoular/tests/test_tprocess.py +0 -90
- acoular/tests/test_traj_beamformer_results.py +0 -164
- acoular/tests/unsupported/SpeedComparison/OvernightTestcasesBeamformer_nMics32_nGridPoints100_nFreqs4_nTrials10.png +0 -0
- acoular/tests/unsupported/SpeedComparison/cythonBeamformer.pyx +0 -237
- acoular/tests/unsupported/SpeedComparison/mainForCython.py +0 -103
- acoular/tests/unsupported/SpeedComparison/mainForParallelJit.py +0 -143
- acoular/tests/unsupported/SpeedComparison/setupCythonOpenMP.py +0 -63
- acoular/tests/unsupported/SpeedComparison/sharedFunctions.py +0 -153
- acoular/tests/unsupported/SpeedComparison/timeOverNMics_AllImportantMethods.png +0 -0
- acoular/tests/unsupported/SpeedComparison/timeOverNMics_faverage.png +0 -0
- acoular/tests/unsupported/SpeedComparison/vglOptimierungFAverage.py +0 -204
- acoular/tests/unsupported/SpeedComparison/vglOptimierungGaussSeidel.py +0 -182
- acoular/tests/unsupported/SpeedComparison/vglOptimierungR_BEAMFULL_INVERSE.py +0 -764
- acoular/tests/unsupported/SpeedComparison/vglOptimierungR_BEAM_OS.py +0 -231
- acoular/tests/unsupported/SpeedComparison/whatsFastestWayFor_absASquared.py +0 -48
- acoular/tests/unsupported/functionalBeamformer.py +0 -123
- acoular/tests/unsupported/precisionTest.py +0 -153
- acoular/tests/unsupported/validationOfBeamformerFuncsPOSTAcoularIntegration.py +0 -254
- acoular/tests/unsupported/validationOfBeamformerFuncsPREeAcoularIntegration.py +0 -531
- acoular/tools.py +0 -422
- acoular-24.3.dist-info/RECORD +0 -148
- acoular-24.3.dist-info/licenses/LICENSE +0 -29
- {acoular-24.3.dist-info → acoular-24.7.dist-info}/licenses/AUTHORS.rst +0 -0
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
import unittest
|
|
2
|
-
|
|
3
|
-
from os.path import join
|
|
4
|
-
|
|
5
|
-
import numpy as np
|
|
6
|
-
|
|
7
|
-
from acoular import config
|
|
8
|
-
config.global_caching = 'none'
|
|
9
|
-
|
|
10
|
-
from acoular import WNoiseGenerator, MovingPointSource, WriteH5, Trajectory, MicGeom,\
|
|
11
|
-
RectGrid, MaskedTimeSamples, SteeringVector, TimeAverage, BeamformerTimeSqTraj, BeamformerTimeTraj,\
|
|
12
|
-
BeamformerCleantTraj, BeamformerCleantSqTraj, BeamformerTime, BeamformerTimeSq,\
|
|
13
|
-
BeamformerCleant, BeamformerCleantSq
|
|
14
|
-
|
|
15
|
-
# if this flag is set to True, new time data will be simulated and
|
|
16
|
-
WRITE_NEW_REFERENCE_DATA = False
|
|
17
|
-
# new beamformer results are generated for comparison during testing. Should always be False. Only set to
|
|
18
|
-
# true, if it is necessary to recalculate the data, due to wanted changes of the Beamformers (or MovingPointSource).
|
|
19
|
-
|
|
20
|
-
# Parameters
|
|
21
|
-
FNAME = join('reference_data','beamformer_traj_time_data.h5')
|
|
22
|
-
SFREQ = 6000
|
|
23
|
-
SPEED = 10 # km/h
|
|
24
|
-
SEED = 1
|
|
25
|
-
D = .5
|
|
26
|
-
SOURCE_POS = (0.0, 0.0, D)
|
|
27
|
-
passby_dist = .5 # distance that the source is passing in front of array
|
|
28
|
-
CONV_AMP = True
|
|
29
|
-
|
|
30
|
-
# create linear mic geom
|
|
31
|
-
MGEOM = MicGeom()
|
|
32
|
-
N = 5
|
|
33
|
-
L = .5
|
|
34
|
-
MGEOM.mpos_tot = np.zeros((3, N), dtype=np.float64)
|
|
35
|
-
win = np.sin(np.arange(N)*np.pi/(N-1))
|
|
36
|
-
b = 0.4
|
|
37
|
-
MGEOM.mpos_tot[0] = np.linspace(-L, L, N)*(1-b)/(win*b+1-b)
|
|
38
|
-
|
|
39
|
-
# Monopole Trajectory
|
|
40
|
-
t_passby = passby_dist/SPEED/3.6
|
|
41
|
-
nsamples = int(t_passby*SFREQ)
|
|
42
|
-
TRAJ = Trajectory() # source center
|
|
43
|
-
TRAJ.points[0] = (-passby_dist/2 + SOURCE_POS[0], SOURCE_POS[1], SOURCE_POS[2])
|
|
44
|
-
TRAJ.points[t_passby] = (+passby_dist/2, SOURCE_POS[1], SOURCE_POS[2])
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
def create_test_time_data(nsamples):
|
|
48
|
-
"""
|
|
49
|
-
creates test data for a single moving monopole emitting white noise
|
|
50
|
-
|
|
51
|
-
Parameters
|
|
52
|
-
----------
|
|
53
|
-
speed : float
|
|
54
|
-
source velocity in m/s.
|
|
55
|
-
|
|
56
|
-
Returns
|
|
57
|
-
-------
|
|
58
|
-
None.
|
|
59
|
-
|
|
60
|
-
"""
|
|
61
|
-
n1 = WNoiseGenerator(sample_freq=SFREQ, numsamples=nsamples, seed=SEED)
|
|
62
|
-
p1 = MovingPointSource(signal=n1, mics=MGEOM,
|
|
63
|
-
trajectory=TRAJ, conv_amp=CONV_AMP)
|
|
64
|
-
wh5 = WriteH5(source=p1, name=FNAME)
|
|
65
|
-
print(50*"#")
|
|
66
|
-
print(f"create {FNAME} ...")
|
|
67
|
-
print(f"num samples: {nsamples}, pass-by time: {t_passby}s")
|
|
68
|
-
print(50*"#")
|
|
69
|
-
wh5.save()
|
|
70
|
-
|
|
71
|
-
def get_beamformer_traj_result(Beamformer, num=32):
|
|
72
|
-
"""
|
|
73
|
-
returns the result for a given Beamformer class
|
|
74
|
-
|
|
75
|
-
Parameters
|
|
76
|
-
----------
|
|
77
|
-
Beamformer : cls
|
|
78
|
-
trajectory beamformer.
|
|
79
|
-
num : int, optional
|
|
80
|
-
number of samples to return. The default is 32.
|
|
81
|
-
|
|
82
|
-
Returns
|
|
83
|
-
-------
|
|
84
|
-
array
|
|
85
|
-
first block returned by the trajectory beamformers result() function.
|
|
86
|
-
|
|
87
|
-
"""
|
|
88
|
-
## with moving grid
|
|
89
|
-
ts = MaskedTimeSamples(name=FNAME)
|
|
90
|
-
gMoving = RectGrid(x_min=-.1, x_max=.1, y_min=0, y_max=0, z=0,
|
|
91
|
-
increment=.1)
|
|
92
|
-
stMoving = SteeringVector(grid=gMoving, mics=MGEOM)
|
|
93
|
-
bt = Beamformer(source=ts, trajectory=TRAJ, steer=stMoving)
|
|
94
|
-
if hasattr(bt,'n_iter'):
|
|
95
|
-
bt.n_iter = 2
|
|
96
|
-
return next(bt.result(num)).astype(np.float32)
|
|
97
|
-
|
|
98
|
-
def get_beamformer_time_result(Beamformer, num=32):
|
|
99
|
-
"""
|
|
100
|
-
returns the result for a given time Beamformer class
|
|
101
|
-
|
|
102
|
-
Parameters
|
|
103
|
-
----------
|
|
104
|
-
Beamformer : cls
|
|
105
|
-
time beamformer.
|
|
106
|
-
num : int, optional
|
|
107
|
-
number of samples to return. The default is 32.
|
|
108
|
-
|
|
109
|
-
Returns
|
|
110
|
-
-------
|
|
111
|
-
array
|
|
112
|
-
first block returned by the time beamformers result() function.
|
|
113
|
-
|
|
114
|
-
"""
|
|
115
|
-
## with moving grid
|
|
116
|
-
ts = MaskedTimeSamples(name=FNAME)
|
|
117
|
-
gfixed = RectGrid(x_min=-.1, x_max=.1, y_min=0, y_max=0, z=D,
|
|
118
|
-
increment=.1)
|
|
119
|
-
stfixed = SteeringVector(grid=gfixed, mics=MGEOM)
|
|
120
|
-
bt = Beamformer(source=ts,steer=stfixed)
|
|
121
|
-
if hasattr(bt,'n_iter'):
|
|
122
|
-
bt.n_iter = 2
|
|
123
|
-
return next(bt.result(num)).astype(np.float32)
|
|
124
|
-
|
|
125
|
-
class BeamformerTimeTest(unittest.TestCase):
|
|
126
|
-
"""
|
|
127
|
-
A simple test case that varifies that the results of trajectory beamformers
|
|
128
|
-
and fixed focus beamformers in time domain are not changing across different
|
|
129
|
-
versions of code.
|
|
130
|
-
"""
|
|
131
|
-
|
|
132
|
-
traj_beamformers = [BeamformerTimeTraj, BeamformerTimeSqTraj,
|
|
133
|
-
BeamformerCleantTraj, BeamformerCleantSqTraj]
|
|
134
|
-
|
|
135
|
-
time_beamformers = [BeamformerTime, BeamformerTimeSq,
|
|
136
|
-
BeamformerCleant, BeamformerCleantSq]
|
|
137
|
-
|
|
138
|
-
def test_beamformer_traj_result(self):
|
|
139
|
-
"""compare results of trajectory beamformers against previous
|
|
140
|
-
results from .h5 file"""
|
|
141
|
-
for beamformer in self.traj_beamformers:
|
|
142
|
-
with self.subTest(beamformer.__name__):
|
|
143
|
-
name = join('reference_data',f'{beamformer.__name__}.npy')
|
|
144
|
-
actual_data = get_beamformer_traj_result(beamformer)
|
|
145
|
-
if WRITE_NEW_REFERENCE_DATA:
|
|
146
|
-
np.save(name,actual_data)
|
|
147
|
-
ref_data = np.load(name)
|
|
148
|
-
np.testing.assert_allclose(actual_data, ref_data, rtol=5e-5, atol=5e-6)
|
|
149
|
-
|
|
150
|
-
def test_beamformer_time_result(self):
|
|
151
|
-
"""compare results of time beamformers with fixed focus against previous
|
|
152
|
-
results from .h5 file"""
|
|
153
|
-
for beamformer in self.time_beamformers:
|
|
154
|
-
with self.subTest(beamformer.__name__):
|
|
155
|
-
name = join('reference_data',f'{beamformer.__name__}.npy')
|
|
156
|
-
actual_data = get_beamformer_time_result(beamformer)
|
|
157
|
-
if WRITE_NEW_REFERENCE_DATA:
|
|
158
|
-
np.save(name,actual_data)
|
|
159
|
-
ref_data = np.load(name)
|
|
160
|
-
np.testing.assert_allclose(actual_data, ref_data, rtol=5e-5, atol=5e-6)
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
if __name__ == '__main__':
|
|
164
|
-
unittest.main()
|
|
Binary file
|
|
@@ -1,237 +0,0 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
cimport numpy as np
|
|
3
|
-
|
|
4
|
-
from libc.math cimport exp as c_exp
|
|
5
|
-
from libc.math cimport sin as c_sin
|
|
6
|
-
from libc.math cimport cos as c_cos
|
|
7
|
-
|
|
8
|
-
from cython.parallel import prange, parallel
|
|
9
|
-
from cython import boundscheck, wraparound, nonecheck, cdivision
|
|
10
|
-
from cpython cimport array
|
|
11
|
-
import array
|
|
12
|
-
|
|
13
|
-
#ZUM PARALLELISIEREN MIT CYTHON
|
|
14
|
-
#1. Inplace Operatoren ("+=", etc) kommen hier eine besondere Bedeutung zu.
|
|
15
|
-
#2. Bei Cython-Version 0.25.2 gibt es einen Bug beim Zuweisen von numpy-Arrays:
|
|
16
|
-
# Wenn ein Vektor zuerst vollgeschrieben und im späteren Verlauf der Methode
|
|
17
|
-
# wieder ausgelesen wird, wurden nicht die korrekten Werte ausgelesen.
|
|
18
|
-
# Wurde der Vektor/Matrix allerdings nur einmalig geschrieben und dann returned,
|
|
19
|
-
# war alles okay. Ist im Code unten nochmal am Bsp. "beamformerCython" beschrieben.
|
|
20
|
-
# Dieses Problem tritt nur auf, falls der Code über prange parallelisiert wird.
|
|
21
|
-
# Außerdem tritt der Fehler nicht immer auf. Liegt vllt an unausgereifter Ausnutzung
|
|
22
|
-
# der gesharedten Caches.
|
|
23
|
-
#3. Welche Variablen Thread-private und welche geshared werden sollen, entscheidet
|
|
24
|
-
# Cython selbst.
|
|
25
|
-
#4. Beim Beamformer (s.u.) hat das parallelisieren mit 'prange' zu erheblichen Einbußen in
|
|
26
|
-
# der Laufzeit geführt (ca 5x LANGSAMER). Es gibt allerdings einfache BSPs
|
|
27
|
-
# ("c_arrayOpenMP", "c_array", s.u.), bei denen mit gleichen Compiler-Optionen
|
|
28
|
-
# wie beim Beamformer durch die Parallelisierung mit 'prange' erhebliche
|
|
29
|
-
# Laufzeitverbesserungen erreicht werden.
|
|
30
|
-
#5. Es muss ein setup-File mit den Kompilieroptionen erstellt werden. In diesem
|
|
31
|
-
# Fall ist dies "setupCythonOpenMP.py". Danach wird über die Konsole mit dem
|
|
32
|
-
# Befehl "python setupCythonOpenMP.py build_ext --inplace" kompiliert.
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
#==============================================================================
|
|
38
|
-
# # Das Ganze wird fuer effizientes indexing gebraucht...
|
|
39
|
-
DTYPEComplex = np.complex128
|
|
40
|
-
DTYPEReal = np.float
|
|
41
|
-
ctypedef np.complex128_t DTYPEComplex_t
|
|
42
|
-
ctypedef np.float_t DTYPEReal_t
|
|
43
|
-
#==============================================================================
|
|
44
|
-
|
|
45
|
-
# Die Dekoratoren sollen nochmals Schnelligkeit bringen.
|
|
46
|
-
@nonecheck(False)
|
|
47
|
-
@boundscheck(False)
|
|
48
|
-
@wraparound(False)
|
|
49
|
-
@cdivision(True)
|
|
50
|
-
def beamformerCython(np.ndarray[DTYPEComplex_t, ndim=3] csm, np.ndarray[DTYPEReal_t] r0, np.ndarray[DTYPEReal_t, ndim=2] rm, np.ndarray[DTYPEComplex_t] kj):
|
|
51
|
-
#def beamformerCython(complex[:,:,:] csm, double[:] r0, double[:,:] rm, complex[:] kj): # Standard Methodenkopf (laut Doku etwas langsamer)
|
|
52
|
-
""" Dies ist eine Implementierung der Methode 'r_beamfull_inverse' der
|
|
53
|
-
mit scipy.weave erzeugten 'beamformer.so'. Benutzt Parallelisierung via
|
|
54
|
-
cythons 'prange' und Kompilierung mit OpenMP.
|
|
55
|
-
"""
|
|
56
|
-
cdef int nFreqs = csm.shape[0]
|
|
57
|
-
cdef int nGridPoints = len(r0)
|
|
58
|
-
cdef int nMics = csm.shape[1]
|
|
59
|
-
|
|
60
|
-
cdef double[:,:] beamformOutput = np.zeros([nFreqs, nGridPoints], dtype=DTYPEReal)
|
|
61
|
-
cdef complex[:] steerVec = np.zeros([nMics], dtype=DTYPEComplex)
|
|
62
|
-
|
|
63
|
-
cdef int cntFreqs, cntGrid, cntMics, cntMics2, cntMics1
|
|
64
|
-
cdef double r01, kjj, rm1, temp1, rs, temp3
|
|
65
|
-
cdef complex temp2
|
|
66
|
-
# cdef float temp3 # Das hat erstmal nicht auf Anhieb geklappt, deshalb ist temp3 noch double
|
|
67
|
-
|
|
68
|
-
for cntFreqs in range(nFreqs):
|
|
69
|
-
kjj = kj[cntFreqs].imag
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
with nogil, parallel():
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
# Mit Chef drüber reden.
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
for cntGrid in prange(nGridPoints, schedule='static'): # Parallelisierung
|
|
84
|
-
r01 = r0[cntGrid]
|
|
85
|
-
rs = r01 ** 2
|
|
86
|
-
temp1 = 0.0
|
|
87
|
-
for cntFreqs in range(nFreqs):
|
|
88
|
-
kjj = kj[cntFreqs].imag
|
|
89
|
-
for cntGrid in range(nGridPoints):
|
|
90
|
-
rs = 0
|
|
91
|
-
r01 = r0[cntGrid]
|
|
92
|
-
for cntMics in range(nMics):
|
|
93
|
-
rm1 = rm[cntGrid, cntMics]
|
|
94
|
-
rs += 1.0 / (rm1 ** 2)
|
|
95
|
-
temp3 = (kjj * (rm1 - r01))
|
|
96
|
-
steerVec[cntMics] = (c_cos(temp3) - 1j * c_sin(temp3)) * rm1
|
|
97
|
-
rs = r01 ** 2
|
|
98
|
-
|
|
99
|
-
temp1 = 0.0
|
|
100
|
-
for cntMics in range(nMics):
|
|
101
|
-
temp2 = 0.0
|
|
102
|
-
for cntMics2 in range(cntMics):
|
|
103
|
-
temp2 = temp2 + csm[cntFreqs, cntMics2, cntMics] * steerVec[cntMics2] # Falls nicht mit prange gearbeitet wird, kann man "+= etc" wie sonst benutzen
|
|
104
|
-
temp1 = temp1 + 2 * (temp2 * steerVec[cntMics].conjugate()).real
|
|
105
|
-
temp1 = temp1 + (csm[cntFreqs, cntMics, cntMics] * (steerVec[cntMics]).conjugate() * steerVec[cntMics]).real
|
|
106
|
-
beamformOutput[cntFreqs, cntGrid] = (temp1 / rs)
|
|
107
|
-
return beamformOutput
|
|
108
|
-
|
|
109
|
-
@boundscheck(False)
|
|
110
|
-
@wraparound(False)
|
|
111
|
-
@nonecheck(False)
|
|
112
|
-
@cdivision(True)
|
|
113
|
-
def beamformerCythonNOTparallel(np.ndarray[DTYPEComplex_t, ndim=3] csm, np.ndarray[DTYPEReal_t] r0, np.ndarray[DTYPEReal_t, ndim=2] rm, np.ndarray[DTYPEComplex_t] kj):
|
|
114
|
-
""" Dies ist eine Implementierung der Methode 'r_beamfull_inverse' der
|
|
115
|
-
mit scipy.weave erzeugten 'beamformer.so', OHNE Parallelisierung.
|
|
116
|
-
"""
|
|
117
|
-
cdef int nFreqs = csm.shape[0]
|
|
118
|
-
cdef int nGridPoints = len(r0)
|
|
119
|
-
cdef int nMics = csm.shape[1]
|
|
120
|
-
|
|
121
|
-
cdef double[:,:] beamformOutput = np.zeros([nFreqs, nGridPoints], dtype=DTYPEReal)
|
|
122
|
-
cdef complex[:] steerVec = np.zeros([nMics], dtype=DTYPEComplex)
|
|
123
|
-
|
|
124
|
-
cdef int cntFreqs, cntGrid, cntMics, cntMics2
|
|
125
|
-
cdef double rs, r01, kjj, rm1, temp1, temp3
|
|
126
|
-
cdef complex temp2
|
|
127
|
-
# cdef float temp3
|
|
128
|
-
|
|
129
|
-
for cntFreqs in range(nFreqs):
|
|
130
|
-
kjj = kj[cntFreqs].imag
|
|
131
|
-
for cntGrid in range(nGridPoints):
|
|
132
|
-
rs = 0
|
|
133
|
-
r01 = r0[cntGrid]
|
|
134
|
-
for cntMics in range(nMics):
|
|
135
|
-
rm1 = rm[cntGrid, cntMics]
|
|
136
|
-
rs += 1.0 / (rm1 ** 2)
|
|
137
|
-
temp3 = (kjj * (rm1 - r01))
|
|
138
|
-
steerVec[cntMics] = (c_cos(temp3) - 1j * c_sin(temp3)) * rm1
|
|
139
|
-
rs = r01 ** 2
|
|
140
|
-
|
|
141
|
-
temp1 = 0.0
|
|
142
|
-
for cntMics in range(nMics):
|
|
143
|
-
temp2 = 0.0
|
|
144
|
-
for cntMics2 in range(cntMics):
|
|
145
|
-
temp2 += csm[cntFreqs, cntMics2, cntMics] * steerVec[cntMics2] # Falls nicht mit prange gearbeitet wird, kann man "+= etc" wie sonst benutzen
|
|
146
|
-
temp1 += 2 * (temp2 * steerVec[cntMics].conjugate()).real
|
|
147
|
-
temp1 += (csm[cntFreqs, cntMics, cntMics] * (steerVec[cntMics]).conjugate() * steerVec[cntMics]).real
|
|
148
|
-
beamformOutput[cntFreqs, cntGrid] = (temp1 / rs)
|
|
149
|
-
return beamformOutput
|
|
150
|
-
|
|
151
|
-
@nonecheck(False)
|
|
152
|
-
@boundscheck(False)
|
|
153
|
-
@wraparound(False)
|
|
154
|
-
@cdivision(True)
|
|
155
|
-
def beamformerCythonCorrectButSlow(np.ndarray[DTYPEComplex_t, ndim=3] csm, np.ndarray[DTYPEReal_t] r0, np.ndarray[DTYPEReal_t, ndim=2] rm, np.ndarray[DTYPEComplex_t] kj):
|
|
156
|
-
#def beamformerCython(complex[:,:,:] csm, double[:] r0, double[:,:] rm, complex[:] kj): # Standard Methodenkopf (laut Doku etwas langsamer)
|
|
157
|
-
""" Dies ist eine Implementierung der Methode 'r_beamfull_inverse' der
|
|
158
|
-
mit scipy.weave erzeugten 'beamformer.so'. Benutzt Parallelisierung via
|
|
159
|
-
cythons 'prange' und Kompilierung mit OpenMP.
|
|
160
|
-
"""
|
|
161
|
-
cdef int nFreqs = csm.shape[0]
|
|
162
|
-
cdef int nGridPoints = len(r0)
|
|
163
|
-
cdef int nMics = csm.shape[1]
|
|
164
|
-
|
|
165
|
-
cdef double[:,:] beamformOutput = np.zeros([nFreqs, nGridPoints], dtype=DTYPEReal)
|
|
166
|
-
|
|
167
|
-
cdef int cntFreqs, cntGrid, cntMics, cntMics2, cntMics1
|
|
168
|
-
cdef double r01, kjj, rm1, temp1, rs, temp3
|
|
169
|
-
cdef complex temp2, steerVec1, steerVec
|
|
170
|
-
# cdef float temp3
|
|
171
|
-
|
|
172
|
-
for cntFreqs in range(nFreqs):
|
|
173
|
-
kjj = kj[cntFreqs].imag
|
|
174
|
-
for cntGrid in prange(nGridPoints, nogil=True, schedule='static'): # Parallelisierung
|
|
175
|
-
r01 = r0[cntGrid]
|
|
176
|
-
rs = r01 ** 2
|
|
177
|
-
|
|
178
|
-
# Im ursprünglichen Code wurde hier erstmal in einer Schleife
|
|
179
|
-
# ueber die Mics der Steering-Vektor erstellt und später verarbeitet.
|
|
180
|
-
# Cython verhaut aber beim späteren Auslesen dieses Vektors, falls
|
|
181
|
-
# mit prange parallelisiert wird (siehe 2. im Kommentar ganz oben).
|
|
182
|
-
# Deshalb wurde hier der Code ein wenig geändert (Wirkung bleibt aber erhalten,
|
|
183
|
-
# allerdings werdfen redundante Operationen ausgeführt -->langsamer)
|
|
184
|
-
# Siehe Methode "beamformerCythonNOTparallel" für den ursprünglichen Code.
|
|
185
|
-
|
|
186
|
-
temp1 = 0.0
|
|
187
|
-
for cntMics in range(nMics):
|
|
188
|
-
temp2 = 0.0
|
|
189
|
-
rm1 = rm[cntGrid, cntMics]
|
|
190
|
-
temp3 = (kjj * (rm1 - r01))
|
|
191
|
-
steerVec = (c_cos(temp3) - 1j * c_sin(temp3)) * rm1
|
|
192
|
-
|
|
193
|
-
for cntMics2 in range(cntMics):
|
|
194
|
-
rm1 = rm[cntGrid, cntMics2]
|
|
195
|
-
temp3 = (kjj * (rm1 - r01))
|
|
196
|
-
steerVec1 = (c_cos(temp3) - 1j * c_sin(temp3)) * rm1
|
|
197
|
-
temp2 = temp2 + csm[cntFreqs, cntMics2, cntMics] * steerVec1
|
|
198
|
-
temp1 = temp1 + 2 * (temp2 * steerVec.conjugate()).real
|
|
199
|
-
temp1 = temp1 + (csm[cntFreqs, cntMics, cntMics] * steerVec.conjugate() * steerVec).real
|
|
200
|
-
beamformOutput[cntFreqs, cntGrid] = (temp1 / rs) # Hier gibt es keine Schwierigkeiten bzgl des Stichpkts 2. von oben. Nur falls "beamformOutput" nochmal in derselben Methode ausgelesen werden sollte.
|
|
201
|
-
return beamformOutput
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
#==============================================================================
|
|
205
|
-
# BSP, FÜR DIE DIE PARALLELISIERUNG MIT PRANGE LAUFZEITVERBESSERUNGEN BRINGT:
|
|
206
|
-
#---------------------------------------------------------------------------
|
|
207
|
-
#
|
|
208
|
-
# Die nachfolgenden 2 Fkt. machen das gleiche. Allerdings ist "c_arrayOpenMP" mit 'prange' parallelisiert.
|
|
209
|
-
# Macht man von ausserhalb einen Laufzeitvergleich, ist zu erkennen, dass das
|
|
210
|
-
# Parallelisieren hier tatsächlich was bringt (bei mir ungefähr 2x schneller).
|
|
211
|
-
@boundscheck(False)
|
|
212
|
-
@wraparound(False)
|
|
213
|
-
@nonecheck(False)
|
|
214
|
-
def c_array(double[:] X):
|
|
215
|
-
cdef int N = X.shape[0]
|
|
216
|
-
cdef double[:] Y = np.zeros(N)
|
|
217
|
-
cdef int i
|
|
218
|
-
for i in range(N): # NICHT parallelisiert
|
|
219
|
-
if X[i] > 0.5:
|
|
220
|
-
Y[i] = c_exp(X[i])
|
|
221
|
-
else:
|
|
222
|
-
Y[i] = 0
|
|
223
|
-
return Y
|
|
224
|
-
|
|
225
|
-
@boundscheck(False)
|
|
226
|
-
@wraparound(False)
|
|
227
|
-
@nonecheck(False)
|
|
228
|
-
def c_arrayOpenMP(double[:] X):
|
|
229
|
-
cdef int N = X.shape[0]
|
|
230
|
-
cdef double[:] Y = np.zeros(N)
|
|
231
|
-
cdef int i
|
|
232
|
-
for i in prange(N, nogil=True): # parallelisiert
|
|
233
|
-
if X[i] > 0.5:
|
|
234
|
-
Y[i] = c_exp(X[i])
|
|
235
|
-
else:
|
|
236
|
-
Y[i] = 0
|
|
237
|
-
return Y
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python2
|
|
2
|
-
# -*- coding: utf-8 -*-
|
|
3
|
-
"""
|
|
4
|
-
Created on Thu Jul 6 16:16:03 2017
|
|
5
|
-
|
|
6
|
-
@author: tomgensch
|
|
7
|
-
"""
|
|
8
|
-
#import os
|
|
9
|
-
#print(os.path.dirname(os.path.realpath(__file__)))
|
|
10
|
-
|
|
11
|
-
import numpy as np
|
|
12
|
-
from cythonBeamformer import beamformerCython, beamformerCythonNOTparallel
|
|
13
|
-
|
|
14
|
-
nMics = 32
|
|
15
|
-
nGridPoints = 100
|
|
16
|
-
nFreqs = 10
|
|
17
|
-
|
|
18
|
-
csm = np.random.rand(nFreqs, nMics, nMics) + 1j*np.random.rand(nFreqs, nMics, nMics)
|
|
19
|
-
for cntFreqs in range(nFreqs):
|
|
20
|
-
csm[cntFreqs, :, :] += csm[cntFreqs, :, :].T.conj() # zu Hermitischer Matrix machen
|
|
21
|
-
r0 = np.random.rand(nGridPoints) #abstand aufpunkte-arraymittelpunkt
|
|
22
|
-
rm = np.random.rand(nGridPoints, nMics) #abstand aufpunkte-arraymikrofone
|
|
23
|
-
kj = np.zeros(nFreqs) + 1j*np.random.rand(nFreqs) #
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
#csm = np.ones((nFreqs, nMics, nMics), 'D')
|
|
27
|
-
#r0 = np.ones(nGridPoints) * .2
|
|
28
|
-
#rm = np.array([[.2, .3]])#rm = np.ones((nGridPoints, nMics)) * .24
|
|
29
|
-
#kj = np.zeros(nFreqs) + 1j
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
print('Sequentiel')
|
|
33
|
-
outputWithoutMP = beamformerCythonNOTparallel(csm, r0, rm, kj)
|
|
34
|
-
|
|
35
|
-
print('Parallel')
|
|
36
|
-
outputMP = beamformerCython(csm, r0, rm, kj)
|
|
37
|
-
|
|
38
|
-
outputMit = np.array(outputMP)
|
|
39
|
-
outputOhne = np.array(outputWithoutMP)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
#==============================================================================
|
|
45
|
-
# Bei Intel gibt es mit dem setuo-file aus der Doku keine probleme.
|
|
46
|
-
# Die differenz zwischen den methoden und der referenz ist dann 0 (also wirklich 0, nicht e-12)
|
|
47
|
-
# Allerdings ist parallel viel lamngsamer!
|
|
48
|
-
#==============================================================================
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
#e1Mit = np.array(e1MP)
|
|
55
|
-
#e1Ohne = np.array(e1OhneMP)
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
## Referenz
|
|
59
|
-
beamformOutput = np.zeros((nFreqs, nGridPoints), np.float64)
|
|
60
|
-
e1 = np.zeros((nMics), np.complex128)
|
|
61
|
-
|
|
62
|
-
for cntFreqs in xrange(nFreqs): # laeuft z.Z. nur einmal durch
|
|
63
|
-
kjj = kj[cntFreqs].imag ### könnte man vielleicht reinnehmen um unten nicht immer den realteilnehmen zu müssen
|
|
64
|
-
for cntGrid in xrange(nGridPoints):
|
|
65
|
-
rs = 0
|
|
66
|
-
r01 = r0[cntGrid]
|
|
67
|
-
|
|
68
|
-
# Erzeugen der Steering-Vectoren
|
|
69
|
-
for cntMics in xrange(nMics):
|
|
70
|
-
rm1 = rm[cntGrid, cntMics]
|
|
71
|
-
rs += 1.0 / (rm1**2)
|
|
72
|
-
temp3 = (kjj * (rm1 - r01)) # der Float bewirkt die Abweichung vom Originalergebnis um ca 10^-8
|
|
73
|
-
e1[cntMics] = (np.cos(temp3) - 1j * np.sin(temp3)) * rm1
|
|
74
|
-
rs = r01 ** 2
|
|
75
|
-
|
|
76
|
-
# Berechnen der Matrix multiplikation
|
|
77
|
-
temp1 = 0.0
|
|
78
|
-
for cntMics in xrange(nMics):
|
|
79
|
-
temp2 = 0.0
|
|
80
|
-
for cntMics2 in xrange(cntMics):
|
|
81
|
-
temp2 += csm[cntFreqs, cntMics2, cntMics] * e1[cntMics2] # nicht ganz sicher ob richtig
|
|
82
|
-
temp1 += 2 * (temp2 * e1[cntMics].conjugate()).real
|
|
83
|
-
temp1 += (csm[cntFreqs, cntMics, cntMics] * np.conjugate(e1[cntMics]) * e1[cntMics]).real
|
|
84
|
-
|
|
85
|
-
beamformOutput[cntFreqs, cntGrid] = (temp1 / rs).real
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
#diffE1MitOpenMP = max(abs(e1 - e1Mit))
|
|
89
|
-
#diffE1OhneOpenMP = max(abs(e1 - e1Ohne))
|
|
90
|
-
##diffE1BothCythonMethods = max([abs(e1Mit[cnt] - e1Ohne[cnt]) for cnt in range(len(e1Ohne))])
|
|
91
|
-
#diffE1BothCythonMethods = np.amax(abs(e1Mit - e1Ohne), axis=0)
|
|
92
|
-
#diffE1BothCythonMethods = np.amax(diffE1BothCythonMethods, axis=0)
|
|
93
|
-
|
|
94
|
-
diffOutputBothMethods = np.amax(abs(outputMit - outputOhne), axis=0)
|
|
95
|
-
diffOutputBothMethods = np.amax(abs(diffOutputBothMethods), axis=0)
|
|
96
|
-
|
|
97
|
-
diffOutputOpenMP = np.amax(abs(outputMit - beamformOutput), axis=0)
|
|
98
|
-
diffOutputOpenMP = np.amax(abs(diffOutputOpenMP), axis=0)
|
|
99
|
-
|
|
100
|
-
diffOutputWithoutOpenMP = np.amax(abs(outputOhne - beamformOutput), axis=0)
|
|
101
|
-
diffOutputWithoutOpenMP = np.amax(abs(diffOutputWithoutOpenMP), axis=0)
|
|
102
|
-
|
|
103
|
-
print(diffOutputBothMethods)
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python2
|
|
2
|
-
# -*- coding: utf-8 -*-
|
|
3
|
-
"""
|
|
4
|
-
Created on Thu Jul 20 14:06:46 2017
|
|
5
|
-
|
|
6
|
-
@author: tomgensch
|
|
7
|
-
|
|
8
|
-
This script was for getting to know the mechanisms of the new prange function
|
|
9
|
-
of jit (numba version 0.34). As it turns out the automatic parallelization is
|
|
10
|
-
as faulty as in cython (same errors).
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
import numpy as np
|
|
14
|
-
from numba import njit, float64, complex128, prange
|
|
15
|
-
|
|
16
|
-
nMics = 4
|
|
17
|
-
nGridPoints = 5
|
|
18
|
-
nFreqs = 1
|
|
19
|
-
|
|
20
|
-
csm = np.random.rand(nFreqs, nMics, nMics) + 1j*np.random.rand(nFreqs, nMics, nMics)
|
|
21
|
-
for cntFreqs in range(nFreqs):
|
|
22
|
-
csm[cntFreqs, :, :] += csm[cntFreqs, :, :].T.conj() # zu Hermitischer Matrix machen
|
|
23
|
-
r0 = np.random.rand(nGridPoints) #abstand aufpunkte-arraymittelpunkt
|
|
24
|
-
rm = np.random.rand(nGridPoints, nMics) #abstand aufpunkte-arraymikrofone
|
|
25
|
-
kj = np.zeros(nFreqs) + 1j*np.random.rand(nFreqs)
|
|
26
|
-
|
|
27
|
-
@njit(float64[:,:](complex128[:,:,:], float64[:], float64[:,:], complex128[:]), parallel=True)
|
|
28
|
-
def loops_NumbaJit_parallelSlow(csm, r0, rm, kj):
|
|
29
|
-
nFreqs = csm.shape[0]
|
|
30
|
-
nGridPoints = len(r0)
|
|
31
|
-
nMics = csm.shape[1]
|
|
32
|
-
beamformOutput = np.zeros((nFreqs, nGridPoints), np.float64)
|
|
33
|
-
|
|
34
|
-
for cntFreqs in xrange(nFreqs):
|
|
35
|
-
kjj = kj[cntFreqs].imag
|
|
36
|
-
for cntGrid in prange(nGridPoints):
|
|
37
|
-
r01 = r0[cntGrid]
|
|
38
|
-
rs = r01 ** 2
|
|
39
|
-
|
|
40
|
-
temp1 = 0.0
|
|
41
|
-
for cntMics in xrange(nMics):
|
|
42
|
-
temp2 = 0.0
|
|
43
|
-
rm1 = rm[cntGrid, cntMics]
|
|
44
|
-
temp3 = np.float32(kjj * (rm1 - r01))
|
|
45
|
-
steerVec = (np.cos(temp3) - 1j * np.sin(temp3)) * rm1
|
|
46
|
-
|
|
47
|
-
for cntMics2 in xrange(cntMics):
|
|
48
|
-
rm1 = rm[cntGrid, cntMics2]
|
|
49
|
-
temp3 = np.float32(kjj * (rm1 - r01))
|
|
50
|
-
steerVec1 = (np.cos(temp3) - 1j * np.sin(temp3)) * rm1
|
|
51
|
-
temp2 += csm[cntFreqs, cntMics2, cntMics] * steerVec1
|
|
52
|
-
temp1 += 2 * (temp2 * steerVec.conjugate()).real
|
|
53
|
-
temp1 += (csm[cntFreqs, cntMics, cntMics] * steerVec.conjugate() * steerVec).real
|
|
54
|
-
|
|
55
|
-
beamformOutput[cntFreqs, cntGrid] = (temp1 / rs).real
|
|
56
|
-
return beamformOutput
|
|
57
|
-
|
|
58
|
-
@njit(float64[:,:](complex128[:,:,:], float64[:], float64[:,:], complex128[:]), parallel=True)
|
|
59
|
-
def loops_NumbaJit_parallelFast(csm, r0, rm, kj):
|
|
60
|
-
""" This method implements the prange over the Gridpoints, which is a direct
|
|
61
|
-
implementation of the currently used c++ methods created with scipy.wave.
|
|
62
|
-
|
|
63
|
-
Very strange: Just like with Cython, this implementation (prange over Gridpoints)
|
|
64
|
-
produces wrong results. If one doesn't parallelize -> everything is good
|
|
65
|
-
(just like with Cython). Maybe Cython and Numba.jit use the same interpreter
|
|
66
|
-
to generate OpenMP-parallelizable code.
|
|
67
|
-
|
|
68
|
-
BUT: If one uncomments the 'steerVec' declaration in the prange-loop over the
|
|
69
|
-
gridpoints an error occurs. After commenting the line again and executing
|
|
70
|
-
the script once more, THE BEAMFORMER-RESULTS ARE CORRECT (for repeated tries).
|
|
71
|
-
Funny enough the method is now twice as slow in comparison to the
|
|
72
|
-
'wrong version' (before invoking the error).
|
|
73
|
-
"""
|
|
74
|
-
# init
|
|
75
|
-
nFreqs = csm.shape[0]
|
|
76
|
-
nGridPoints = len(r0)
|
|
77
|
-
nMics = csm.shape[1]
|
|
78
|
-
beamformOutput = np.zeros((nFreqs, nGridPoints), np.float64)
|
|
79
|
-
steerVec = np.zeros((nMics), np.complex128)
|
|
80
|
-
|
|
81
|
-
for cntFreqs in xrange(nFreqs):
|
|
82
|
-
kjj = kj[cntFreqs].imag
|
|
83
|
-
for cntGrid in prange(nGridPoints):
|
|
84
|
-
# steerVec = np.zeros((nMics), np.complex128) # This is the line that has to be uncommented (see this methods documentation comment)
|
|
85
|
-
rs = 0
|
|
86
|
-
r01 = r0[cntGrid]
|
|
87
|
-
|
|
88
|
-
for cntMics in xrange(nMics):
|
|
89
|
-
rm1 = rm[cntGrid, cntMics]
|
|
90
|
-
rs += 1.0 / (rm1**2)
|
|
91
|
-
temp3 = np.float32(kjj * (rm1 - r01))
|
|
92
|
-
steerVec[cntMics] = (np.cos(temp3) - 1j * np.sin(temp3)) * rm1
|
|
93
|
-
rs = r01 ** 2
|
|
94
|
-
|
|
95
|
-
temp1 = 0.0
|
|
96
|
-
for cntMics in xrange(nMics):
|
|
97
|
-
temp2 = 0.0
|
|
98
|
-
for cntMics2 in xrange(cntMics):
|
|
99
|
-
temp2 = temp2 + csm[cntFreqs, cntMics2, cntMics] * steerVec[cntMics2]
|
|
100
|
-
temp1 = temp1 + 2 * (temp2 * steerVec[cntMics].conjugate()).real
|
|
101
|
-
temp1 = temp1 + (csm[cntFreqs, cntMics, cntMics] * np.conjugate(steerVec[cntMics]) * steerVec[cntMics]).real
|
|
102
|
-
|
|
103
|
-
beamformOutput[cntFreqs, cntGrid] = (temp1 / rs).real
|
|
104
|
-
return beamformOutput
|
|
105
|
-
|
|
106
|
-
beamformOutputFast = loops_NumbaJit_parallelFast(csm, r0, rm, kj)
|
|
107
|
-
beamformOutputSlow = loops_NumbaJit_parallelSlow(csm, r0, rm, kj)
|
|
108
|
-
|
|
109
|
-
#%% Referenz
|
|
110
|
-
beamformOutputRef = np.zeros((nFreqs, nGridPoints), np.float64)
|
|
111
|
-
e1 = np.zeros((nMics), np.complex128)
|
|
112
|
-
|
|
113
|
-
for cntFreqs in xrange(nFreqs):
|
|
114
|
-
kjj = kj[cntFreqs].imag
|
|
115
|
-
for cntGrid in xrange(nGridPoints):
|
|
116
|
-
rs = 0
|
|
117
|
-
r01 = r0[cntGrid]
|
|
118
|
-
|
|
119
|
-
for cntMics in xrange(nMics):
|
|
120
|
-
rm1 = rm[cntGrid, cntMics]
|
|
121
|
-
rs += 1.0 / (rm1**2)
|
|
122
|
-
temp3 = np.float32(kjj * (rm1 - r01))
|
|
123
|
-
e1[cntMics] = (np.cos(temp3) - 1j * np.sin(temp3)) * rm1
|
|
124
|
-
rs = r01 ** 2
|
|
125
|
-
|
|
126
|
-
temp1 = 0.0
|
|
127
|
-
for cntMics in xrange(nMics):
|
|
128
|
-
temp2 = 0.0
|
|
129
|
-
for cntMics2 in xrange(cntMics):
|
|
130
|
-
temp2 += csm[cntFreqs, cntMics2, cntMics] * e1[cntMics2]
|
|
131
|
-
temp1 += 2 * (temp2 * e1[cntMics].conjugate()).real
|
|
132
|
-
temp1 += (csm[cntFreqs, cntMics, cntMics] * np.conjugate(e1[cntMics]) * e1[cntMics]).real
|
|
133
|
-
|
|
134
|
-
beamformOutputRef[cntFreqs, cntGrid] = (temp1 / rs).real
|
|
135
|
-
|
|
136
|
-
diffFast = np.amax(abs(beamformOutputFast - beamformOutputRef), axis=0)
|
|
137
|
-
diffFast= np.amax(abs(diffFast), axis=0)
|
|
138
|
-
|
|
139
|
-
diffSlow = np.amax(abs(beamformOutputSlow - beamformOutputRef), axis=0)
|
|
140
|
-
diffSlow= np.amax(abs(diffSlow), axis=0)
|
|
141
|
-
|
|
142
|
-
print(diffFast)
|
|
143
|
-
print(diffSlow)
|