Skip to content

Commit

Permalink
refactored the parse_azfp code and added new tests
Browse files Browse the repository at this point in the history
  • Loading branch information
praneethratna committed Sep 18, 2023
1 parent 558f3b9 commit 54e1068
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 38 deletions.
20 changes: 13 additions & 7 deletions echopype/convert/parse_azfp.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,10 @@ def load_AZFP_xml(self):
root = ET.parse(xmlmap.fs.open(xmlmap.root)).getroot()

for child in root.iter():
camel_case_tag = self._to_camelCase(child.tag)
if len(child.attrib) > 0:
for key, val in child.attrib.items():
self.parameters[child.tag + key].append(val)
self.parameters[camel_case_tag + "_" + self._to_camelCase(key)].append(val)

if all(char == "\n" for char in child.text):
continue
Expand All @@ -107,12 +108,7 @@ def load_AZFP_xml(self):
val = float(child.text)

if len(child.tag) > 3 and not child.tag.startswith("VTX"):
words = re.findall("[A-Z]+[a-z]*", child.tag)
words_lower = [word.lower() for word in words]
if len(words) > 1:
self.parameters["_".join(words_lower)].append(val)
elif len(words) == 1:
self.parameters[words_lower[0]].append(val)
self.parameters[camel_case_tag].append(val)
else:
self.parameters[child.tag].append(val)

Expand All @@ -121,6 +117,16 @@ def load_AZFP_xml(self):
if len(val) == 1:
self.parameters[key] = val[0]

def _to_camelCase(self, tag):
words = re.findall("[A-Z]+[a-z]*", tag)
words_lower = [word.lower() for word in words]
if len(words) > 1:
return "_".join(words_lower)
elif len(words) == 1:
return words_lower[0]
else:
return tag

def _compute_temperature(self, ping_num, is_valid):
"""
Compute temperature in celsius.
Expand Down
58 changes: 49 additions & 9 deletions echopype/convert/set_groups_azfp.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def _create_unique_channel_name(self):
"""

serial_number = self.parser_obj.unpacked_data["serial_number"]
frequency_number = self.parser_obj.parameters["FrequencyNumber"]
frequency_number = self.parser_obj.parameters["frequency_number"]

