9
9
from .cal_params import get_cal_params_EK
10
10
from .calibrate_base import CalibrateBase
11
11
from .ek80_complex import compress_pulse , get_filter_coeff , get_tau_effective , get_transmit_signal
12
- from .env_params import get_env_params_EK60 , get_env_params_EK80
12
+ from .env_params import get_env_params_EK
13
13
from .range import compute_range_EK , range_mod_TVG_EK
14
14
15
15
logger = _init_logger (__name__ )
@@ -19,6 +19,8 @@ class CalibrateEK(CalibrateBase):
19
19
def __init__ (self , echodata : EchoData , env_params , cal_params ):
20
20
super ().__init__ (echodata , env_params , cal_params )
21
21
22
+ self .ed_beam_group = None # will be assigned in child class
23
+
22
24
def compute_echo_range (self , chan_sel : xr .DataArray = None ):
23
25
"""
24
26
Compute echo range for EK echosounders.
@@ -36,24 +38,22 @@ def compute_echo_range(self, chan_sel: xr.DataArray = None):
36
38
chan_sel = chan_sel ,
37
39
)
38
40
39
- def _cal_power_samples (self , cal_type : str , power_ed_group : str = None ) -> xr .Dataset :
41
+ def _cal_power_samples (self , cal_type : str ) -> xr .Dataset :
40
42
"""Calibrate power data from EK60 and EK80.
41
43
42
44
Parameters
43
45
----------
44
46
cal_type: str
45
47
'Sv' for calculating volume backscattering strength, or
46
48
'TS' for calculating target strength
47
- power_ed_group:
48
- The ``EchoData`` beam group path containing the power data
49
49
50
50
Returns
51
51
-------
52
52
xr.Dataset
53
53
The calibrated dataset containing Sv or TS
54
54
"""
55
55
# Select source of backscatter data
56
- beam = self .echodata [power_ed_group ]
56
+ beam = self .echodata [self . ed_beam_group ]
57
57
58
58
# Derived params
59
59
wavelength = self .env_params ["sound_speed" ] / beam ["frequency_nominal" ] # wavelength
@@ -63,7 +63,7 @@ def _cal_power_samples(self, cal_type: str, power_ed_group: str = None) -> xr.Da
63
63
sound_speed = self .env_params ["sound_speed" ]
64
64
absorption = self .env_params ["sound_absorption" ]
65
65
tvg_mod_range = range_mod_TVG_EK (
66
- self .echodata , self .ed_group , self .range_meter , sound_speed
66
+ self .echodata , self .ed_beam_group , self .range_meter , sound_speed
67
67
)
68
68
tvg_mod_range = tvg_mod_range .where (tvg_mod_range > 0 , np .nan )
69
69
@@ -130,26 +130,31 @@ class CalibrateEK60(CalibrateEK):
130
130
def __init__ (self , echodata , env_params , cal_params , ** kwargs ):
131
131
super ().__init__ (echodata , env_params , cal_params )
132
132
133
- # Set sonar_type
133
+ # Set sonar_type and waveform/encode mode
134
134
self .sonar_type = "EK60"
135
-
136
- # Get env_params
137
- self .env_params = get_env_params_EK60 (echodata = echodata , user_env_dict = self .env_params )
138
135
self .waveform_mode = "CW"
139
136
self .encode_mode = "power"
140
137
141
- # Compute range
142
- self .compute_echo_range ()
143
-
144
- # Get the right ed_group for CW power samples
145
- self .ed_group = retrieve_correct_beam_group (
138
+ # Get the right ed_beam_group for CW power samples
139
+ self .ed_beam_group = retrieve_correct_beam_group (
146
140
echodata = self .echodata , waveform_mode = self .waveform_mode , encode_mode = self .encode_mode
147
141
)
148
142
143
+ # Get env_params
144
+ self .env_params = get_env_params_EK (
145
+ sonar_type = self .sonar_type ,
146
+ beam = self .echodata [self .ed_beam_group ],
147
+ env = self .echodata ["Environment" ],
148
+ user_dict = self .env_params ,
149
+ )
150
+
151
+ # Compute range
152
+ self .compute_echo_range ()
153
+
149
154
# Set the channels to calibrate
150
155
# For EK60 this is all channels
151
- self .chan_sel = self .echodata [self .ed_group ]["channel" ]
152
- beam = self .echodata [self .ed_group ]
156
+ self .chan_sel = self .echodata [self .ed_beam_group ]["channel" ]
157
+ beam = self .echodata [self .ed_beam_group ]
153
158
154
159
# Get cal_params
155
160
self .cal_params = get_cal_params_EK (
@@ -162,10 +167,10 @@ def __init__(self, echodata, env_params, cal_params, **kwargs):
162
167
)
163
168
164
169
def compute_Sv (self , ** kwargs ):
165
- return self ._cal_power_samples (cal_type = "Sv" , power_ed_group = self . ed_group )
170
+ return self ._cal_power_samples (cal_type = "Sv" )
166
171
167
172
def compute_TS (self , ** kwargs ):
168
- return self ._cal_power_samples (cal_type = "TS" , power_ed_group = self . ed_group )
173
+ return self ._cal_power_samples (cal_type = "TS" )
169
174
170
175
171
176
class CalibrateEK80 (CalibrateEK ):
@@ -197,23 +202,23 @@ def __init__(self, echodata, env_params, cal_params, waveform_mode, encode_mode)
197
202
self .encode_mode = encode_mode
198
203
self .echodata = echodata
199
204
200
- # Get the right ed_group given waveform and encode mode
201
- self .ed_group = retrieve_correct_beam_group (
205
+ # Get the right ed_beam_group given waveform and encode mode
206
+ self .ed_beam_group = retrieve_correct_beam_group (
202
207
echodata = self .echodata , waveform_mode = self .waveform_mode , encode_mode = self .encode_mode
203
208
)
204
209
205
210
# Select the channels to calibrate
206
211
if self .encode_mode == "power" :
207
212
# Power sample only possible under CW mode,
208
213
# and all power samples will live in the same group
209
- self .chan_sel = self .echodata [self .ed_group ]["channel" ]
214
+ self .chan_sel = self .echodata [self .ed_beam_group ]["channel" ]
210
215
else :
211
216
# Complex samples can be CW or BB, so select based on waveform mode
212
- chan_dict = self ._get_chan_dict (self .echodata [self .ed_group ])
217
+ chan_dict = self ._get_chan_dict (self .echodata [self .ed_beam_group ])
213
218
self .chan_sel = chan_dict [self .waveform_mode ]
214
219
215
220
# Subset of the right Sonar/Beam_groupX group given the selected channels
216
- beam = self .echodata [self .ed_group ].sel (channel = self .chan_sel )
221
+ beam = self .echodata [self .ed_beam_group ].sel (channel = self .chan_sel )
217
222
218
223
# Use center frequency if in BB mode, else use nominal channel frequency
219
224
if self .waveform_mode == "BB" :
@@ -226,11 +231,12 @@ def __init__(self, echodata, env_params, cal_params, waveform_mode, encode_mode)
226
231
self .freq_center = beam ["frequency_nominal" ].sel (channel = self .chan_sel )
227
232
228
233
# Get env_params: depends on waveform mode
229
- self .env_params = get_env_params_EK80 (
230
- echodata = echodata ,
234
+ self .env_params = get_env_params_EK (
235
+ sonar_type = self .sonar_type ,
236
+ beam = beam ,
237
+ env = self .echodata ["Environment" ],
238
+ user_dict = self .env_params ,
231
239
freq = self .freq_center ,
232
- user_env_dict = env_params ,
233
- ed_group = self .ed_group ,
234
240
)
235
241
236
242
# Get cal_params: depends on waveform and encode mode
@@ -333,24 +339,22 @@ def _get_B_theta_phi_m(self):
333
339
334
340
return B_theta_phi_m
335
341
336
- def _cal_complex_samples (self , cal_type : str , complex_ed_group : str ) -> xr .Dataset :
342
+ def _cal_complex_samples (self , cal_type : str ) -> xr .Dataset :
337
343
"""Calibrate complex data from EK80.
338
344
339
345
Parameters
340
346
----------
341
347
cal_type : str
342
348
'Sv' for calculating volume backscattering strength, or
343
349
'TS' for calculating target strength
344
- complex_ed_group : str
345
- The ``EchoData`` beam group path containing complex data
346
350
347
351
Returns
348
352
-------
349
353
xr.Dataset
350
354
The calibrated dataset containing Sv or TS
351
355
"""
352
356
# Select source of backscatter data
353
- beam = self .echodata [complex_ed_group ].sel (channel = self .chan_sel )
357
+ beam = self .echodata [self . ed_beam_group ].sel (channel = self .chan_sel )
354
358
vend = self .echodata ["Vendor_specific" ].sel (channel = self .chan_sel )
355
359
356
360
# Get transmit signal
@@ -376,7 +380,9 @@ def _cal_complex_samples(self, cal_type: str, complex_ed_group: str) -> xr.Datas
376
380
transmit_power = beam ["transmit_power" ]
377
381
378
382
# TVG compensation with modified range
379
- tvg_mod_range = range_mod_TVG_EK (self .echodata , self .ed_group , range_meter , sound_speed )
383
+ tvg_mod_range = range_mod_TVG_EK (
384
+ self .echodata , self .ed_beam_group , range_meter , sound_speed
385
+ )
380
386
tvg_mod_range = tvg_mod_range .where (tvg_mod_range > 0 , np .nan )
381
387
382
388
spreading_loss = 20 * np .log10 (tvg_mod_range )
@@ -476,10 +482,10 @@ def _compute_cal(self, cal_type) -> xr.Dataset:
476
482
477
483
if flag_complex :
478
484
# Complex samples can be BB or CW
479
- ds_cal = self ._cal_complex_samples (cal_type = cal_type , complex_ed_group = self . ed_group )
485
+ ds_cal = self ._cal_complex_samples (cal_type = cal_type )
480
486
else :
481
487
# Power samples only make sense for CW mode data
482
- ds_cal = self ._cal_power_samples (cal_type = cal_type , power_ed_group = self . ed_group )
488
+ ds_cal = self ._cal_power_samples (cal_type = cal_type )
483
489
484
490
return ds_cal
485
491
0 commit comments