Skip to content

Commit

Permalink
Reduce complexity and don't hardcode plotting units
Browse files Browse the repository at this point in the history
  • Loading branch information
jmcvey3 committed Oct 10, 2024
1 parent 378ea29 commit 22512f1
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 94 deletions.
45 changes: 18 additions & 27 deletions examples/acoustics_example.ipynb

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions mhkit/acoustics/graphics.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def plot_spectogram(spsdl, fmin=10, fmax=100000, fig=None, ax=None, **kwargs):
h = ax.pcolormesh(
spsdl[time].values, spsdl[freq].values, spsdl.T, shading="nearest", **kwargs
)
fig.colorbar(h, ax=ax, label="dB re 1 uPa^2/Hz")
fig.colorbar(h, ax=ax, label=spsdl.units)
ax.set(xlabel="Time", ylabel="Frequency [Hz]")

return fig, ax
Expand Down Expand Up @@ -97,6 +97,6 @@ def plot_spectra(spsdl, fmin=10, fmax=100000, fig=None, ax=None, **kwargs):
left=0.1, right=0.95, top=0.85, bottom=0.2, hspace=0.3, wspace=0.15
)
ax.plot(spsdl[freq], spsdl.T, **kwargs)
ax.set(xlim=(fmin, fmax), xlabel="Frequency [Hz]", ylabel="$dB re 1 uPa^2/Hz$")
ax.set(xlim=(fmin, fmax), xlabel="Frequency [Hz]", ylabel=spsdl.units)

return fig, ax
62 changes: 13 additions & 49 deletions mhkit/acoustics/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,52 +128,6 @@ def _calculate_voltage_and_time(
return raw_voltage, time, max_count


def _convert_to_pressure(
raw_voltage: np.ndarray,
sensitivity: Union[int, float],
gain: Union[int, float],
) -> np.ndarray:
"""
Converts the raw voltage data into sound pressure and calculates
the minimum resolution and saturation levels based on the hydrophone's
sensitivity and gain.
Parameters
----------
raw_voltage: numpy.ndarray
The normalized voltage values corresponding to the raw data from the WAV file.
sensitivity: int or float
The hydrophone's sensitivity in dB re 1 V/uPa, entered as a negative value.
gain: int or float
Amplifier gain in dB. Default is 0.
Returns
-------
pressure: numpy.ndarray
Calculated sound pressure values in Pascals (Pa).
"""

if not isinstance(raw_voltage, np.ndarray):
raise TypeError("'raw_voltage' must be a numpy.ndarray.")
if not isinstance(sensitivity, (int, float)):
raise TypeError("'sensitivity' must be numeric (int or float).")
if not isinstance(gain, (int, float)):
raise TypeError("'gain' must be numeric (int or float).")

# Subtract gain
# hydrophone with sensitivity of -177 dB and gain of -3 dB = sensitivity of -174 dB
if gain:
sensitivity -= gain
# Convert calibration from dB rel 1 V/uPa into ratio
sensitivity = 10 ** (sensitivity / 20) # V/uPa

# Sound pressure
pressure = raw_voltage / sensitivity # uPa
pressure = pressure / 1e6 # Pa

return pressure


def read_hydrophone(
filename: Union[str, Path],
peak_voltage: Union[int, float],
Expand Down Expand Up @@ -236,13 +190,23 @@ def read_hydrophone(

# If sensitivity is provided, convert to sound pressure
if sensitivity is not None:
raw_pressure = _convert_to_pressure(raw_voltage, sensitivity, gain)
# Subtract gain
# Hydrophone with sensitivity of -177 dB and gain of -3 dB = sensitivity of -174 dB
if gain:
sensitivity -= gain
# Convert calibration from dB rel 1 V/uPa into ratio
sensitivity = 10 ** (sensitivity / 20) # V/uPa

# Sound pressure
pressure = raw_voltage / sensitivity # uPa
pressure = pressure / 1e6 # Pa

out = xr.DataArray(
raw_pressure,
pressure,
coords={"time": time[:-1]},
attrs={
"units": "Pa",
"sensitivity": sensitivity,
"sensitivity": np.round(sensitivity, 12),
# Pressure min resolution
"resolution": np.round(peak_voltage / max_count / sensitivity / 1e6, 9),
# Minimum pressure sensor can read
Expand Down
16 changes: 0 additions & 16 deletions mhkit/tests/acoustics/test_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,22 +59,6 @@ def test_calculate_voltage_and_time(self):
)
pd.testing.assert_index_equal(time, expected_time)

def test_pressure_conversion(self):
raw_voltage = np.array([0.0, 1.25, -1.25, 0.625, -0.625])
sensitivity = -160
gain = 0

processed_pressure = acoustics.io._convert_to_pressure(
raw_voltage, sensitivity, gain
)

# Calculate expected values
adjusted_sensitivity = sensitivity - gain
sensitivity_linear = 10 ** (adjusted_sensitivity / 20) # V/μPa

expected_pressure = raw_voltage / sensitivity_linear / 1e6 # Convert to Pa
np.testing.assert_allclose(processed_pressure, expected_pressure, atol=1e-12)

def test_read_iclisten_metadata(self):
from mhkit.acoustics.io import _read_iclisten_metadata

Expand Down

0 comments on commit 22512f1

Please sign in to comment.