Source code for mhkit.acoustics.graphics

"""
This submodule provides essential plotting functions for visualizing passive acoustics 
data. The functions allow for customizable plotting of sound pressure spectral density 
levels across time and frequency dimensions.

Each plotting function leverages the flexibility of Matplotlib, allowing for passthrough
of Matplotlib keyword arguments via ``**kwargs``, making it easy to modify plot aspects such as
color, scale, and label formatting.

Key Functions
-------------
1. **plot_spectrogram**:

   - Generates a spectrogram plot from sound pressure spectral density level data, 
     with a logarithmic frequency scale by default for improved readability of acoustic data.

2. **plot_spectra**:

   - Produces a spectral density plot with a log-transformed x-axis, allowing for clear 
     visualization of spectral density across frequency bands.
"""

from typing import Tuple
import xarray as xr
import matplotlib.pyplot as plt

from .analysis import _fmax_warning


[docs] def plot_spectrogram( spsdl: xr.DataArray, fmin: int = 10, fmax: int = 100000, fig: plt.figure = None, ax: plt.Axes = None, **kwargs ) -> Tuple[plt.figure, plt.Axes]: """ Plots the spectrogram of the sound pressure spectral density level. Parameters ---------- spsdl: xarray DataArray (time, freq) Mean square sound pressure spectral density level in dB rel 1 uPa^2/Hz fmin: int Lower frequency band limit (lower limit of the hydrophone). Default: 10 Hz fmax: int Upper frequency band limit (Nyquist frequency). Default: 100000 Hz fig: matplotlib.pyplot.figure Figure handle to plot on ax: matplotlib.pyplot.axis Figure axis containing plot objects kwargs: dict Dictionary of matplotlib function keyword arguments Returns ------- fig: matplotlib.pyplot.figure Figure handle of plot ax: matplotlib.pyplot.Axes Figure plot axis """ if not isinstance(fmin, (int, float)) or not isinstance(fmax, (int, float)): raise TypeError("fmin and fmax must be numeric types.") if fmin >= fmax: raise ValueError("fmin must be less than fmax.") # Set dimension names # "time" or "time_bins" is always first time = spsdl.dims[0] # "freq" or "freq_bins" is always second freq = spsdl.dims[-1] # Check fmax fn = spsdl[freq].max().item() fmax = _fmax_warning(fn, fmax) # select frequency range spsdl = spsdl.sel({freq: slice(fmin, fmax)}) if ax is None: fig, ax = plt.subplots(figsize=(6, 5), subplot_kw={"yscale": "log"}) fig.subplots_adjust(left=0.1, right=0.95, top=0.97, bottom=0.11) h = ax.pcolormesh( spsdl[time].values, spsdl[freq].values, spsdl.transpose(freq, time), shading="nearest", **kwargs ) fig.colorbar(h, ax=ax, label=getattr(spsdl, "units", None)) ax.set(xlabel="Time", ylabel="Frequency [Hz]") return fig, ax
[docs] def plot_spectra( spsdl: xr.DataArray, fmin: int = 10, fmax: int = 100000, fig: plt.figure = None, ax: plt.Axes = None, **kwargs ) -> Tuple[plt.figure, plt.Axes]: """ Plots spectral density. X axis is log-transformed. Parameters ---------- spsdl: xarray DataArray (time, freq) Mean square sound pressure spectral density level in dB rel 1 uPa^2/Hz fmin: int Lower frequency band limit (lower limit of the hydrophone). Default: 10 Hz fmax: int Upper frequency band limit (Nyquist frequency). Default: 100000 Hz fig: matplotlib.pyplot.figure Figure handle to plot on ax: matplotlib.pyplot.Axes Figure axis containing plot objects kwargs: dict Dictionary of matplotlib function keyword arguments Returns ------- fig: matplotlib.pyplot.figure Figure handle of plot ax: matplotlib.pyplot.Axes Figure plot axis """ if not isinstance(fmin, (int, float)) or not isinstance(fmax, (int, float)): raise TypeError("fmin and fmax must be numeric types.") if fmin >= fmax: raise ValueError("fmin must be less than fmax.") # Set dimension names. # "freq" or "freq_bins" is always second freq = spsdl.dims[-1] # Check fmax fn = spsdl[freq].max().item() fmax = _fmax_warning(fn, fmax) # select frequency range spsdl = spsdl.sel({freq: slice(fmin, fmax)}) if ax is None: fig, ax = plt.subplots(figsize=(6, 5), subplot_kw={"xscale": "log"}) fig.subplots_adjust( 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=getattr(spsdl, "units", None) ) return fig, ax