Skip to content

[1488] Support frequency nominal dim in consolidate functions#1520

Open
dbashford-NOAA wants to merge 99 commits intoOSOceanAcoustics:mainfrom
dbashford-NOAA:1488_support_frequency_nominal_in_consolidate_functions
Open

[1488] Support frequency nominal dim in consolidate functions#1520
dbashford-NOAA wants to merge 99 commits intoOSOceanAcoustics:mainfrom
dbashford-NOAA:1488_support_frequency_nominal_in_consolidate_functions

Conversation

@dbashford-NOAA
Copy link
Copy Markdown
Collaborator

Resolves #1488

  • Use a generalized dim_0 so frequency nominal can be supported in place of channel
  • Added testing for the swapped dims
  • Update tests to use fixture for the test data folder

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Jul 30, 2025

Codecov Report

❌ Patch coverage is 70.26379% with 124 lines in your changes missing coverage. Please review.
✅ Project coverage is 84.96%. Comparing base (9f56124) to head (1b30b30).
⚠️ Report is 387 commits behind head on main.

Files with missing lines Patch % Lines
...hopype/mask/seafloor_detection/bottom_blackwell.py 14.89% 40 Missing ⚠️
...hopype/clean/transient_noise/transient_fielding.py 38.33% 37 Missing ⚠️
echopype/mask/seafloor_detection/utils.py 53.84% 18 Missing ⚠️
...chopype/clean/transient_noise/transient_matecho.py 78.57% 15 Missing ⚠️
echopype/mask/shoal_detection/shoal_echoview.py 90.16% 6 Missing ⚠️
echopype/mask/shoal_detection/shoal_weill.py 91.22% 5 Missing ⚠️
echopype/consolidate/api.py 90.00% 1 Missing ⚠️
echopype/echodata/echodata.py 80.00% 1 Missing ⚠️
echopype/mask/api.py 93.33% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1520      +/-   ##
==========================================
+ Coverage   83.52%   84.96%   +1.44%     
==========================================
  Files          64       79      +15     
  Lines        5686     7004    +1318     
==========================================
+ Hits         4749     5951    +1202     
- Misses        937     1053     +116     
Flag Coverage Δ
unittests 84.96% <70.26%> (+1.44%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@dbashford-NOAA dbashford-NOAA requested a review from leewujung July 30, 2025 16:41
…ts [all tests ci] (OSOceanAcoustics#1517)

* [1486] Support computing MVBS with frequency_nominal and fix some tests

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* [1486] Use Dataset.sizes instaed of Dataset.dims

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
dependabot bot and others added 5 commits August 12, 2025 21:07
…tics#1529)

Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4 to 5.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](actions/download-artifact@v4...v5)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](actions/checkout@v4...v5)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…#1527)

Bumps [actions/cache](https://github.com/actions/cache) from 4.2.3 to 4.2.4.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](actions/cache@v4.2.3...v4.2.4)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: 4.2.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
updates:
- [github.com/pre-commit/pre-commit-hooks: v5.0.0 → v6.0.0](pre-commit/pre-commit-hooks@v5.0.0...v6.0.0)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This PR updates the pr.yaml GitHub Actions workflow to always run the full test suite for all pull requests, regardless of the PR title, by removing the conditional logic that previously limited full test runs to PRs titled with [all tests ci].
Comment on lines 209 to 213
dim_0 = list(ds.sizes.keys())[0]
if echodata["Sonar/Beam_group1"][dim_0].equals(ds[dim_0]):
beam_group_name = "Beam_group1"
else:
beam_group_name = "Beam_group2"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, the current implementation

            if echodata["Sonar/Beam_group1"][dim_0].equals(ds[dim_0]):
                beam_group_name = "Beam_group1"
            else:
                beam_group_name = "Beam_group2"

is a weird setup in terms of Beam_groupX selection. This is a larger issue so no immediate actions required under this PR, but I will note this in a separate issue.

Comment on lines +355 to +357
def test_add_splitbeam_angle_w_dim_swap(sonar_model, test_path_key, raw_file_name, test_path,
paths_to_echoview_mat, waveform_mode, encode_mode,
pulse_compression, to_disk):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This new test is largely identical with the existing test_add_splitbeam_angle, and the content of that test was to make sure the split beam angle computation is correct. I think it's a bit meddling the water to repeat the same thing here, since dimension swap is not part of the split beam calculate.

Could you slim this down to just testing the dimension swap?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is already a test for the swap_dims_channel_frequency and I didn't make any changes to that function but do you think it needs more coverage? This test was meant to cover the changes I made to 'test_add_splitbeam_angle' and make sure the split beam angle computation was correct when the dims are swapped. Maybe it would be better to just add a dim swap test case to the existing test_add_splitbeam_angle test?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

adding one test to go through the swap_dims_channel_frequency step and then add_splitbeam_angle would be great. I think making it a separate test from test_add_splitbeam_angle which tests the function outputs would be a good idea.

Comment on lines +640 to +642
def test_add_depth_EK_with_beam_angles_with_different_beam_groups_and_dim_swap(
file, sonar_model, compute_Sv_kwargs, expected_beam_group_name, ek80_path
):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to my comment on test_add_splitbeam_angle, I think it's better to not repeat the same test and create a new one focusing on the dimension swap.

Copy link
Copy Markdown
Member

@leewujung leewujung left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dbashford-NOAA : Thanks for the PR. Sorry it took a while for me to get to this.

I made a few suggestions that I think will improve the robustness and the tests.

Could you also add a test for add_location to make sure things flow through even with dimension swap? Thanks.

Please request my review once you're done with the above.

dependabot bot and others added 11 commits September 20, 2025 18:33
…SOceanAcoustics#1534)

Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.12.4 to 1.13.0.
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](pypa/gh-action-pypi-publish@v1.12.4...v1.13.0)

