diff --git a/notebooks/_config.yml b/notebooks/_config.yml index 4b38e9a..aeb562c 100644 --- a/notebooks/_config.yml +++ b/notebooks/_config.yml @@ -22,9 +22,9 @@ latex: # Information about where the book exists on the web repository: - url: https://github.com/OSOceanAcoustics/echopype-examples # Online location of your book - path_to_book: notebooks # Optional path to your book, relative to the repository root - branch: main # Which branch of the repository should be used when creating links (optional) + url: https://github.com/echostack-org/echopype-examples + path_to_book: notebooks + branch: main # Add GitHub buttons to your book # See https://jupyterbook.org/customize/config.html#add-a-link-to-your-repository diff --git a/notebooks/_toc.yml b/notebooks/_toc.yml index e112d10..26ea450 100644 --- a/notebooks/_toc.yml +++ b/notebooks/_toc.yml @@ -16,6 +16,7 @@ parts: - file: krill_freq_diff - file: hake_mask - file: glider_AZFP + - file: resample_to_geometry - caption: Community showcase numbered: False diff --git a/notebooks/gallery.yml b/notebooks/gallery.yml index a13da1c..3830b45 100644 --- a/notebooks/gallery.yml +++ b/notebooks/gallery.yml @@ -1,8 +1,8 @@ - section: Getting started items: - name: Getting Started with Echopype - website: https://echopype-examples.readthedocs.io/en/latest/getting_started.html - repository: https://github.com/OSOceanAcoustics/echopype-examples/blob/main/notebooks/getting_started.ipynb + website: getting_started.html + repository: https://github.com/echostack-org/echopype-examples/blob/main/notebooks/getting_started.ipynb notebook: getting_started.ipynb summary: A minimum example to get started on Echopype functions. image: images/gallery/01_getting_started.png @@ -10,53 +10,60 @@ - section: Processing items: - name: Watching Eclipse from a Moored Echosounder - website: https://echopype-examples.readthedocs.io/en/latest/OOI_eclipse.html - repository: https://github.com/OSOceanAcoustics/echopype-examples/blob/main/notebooks/OOI_eclipse.ipynb + website: OOI_eclipse.html + repository: https://github.com/echostack-org/echopype-examples/blob/main/notebooks/OOI_eclipse.ipynb notebook: OOI_eclipse.ipynb summary: Pairing acoustic data from an upward-looking echosounder and shortwave irradiance measured by a pyrometer on a surface mooring to observe the movement response of zooplankton to a solar eclipse. (Not binder friendly.) image: images/gallery/02_OOI_eclipse.png - name: Seafloor Detection - website: https://echopype-examples.readthedocs.io/en/latest/seafloor_detection.html - repository: https://github.com/OSOceanAcoustics/echopype-examples/blob/main/notebooks/seafloor_detection.ipynb + website: seafloor_detection.html + repository: https://github.com/echostack-org/echopype-examples/blob/main/notebooks/seafloor_detection.ipynb notebook: seafloor_detection.ipynb summary: Seafloor detection with echopype (two algorithms) and use of echoregions; compute a bottom line and mask below-bottom data. image: images/gallery/07_seafloor.png - name: Transient Noise Removal - website: https://echopype-examples.readthedocs.io/en/latest/transient_noise.html - repository: https://github.com/OSOceanAcoustics/echopype-examples/blob/main/notebooks/transient_noise.ipynb + website: transient_noise.html + repository: https://github.com/echostack-org/echopype-examples/blob/main/notebooks/transient_noise.ipynb notebook: transient_noise.ipynb summary: Transient noise removal with echopype (two algorithms) and exploring the effects on Sv profiles. image: images/gallery/08_transient_noise.png - name: Ship Tracks Visualisation - website: https://echopype-examples.readthedocs.io/en/latest/ship_tracks.html - repository: https://github.com/OSOceanAcoustics/echopype-examples/blob/main/notebooks/ship_tracks.ipynb + website: ship_tracks.html + repository: https://github.com/echostack-org/echopype-examples/blob/main/notebooks/ship_tracks.ipynb notebook: ship_tracks.ipynb summary: Subselect sections of echo data based on ship GPS data embedded in the echosounder raw files to demonstrate the power of label-aware data processing based on standardized netCDF data model. (Not binder friendly.) image: images/gallery/03_subselection.png - name: Krill Frequency Differencing - website: https://echopype-examples.readthedocs.io/en/latest/krill_freq_diff.html - repository: https://github.com/OSOceanAcoustics/echopype-examples/blob/main/notebooks/krill_freq_diff.ipynb + website: krill_freq_diff.html + repository: https://github.com/echostack-org/echopype-examples/blob/main/notebooks/krill_freq_diff.ipynb notebook: krill_freq_diff.ipynb summary: Perform frequency-differencing analysis to identify fluid-like zooplankton scatterers (likely krill) in ship echosounder data, and compute nautical acoustic scattering coefficient (NASC) based on the classification. (Not binder friendly.) image: images/gallery/04_krill.png - name: Masking Echogram and Computing NASC - website: https://echopype-examples.readthedocs.io/en/latest/hake_mask.html - repository: https://github.com/OSOceanAcoustics/echopype-examples/blob/main/notebooks/hake_mask.ipynb + website: hake_mask.html + repository: https://github.com/echostack-org/echopype-examples/blob/main/notebooks/hake_mask.ipynb notebook: hake_mask.ipynb summary: Incorporate an externally generated mask that identify the occurrence of Pacific hake in ship echosounder data, and compute NASC based on the masked outputs. image: images/gallery/05_NASC.png - name: Glider AZFP Processing - website: https://echopype-examples.readthedocs.io/en/latest/glider_AZFP.html - repository: https://github.com/OSOceanAcoustics/echopype-examples/blob/main/notebooks/glider_AZFP.ipynb + website: glider_AZFP.html + repository: https://github.com/echostack-org/echopype-examples/blob/main/notebooks/glider_AZFP.ipynb notebook: glider_AZFP.ipynb summary: Process acoustic data from a Slocum glider by incorporating external position, motion, and environmental data and identify zooplankton shoals. image: images/gallery/06_glider.png + - name: Resample Channels to a Common Range Geometry + website: resample_to_geometry.html + repository: https://github.com/echostack-org/echopype-examples/blob/main/notebooks/resample_to_geometry.ipynb + notebook: resample_to_geometry.ipynb + summary: Resample acoustic variables across channels to a reference channel geometry or a custom ping-dependent range grid. + image: images/gallery/10_resample_to_geometry.png + - section: Community showcase items: [] \ No newline at end of file diff --git a/notebooks/images/gallery/10_resample_to_geometry.png b/notebooks/images/gallery/10_resample_to_geometry.png new file mode 100644 index 0000000..dac8eb7 Binary files /dev/null and b/notebooks/images/gallery/10_resample_to_geometry.png differ diff --git a/notebooks/resample_to_geometry.ipynb b/notebooks/resample_to_geometry.ipynb new file mode 100644 index 0000000..0aa3c8f --- /dev/null +++ b/notebooks/resample_to_geometry.ipynb @@ -0,0 +1,5759 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "1755b086", + "metadata": {}, + "source": [ + "## Resample channels to a common range geometry" + ] + }, + { + "cell_type": "markdown", + "id": "193fcd24", + "metadata": {}, + "source": [ + "```{important}\n", + "This notebook uses development-version functionality that is not yet available in the latest released version of `echopype`.\n", + "\n", + "Users need to install `echopype` from source to reproduce the examples shown here.\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "4bf4663c", + "metadata": {}, + "source": [ + "### Introduction\n", + "\n", + "Echosounder data collected on different transducer channels (typically at different frequencies) may not share the same vertical sampling resolution or maximum range. When analyzing data, it is often useful to regrid all channels to a common geometry along range. This notebook demonstrates three approaches to do this:\n", + "\n", + "1. Resampling to the exact geometry of the 200 kHz channel.\n", + "2. Resampling to a custom regular grid using the 200 kHz spacing while extending the range support.\n", + "3. Resampling to a custom irregular `echo_range` grid whose spacing varies along range and between pings.\n", + "\n", + "The examples also verify the output dimensions and attributes, demonstrate the handling of linear variables such as angles, and illustrate how each set of parameter choices affects the final data geometry." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "6ec7b13c-3310-4f22-82b6-8c636441cf19", + "metadata": {}, + "outputs": [], + "source": [ + "import warnings\n", + "\n", + "import echopype as ep\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import pandas as pd\n", + "import xarray as xr\n", + "\n", + "from echopype.commongrid import resample_to_geometry" + ] + }, + { + "cell_type": "markdown", + "id": "2dd1f5b5-7d8b-43d5-bc86-0455ca36c512", + "metadata": {}, + "source": [ + "#### Load an EK80 dataset\n", + "\n", + "We first load a multi-frequency EK80 dataset and compute the calibrated volume backscattering strength (`Sv`).\n", + "A variable `depth` is then added to the dataset to simplify the comparison between channels." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "2d0b2ac9-4fba-4337-8f41-6e4edef56676", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
<xarray.Dataset> Size: 926MB\n", + "Dimensions: (channel: 5, ping_time: 213,\n", + " range_sample: 36198, filenames: 1)\n", + "Coordinates:\n", + " * channel (channel) object 40B 'WBT 400140-15 ES120-...\n", + " * ping_time (ping_time) datetime64[ns] 2kB 2023-08-11T...\n", + " * range_sample (range_sample) int64 290kB 0 1 ... 36197\n", + " * filenames (filenames) int64 8B 0\n", + "Data variables: (12/26)\n", + " Sv (channel, ping_time, range_sample) float64 308MB ...\n", + " echo_range (channel, ping_time, range_sample) float64 308MB ...\n", + " tau_effective (channel) float64 40B 0.0009239 ... 0.0009306\n", + " frequency_nominal (channel) float64 40B 1.2e+05 ... 2e+05\n", + " sound_speed float64 8B 1.48e+03\n", + " sound_absorption (channel) float64 40B 0.03281 ... 0.0463\n", + " ... ...\n", + " impedance_transducer (channel) float64 40B 75.0 75.0 ... 75.0 75.0\n", + " impedance_transceiver (channel) int64 40B 5400 5400 5400 5400 5400\n", + " receiver_sampling_frequency (channel) float64 40B 1.5e+06 ... 1.5e+06\n", + " source_filenames (filenames) <U82 328B 's3://noaa-wcsd-pds/...\n", + " water_level float64 8B 0.0\n", + " depth (channel, ping_time, range_sample) float64 308MB ...\n", + "Attributes:\n", + " processing_software_name: echopype\n", + " processing_software_version: 0.11.2.dev183+g02b009a05\n", + " processing_time: 2026-07-23T00:04:22+00:00\n", + " processing_function: calibrate.compute_Sv
<xarray.Dataset> Size: 926MB\n", + "Dimensions: (ping_time: 213, range_sample: 36198, channel: 5)\n", + "Coordinates:\n", + " * ping_time (ping_time) datetime64[ns] 2kB 2023-08-11T16:57:27.277...\n", + " * range_sample (range_sample) int64 290kB 0 1 2 3 ... 36195 36196 36197\n", + " * channel (channel) object 40B 'WBT 400140-15 ES120-7C_ES' ... '...\n", + "Data variables:\n", + " Sv (channel, ping_time, range_sample) float64 308MB dask.array<chunksize=(1, 213, 36198), meta=np.ndarray>\n", + " echo_range (channel, ping_time, range_sample) float64 308MB dask.array<chunksize=(5, 213, 36198), meta=np.ndarray>\n", + " frequency_nominal (channel) float64 40B dask.array<chunksize=(1,), meta=np.ndarray>\n", + " water_level float64 8B 0.0\n", + " depth (channel, ping_time, range_sample) float64 308MB dask.array<chunksize=(5, 213, 36198), meta=np.ndarray>\n", + "Attributes:\n", + " processing_software_name: echopype\n", + " processing_software_version: 0.11.2.dev183+g02b009a05\n", + " processing_time: 2026-07-23T00:06:17+00:00\n", + " processing_function: commongrid.resample_to_geometry
<xarray.DataArray 'echo_range' (range_sample: 31674)> Size: 253kB\n", + "array([0.00000000e+00, 2.36792326e-02, 4.73584653e-02, ...,\n", + " 7.49944977e+02, 7.49968656e+02, 7.49992335e+02], shape=(31674,))\n", + "Coordinates:\n", + " * range_sample (range_sample) int64 253kB 0 1 2 3 ... 31670 31671 31672 31673\n", + "Attributes:\n", + " long_name: Range distance\n", + " units: m
<xarray.Dataset> Size: 810MB\n", + "Dimensions: (channel: 5, ping_time: 213, range_sample: 31674)\n", + "Coordinates:\n", + " * channel (channel) object 40B 'WBT 400140-15 ES120-7C_ES' ... '...\n", + " * ping_time (ping_time) datetime64[ns] 2kB 2023-08-11T16:57:27.277...\n", + " * range_sample (range_sample) int64 253kB 0 1 2 3 ... 31671 31672 31673\n", + "Data variables:\n", + " Sv (channel, ping_time, range_sample) float64 270MB dask.array<chunksize=(1, 213, 31674), meta=np.ndarray>\n", + " echo_range (channel, ping_time, range_sample) float64 270MB 0.0 ....\n", + " frequency_nominal (channel) float64 40B dask.array<chunksize=(1,), meta=np.ndarray>\n", + " water_level float64 8B 0.0\n", + " depth (channel, ping_time, range_sample) float64 270MB 0.0 ....\n", + "Attributes:\n", + " processing_software_name: echopype\n", + " processing_software_version: 0.11.2.dev183+g02b009a05\n", + " processing_time: 2026-07-23T00:07:39+00:00\n", + " processing_function: commongrid.resample_to_geometry
| \n", + " | frequency_kHz | \n", + "original_grid_max_m | \n", + "strict_200_grid_max_m | \n", + "custom_grid_max_m | \n", + "original_last_finite_Sv_m | \n", + "strict_last_finite_Sv_m | \n", + "custom_last_finite_Sv_m | \n", + "
|---|---|---|---|---|---|---|---|
| 0 | \n", + "120.0 | \n", + "749.980496 | \n", + "299.968519 | \n", + "749.992335 | \n", + "749.980496 | \n", + "299.968519 | \n", + "749.992335 | \n", + "
| 1 | \n", + "18.0 | \n", + "749.977536 | \n", + "299.968519 | \n", + "749.992335 | \n", + "749.977536 | \n", + "299.968519 | \n", + "749.992335 | \n", + "
| 2 | \n", + "70.0 | \n", + "749.980496 | \n", + "299.968519 | \n", + "749.992335 | \n", + "749.980496 | \n", + "299.968519 | \n", + "749.992335 | \n", + "
| 3 | \n", + "38.0 | \n", + "749.980496 | \n", + "299.968519 | \n", + "749.992335 | \n", + "749.980496 | \n", + "299.968519 | \n", + "749.992335 | \n", + "
| 4 | \n", + "200.0 | \n", + "299.968519 | \n", + "299.968519 | \n", + "749.992335 | \n", + "299.968519 | \n", + "299.968519 | \n", + "299.968519 | \n", + "
| \n", + " | frequency_kHz | \n", + "sample_interval_s | \n", + "expected_spacing_m | \n", + "original_spacing_m | \n", + "resampled_spacing_m | \n", + "original_max_range_m | \n", + "resampled_max_range_m | \n", + "
|---|---|---|---|---|---|---|---|
| 0 | \n", + "120.0 | \n", + "0.000040 | \n", + "0.029599 | \n", + "0.029599 | \n", + "0.023679 | \n", + "749.980496 | \n", + "299.968519 | \n", + "
| 1 | \n", + "18.0 | \n", + "0.000028 | \n", + "0.020719 | \n", + "0.020719 | \n", + "0.023679 | \n", + "749.977536 | \n", + "299.968519 | \n", + "
| 2 | \n", + "70.0 | \n", + "0.000048 | \n", + "0.035519 | \n", + "0.035519 | \n", + "0.023679 | \n", + "749.980496 | \n", + "299.968519 | \n", + "
| 3 | \n", + "38.0 | \n", + "0.000040 | \n", + "0.029599 | \n", + "0.029599 | \n", + "0.023679 | \n", + "749.980496 | \n", + "299.968519 | \n", + "
| 4 | \n", + "200.0 | \n", + "0.000032 | \n", + "0.023679 | \n", + "0.023679 | \n", + "0.023679 | \n", + "299.968519 | \n", + "299.968519 | \n", + "
<xarray.Dataset> Size: 617MB\n", + "Dimensions: (ping_time: 213, channel: 5, range_sample: 36198)\n", + "Coordinates:\n", + " * ping_time (ping_time) datetime64[ns] 2kB 2023-08-11T16:57:27.277...\n", + " * channel (channel) object 40B 'WBT 400140-15 ES120-7C_ES' ... '...\n", + " * range_sample (range_sample) int64 290kB 0 1 2 3 ... 36195 36196 36197\n", + "Data variables:\n", + " Sv (channel, ping_time, range_sample) float64 308MB dask.array<chunksize=(1, 100, 36198), meta=np.ndarray>\n", + " echo_range (channel, ping_time, range_sample) float64 308MB 0.0 ....\n", + " frequency_nominal (channel) float64 40B dask.array<chunksize=(1,), meta=np.ndarray>\n", + " water_level float64 8B 0.0\n", + "Attributes:\n", + " processing_software_name: echopype\n", + " processing_software_version: 0.11.2.dev183+g02b009a05\n", + " processing_time: 2026-07-23T00:09:15+00:00\n", + " processing_function: commongrid.resample_to_geometry