Simple Analysis of Recording Levels#

This tutorial covers the basic steps required to load recording data, make a simple spectrogram, and how to compute and plot hourly averages over a single day.

Initialization code
>>> import uwacan
>>> from pathlib import Path

>>> data_path = Path(r"D:\ExampleData\LongRecording")

Sensor information#

To load data from recordings and convert it to physical units, we need to specify some information about the sensor used to do the recording. For a simple level analysis, only the sensor sensitivity is required, but for other types of analysis the position and depth of the sensor might also be needed. We store the information in a sensor object:

>>> sensor = uwacan.sensor(
...     "RTsys 1",
...     sensitivity=-179.2,
...     position="58° 51.065'N 11° 4.569'E",
...     depth=18,
... )

The first argument gives a label. In uwacan, sensors always have to be labeled.

Recordings#

Recordings are object is responsible for loading time-data from disk, and performs conversions from the data storage format to physical units:

>>> recording = uwacan.recordings.SylenceLP.read_folder(
...     data_path / "RTsys 1" / "timedata",
...     sensor=sensor,
... )
>>> print(recording.time_window)
TimeWindow(start=2024-08-01 00:19:58Z, stop=2024-08-04 00:26:07.952Z)

Some common recording types are implemented in uwacan.recordings.

Spectrogram#

To compute a detailed Spectrogram, we start by selecting a shorter time to compute it over. This is done using the subwindow method, which is implemented on most of the objects which hold time dependent data:

>>> selection = recording.subwindow(start="2024-08-02 06:30:00z", duration=10 * 60)
>>> time_data = selection.time_data()
>>> spectrogram = uwacan.analysis.Spectrogram.analyze_timedata(
...     time_data,
...     hybrid_resolution=2,
...     bands_per_decade=100,
...     min_frequency=10,
...     max_frequency=40e3,
... )

>>> fig = spectrogram.make_figure()
>>> fig.add_trace(spectrogram.plot(zmin=30, zmax=90))
>>> fig.show()

Spectrum#

From this spectrogram we can easily compute the spectrum (power spectral density) for the same time window, by averaging over time:

>>> spectrum = spectrogram.mean("time")
>>> fig = spectrum.make_figure()
>>> fig.add_trace(spectrum.plot(name="With pulse"))
>>> fig.add_trace(
...     uwacan.analysis.Spectrogram.analyze_timedata(
...         recording.subwindow(start="2024-08-02 06:30:00z", stop="2024-08-02 06:38:00z"),
...         hybrid_resolution=2,
...         bands_per_decade=100,
...         min_frequency=10,
...         max_frequency=40e3,
...     ).mean("time").plot(name="Without pulse")
... )
>>> fig.show()

Of interest here is the strong influence that the pulse at 06:38 has on the average level at high frequencies - rising it by up to 40 dB. This pulse in the recording comes from the nearby acoustic releaser used during deployment.

Hourly spectra#

Learning from how we compute spectrograms and spectra, we can compute a spectrum for each hour of the day. To help us with accessing the recording in one-hour sequential chunks, we can use the rolling method:

>>> selection = recording.subwindow(start="2024-08-02 00:00:00z", stop="2024-08-03 00:00:00z")
>>> spectra = []
>>> for hour in selection.rolling(duration=3600, overlap=0):
...     spectrogram = uwacan.analysis.Spectrogram.analyze_timedata(
...         hour,
...         hybrid_resolution=2,
...         bands_per_decade=100,
...         min_frequency=10,
...         max_frequency=40e3,
...     )
...     spectrum = spectrogram.mean("time")
...     spectrum.coords["time"] = uwacan.time_to_np(spectrogram.time_window.center)
...     spectra.append(spectrum)
>>> spectra = uwacan.concatenate(spectra, dim="time")

To plot this, we want to loop over the time dimension in the spectra. This is easiest done using the groupby method. Combining this with some nice colorscale sampling from plotly, we arrive at:

>>> fig = spectra.make_figure()
>>> colors = plotly.colors.sample_colorscale("twilight", spectra.sizes["time"])
>>> for color, (time, spectrum) in zip(colors, spectra.groupby("time")):
...     label = uwacan.time_to_datetime(time).py_datetime().strftime("%H:%M")
...     fig.add_trace(spectrum.plot(name=label, line_color=color))
>>> fig.show()