if serial_number.size == 1:
freq_as_str = self.freq_sorted.astype(int).astype(str)
Expand Down Expand Up @@ -488,6 +488,16 @@ def set_vendor(self) -> xr.Dataset:
"phase": unpacked_data["phase"],
"number_of_channels": unpacked_data["num_chan"],
# parameters with channel dimension from XML file
"XML_transmit_duration_nominal": (
["channel"],
tdn,
{"long_name": "(From XML file) Nominal bandwidth of transmitted pulse"},
), # tdn comes from parameters
"XML_gain_correction": (
["channel"],
parameters["gain"][self.freq_ind_sorted],
{"long_name": "(From XML file) Gain correction"},
),
"instrument_type": parameters["instrument_type"][0],
"minor": parameters["minor"],
"major": parameters["major"],
Expand All @@ -499,23 +509,53 @@ def set_vendor(self) -> xr.Dataset:
"file_version": parameters["file_version"],
"parameter_version": parameters["parameter_version"],
"configuration_version": parameters["configuration_version"],
"XML_transmit_duration_nominal": (["channel"], tdn), # tdn comes from parameters
"XML_gain_correction": (["channel"], parameters["gain"][self.freq_ind_sorted]),
"XML_digitization_rate": (
["channel"],
parameters["dig_rate"][self.freq_ind_sorted],
),
"XML_lockout_index": (
["channel"],
parameters["lock_out_index"][self.freq_ind_sorted],
{
"long_name": "(From XML file) The distance, rounded to the nearest "
"Bin Size after the pulse is transmitted that over which AZFP will "
"ignore echoes"
},
),
"DS": (["channel"], parameters["DS"][self.freq_ind_sorted]),
"EL": (["channel"], parameters["EL"][self.freq_ind_sorted]),
"TVR": (["channel"], parameters["TVR"][self.freq_ind_sorted]),
"VTX0": (["channel"], parameters["VTX0"][self.freq_ind_sorted]),
"VTX1": (["channel"], parameters["VTX1"][self.freq_ind_sorted]),
"VTX2": (["channel"], parameters["VTX2"][self.freq_ind_sorted]),
"VTX3": (["channel"], parameters["VTX3"][self.freq_ind_sorted]),
"EL": (
["channel"],
parameters["EL"][self.freq_ind_sorted],
{"long_name": "Sound pressure at the transducer", "units": "dB"},
),
"TVR": (
["channel"],
parameters["TVR"][self.freq_ind_sorted],
{
"long_name": "Transmit voltage response of the transducer",
"units": "dB re 1uPa/V at 1m",
},
),
"VTX0": (
["channel"],
parameters["VTX0"][self.freq_ind_sorted],
{"long_name": "Amplified voltage 0 sent to the transducer"},
),
"VTX1": (
["channel"],
parameters["VTX1"][self.freq_ind_sorted],
{"long_name": "Amplified voltage 1 sent to the transducer"},
),
"VTX2": (
["channel"],
parameters["VTX2"][self.freq_ind_sorted],
{"long_name": "Amplified voltage 2 sent to the transducer"},
),
"VTX3": (
["channel"],
parameters["VTX3"][self.freq_ind_sorted],
{"long_name": "Amplified voltage 3 sent to the transducer"},
),
"Sv_offset": (["channel"], Sv_offset),
"number_of_samples_digitized_per_pings": (
["channel"],
Expand Down
61 changes: 39 additions & 22 deletions echopype/tests/convert/test_convert_azfp.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,30 +182,47 @@ def test_load_parse_azfp_xml(azfp_path):
azfp_xml_path = azfp_path / '17030815.XML'
parseAZFP = ParseAZFP(str(azfp_01a_path), str(azfp_xml_path))
parseAZFP.load_AZFP_xml()
expected_params = ['InstrumentTypestring', 'instrument_type', 'major', 'minor', 'date',
'Programname', 'program', 'CPU', 'serial_number', 'board_version',
expected_params = ['instrument_type_string', 'instrument_type', 'major', 'minor', 'date',
'program_name', 'program', 'CPU', 'serial_number', 'board_version',
'file_version', 'parameter_version', 'configuration_version', 'eclock',
'digital_board_version', 'SensorsFlagPressureSensorInstalled',
'SensorsFlagParosInstalled', 'sensors_flag', 'U0', 'Y1', 'Y2', 'Y3', 'C1',
'C2', 'C3', 'D1', 'D2', 'T1', 'T2', 'T3', 'T4', 'T5', 'X_a', 'X_b', 'X_c',
'X_d', 'Y_a', 'Y_b', 'Y_c', 'Y_d', 'period', 'ppm_offset', 'calibration',
'a0', 'a1', 'a2', 'a3', 'ka', 'kb', 'kc', 'A', 'B', 'C', 'num_freq',
'kHzunits', 'kHz', 'TVR', 'num_vtx', 'VTX0', 'VTX1', 'VTX2', 'VTX3', 'BP',
'EL', 'DS', 'min_pulse_len', 'sound_speed', 'StartDatesvalue', 'start_date',
'num_frequencies', 'num_phases', 'DataOutputsvalue', 'data_output',
'Frequencyunits', 'frequency', 'PhaseNumber', 'PhaseTypesvalue', 'phase_type',
'Durationsvalue', 'duration', 'PingPeriodunits', 'ping_period',
'BurstIntervalunits', 'burst_interval', 'PingsPerBurstunits',
'pings_per_burst', 'AverageBurstPingsunits', 'average_burst_pings',
'FrequencyNumber', 'AcquireFrequencyunits', 'acquire_frequency',
'PulseLenunits', 'pulse_len', 'DigRateunits', 'dig_rate', 'RangeSamplesunits',
'range_samples', 'RangeAveragingSamplesunits', 'range_averaging_samples',
'LockOutIndexunits', 'lock_out_index', 'Gainunits', 'gain',
'StorageFormatunits', 'storage_format']

'digital_board_version', 'sensors_flag_pressure_sensor_installed',
'sensors_flag_paros_installed', 'sensors_flag', 'U0', 'Y1', 'Y2', 'Y3',
'C1', 'C2', 'C3', 'D1', 'D2', 'T1', 'T2', 'T3', 'T4', 'T5', 'X_a', 'X_b',
'X_c', 'X_d', 'Y_a', 'Y_b', 'Y_c', 'Y_d', 'period', 'ppm_offset',
'calibration', 'a0', 'a1', 'a2', 'a3', 'ka', 'kb', 'kc', 'A', 'B', 'C',
'num_freq', 'hz_units', 'kHz', 'TVR', 'num_vtx', 'VTX0', 'VTX1', 'VTX2',
'VTX3', 'BP', 'EL', 'DS', 'min_pulse_len', 'sound_speed',
'start_date_svalue', 'start_date', 'num_frequencies', 'num_phases',
'data_output_svalue', 'data_output', 'frequency_units', 'frequency',
'phase_number', 'phase_type_svalue', 'phase_type', 'duration_svalue',
'duration', 'ping_period_units', 'ping_period', 'burst_interval_units',
'burst_interval', 'pings_per_burst_units', 'pings_per_burst',
'average_burst_pings_units', 'average_burst_pings', 'frequency_number',
'acquire_frequency_units', 'acquire_frequency', 'pulse_len_units',
'pulse_len', 'dig_rate_units', 'dig_rate', 'range_samples_units',
'range_samples', 'range_averaging_samples_units', 'range_averaging_samples',
'lock_out_index_units', 'lock_out_index', 'gain_units', 'gain',
'storage_format_units', 'storage_format']
assert set(parseAZFP.parameters.keys()) == set(expected_params)
assert list(set(parseAZFP.parameters['InstrumentTypestring']))[0] == 'AZFP'
assert list(set(parseAZFP.parameters['instrument_type_string']))[0] == 'AZFP'
assert isinstance(parseAZFP.parameters['num_freq'], int)
assert isinstance(parseAZFP.parameters['pulse_len'], list)
assert parseAZFP.parameters['num_freq'] == 4
assert parseAZFP.parameters['pulse_len'] == [300, 300, 300, 300]
expected_frequency_numbers = ['1', '2', '3', '4']
assert len(parseAZFP.parameters['frequency_number']) == 4
assert all(x == y for x, y in zip(parseAZFP.parameters['frequency_number'],
expected_frequency_numbers))
expected_len_params = ['acquire_frequency', 'pulse_len', 'dig_rate', 'range_samples',
'range_averaging_samples', 'lock_out_index', 'gain', 'storage_format']
assert all(len(parseAZFP.parameters[x]) == 4 for x in expected_len_params)
assert all(x == 1 for x in parseAZFP.parameters['acquire_frequency'])
assert all(x == 300 for x in parseAZFP.parameters['pulse_len'])
assert all(x == 20000 for x in parseAZFP.parameters['dig_rate'])
expected_range_samples = [1752, 1752, 1764, 540]
assert all(x == y for x, y in zip(parseAZFP.parameters['range_samples'],
expected_range_samples))
assert all(x == 4 for x in parseAZFP.parameters['range_averaging_samples'])
assert all(x == 0 for x in parseAZFP.parameters['lock_out_index'])
assert all(x == 1 for x in parseAZFP.parameters['gain'])
assert all(x == 1 for x in parseAZFP.parameters['storage_format'])

0 comments on commit 54e1068

Please sign in to comment.