---
updated-dependencies:
- dependency-name: pypa/gh-action-pypi-publish
  dependency-version: 1.13.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…oustics#1535)

Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5.5.0 to 6.0.0.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](actions/setup-python@v5.5.0...v6.0.0)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
updates:
- [github.com/psf/black: 25.1.0 → 25.9.0](psf/black@25.1.0...25.9.0)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Extend .pre-commit-config.yaml to ignore the word "weill", which is used as a method in the shoal detection module. If not, codespell incorrectly flags and auto-corrects it to "will".
…ests ci] (OSOceanAcoustics#1521)

* Implementations of basic seafloor detection in mask subpackage; example notebook coming soon.

I have tested two possible ways to integrate the seafloor detection into the current workflow. Both functions are currently implemented in the mask subpackage (the second one is temporarily located in the seafloor_detection subpackage within mask).

An example notebook demonstrating and testing the feature will be submitted soon to the echopype-examples repository for review.

* Add detect_bottom() dispatcher function for bottom line detection Description:

* Introduced detect_bottom() in mask/api.py to act as a unified interface for bottom detection methods
* Replaced the earlier class-based approach with simpler functional structure under mask/seafloor_detection
* Output is now a 1D DataArray (no channel dim), with one depth per ping

* Added Blackwell detection method (adapted from echopy)

Adds a new bottom detection method (detect_blackwell), based on the approach by Blackwell et al. (2019) and adapted from the Echopy package. It uses both Sv and split-beam angles (angle_alongship, angle_athwartship) to detect the seafloor and returns one bottom depth per ping.

Other changes:

    * Renamed the surface_skip argument to bin_skip_from_surface in detect_basic() to make it clearer.

* Added test for seafloor basic and blackwell methods

Added four basic tests for basic and blackwell methods

* Update test_mask.py

updated the test "test_blackwell_vs_basic_close" to use local file

* Addresses review feedback

- Add detailed docstrings to:
  - detect_seafloor (now documents per-method args)
  - bottom_blackwell
  - bottom_basic
- Rename registry from METHODS -> METHODS_BOTTOM to scope it to bottom detection.
- Replace local lin/log helpers with echopype.utils.compute._log2lin / _lin2log; remove duplicates.
- Rename functions to make purpose explicit:
  - detect_basic      -> bottom_basic
  - detect_blackwell  -> bottom_blackwell
- Update associated files/exports to match new names.

Refs: PR OSOceanAcoustics#1521 (addresses review feedback)

* Apply suggestions from code review

docstring modifications

Co-authored-by: Wu-Jung Lee <leewujung@gmail.com>

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: Wu-Jung Lee <leewujung@gmail.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
…#1547)

Bumps [actions/cache](https://github.com/actions/cache) from 4.2.4 to 4.3.0.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](actions/cache@v4.2.4...v4.3.0)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: 4.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
leewujung and others added 6 commits December 26, 2025 14:29
* update to use azfp in v0.11.1a2

* substitue Ana06/get-changed-files with tj-actions/changed-files

* add debugging step

* list ek60 content for comparison

* update asset without hidden files and sha256 sum

* remove listing azfp and ek60 content fetched by pooch

* clean up updating to tj-actions
…mpy_update_2.4

Update test_commongrid_api.py to match numpy update 2.4 and add prints to confest.py to display more info
Bumps [tj-actions/changed-files](https://github.com/tj-actions/changed-files) from 45 to 47.
- [Release notes](https://github.com/tj-actions/changed-files/releases)
- [Changelog](https://github.com/tj-actions/changed-files/blob/main/HISTORY.md)
- [Commits](tj-actions/changed-files@v45...v47)

---
updated-dependencies:
- dependency-name: tj-actions/changed-files
  dependency-version: '47'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
…abot/github_actions/tj-actions/changed-files-47

chore(deps): bump tj-actions/changed-files from 45 to 47
* Update pr.yaml

* Update build.yaml

add to build.yaml

* Update build.yaml

add disk cleanup to build workflow
Comment on lines +208 to +215
# Check beam groups to find which one contains the matching dimension
dim_0 = list(ds.sizes.keys())[0]
beam_group_name = None
for idx in range(echodata["Sonar"].sizes["beam_group"]):
if dim_0 in list(echodata[f"Sonar/Beam_group{idx + 1}"].sizes):
if echodata[f"Sonar/Beam_group{idx + 1}"][dim_0].equals(ds[dim_0]):
beam_group_name = f"Beam_group{idx + 1}"
break
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The block would fail if the number of channels/transducers in the 2 beamgroups are the same.

I think a cleaner approach is to simply check if dim_0 is "channel" or frequency_nominal, since this is within echopype and the first dimension should be one of these 2, or the function should error out. Later in line 225-226 you explicitly do an if-else for these 2 allowed dimension names anyway, so no need to broadening this up to other possible dimension names.

Comment on lines +220 to +232
logger.warning(
f"Could not identify beam group for dimension `{dim_0}`. "
"Defaulting to `Beam_group1`."
)
if (
"channel" not in list(echodata["Sonar/Beam_group1"].sizes)
and dim_0 != "frequency_nominal"
):
raise ValueError(
"Could not identify beam group for dimension "
f"`{dim_0}` and `Beam_group1` does not have a "
"`channel` or `frequency_nominal` dimension to swap."
)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

adapt these to work with direct check of if dim_0 is "channel" or "frequency_nominal"

Comment on lines +234 to +237
# Swap beam group dims if necessary
echodata["Sonar/Beam_group1"] = swap_dims_channel_frequency(
echodata["Sonar/Beam_group1"]
)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't want to swap "frequency_nominal" with "channel" -- we want to preserve whatever the dimension the input ds has and just add the depth variable to the dataset.

Comment on lines +490 to +493
if dim_0 not in list(echodata[ed_beam_group].sizes) and "channel" in list(
echodata[ed_beam_group].sizes
):
echodata[ed_beam_group] = swap_dims_channel_frequency(echodata[ed_beam_group])
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't want to swap "frequency_nominal" with "channel" -- we want to preserve whatever the dimension the input ds has and just add the depth variable to the dataset.


ds_Sv_with_depth = ep.consolidate.add_depth(ds_Sv, ed, use_beam_angles=True)

# Check that channel dim has been swapped to frequency_nominal
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make sure to change this too since we want to preserve whatever the input ds has

encode_mode=encode_mode,
to_disk=False)

# Check that channel dim has been swapped to frequency_nominal
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make sure to change this too since we want to preserve whatever the input ds has

Copy link
Copy Markdown
Member

@leewujung leewujung left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dbashford-NOAA : Sorry it again took a while for me to get to this!

I think there may have been some misunderstandings on what #1488 aims to achieve, but hopefully my comments below and inline would clear it up.

The goal of #1488 is to enable users to use all functions in ep.consolidate on Sv dataset regardless of if they have called swap_dims_channel_frequency or not.

With this in mind, I have a couple suggestions for this PR:

  • for all ep.consolidate functions, check if either "channel" or "frequency_nominal" exists in the input ds, and error out if not.
    • I'd suggest making a small utility function for this and returns dim_0, so that the same routine can be used across all functions. This would help with future maintenance since everything is in one place.
  • make sure all ep.consolidate functions have a test that checks if the function would run through on Sv dataset both before and after calling swap_dims_channel_frequency -- this embodies the goal of #1488

Also, please pull in all upstream changes to make sure your tests will run with the right assets. We've changed the CI setup pretty significantly in the past month or so. Those changes shouldn't impact the components you're working on, but just in case since I saw some directory changes in this PR.

@dbashford-NOAA
Copy link
Copy Markdown
Collaborator Author

@leewujung
Do you know if there is any test data I could use for add_depth and add_splitbeam_angle that has the frequency_nominal dim instead of channel?
I think part of the issue is that I was trying to adapt the existing test data to test with a frequency_nominal dim.

@leewujung
Copy link
Copy Markdown
Member

@dbashford-NOAA : ah I see. Echopype generated echodata object and its derivative like the Sv dataset would always have channel as a dimension initially. It’s only when users use swap_dims_channel_frequency will they get that dimension changed to frequency_nominal. We made that swap function because most people refer to different channels by their central frequency - like “the 120 kHz channel.”

What we can’t control is when users would do the swap, and therefore we want to get all consolidate functions to be able to work with both the before and after swap data.

So, you can get that by using the swap function.

@dbashford-NOAA
Copy link
Copy Markdown
Collaborator Author

@leewujung
I think I've addressed everything you mentioned. I left the dim swap in the test code just as a way to adapt the data to test when dim_0 is frequency_nominal. Let me know if there's anything else that needs to change.

@leewujung leewujung moved this to In Progress in Echopype 2026 Apr 2, 2026
@leewujung leewujung moved this from In Progress to In Review in Echopype 2026 Apr 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Review

Development

Successfully merging this pull request may close these issues.

Support dimension alignment with frequency_nominal for all ep.consolidate functions

4 participants