water-column-sonar-annotation 26.1.8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. water_column_sonar_annotation-26.1.8/LICENSE +21 -0
  2. water_column_sonar_annotation-26.1.8/PKG-INFO +109 -0
  3. water_column_sonar_annotation-26.1.8/README.md +72 -0
  4. water_column_sonar_annotation-26.1.8/pyproject.toml +68 -0
  5. water_column_sonar_annotation-26.1.8/setup.cfg +4 -0
  6. water_column_sonar_annotation-26.1.8/tests/__init__.py +0 -0
  7. water_column_sonar_annotation-26.1.8/tests/astronomical/__init__.py +0 -0
  8. water_column_sonar_annotation-26.1.8/tests/astronomical/test_astronomical_manager.py +148 -0
  9. water_column_sonar_annotation-26.1.8/tests/conftest.py +60 -0
  10. water_column_sonar_annotation-26.1.8/tests/cruise/__init__.py +0 -0
  11. water_column_sonar_annotation-26.1.8/tests/cruise/test_cruise_manager.py +80 -0
  12. water_column_sonar_annotation-26.1.8/tests/geospatial/__init__.py +0 -0
  13. water_column_sonar_annotation-26.1.8/tests/geospatial/test_geospatial_manager.py +86 -0
  14. water_column_sonar_annotation-26.1.8/tests/record/test_echoview_record_manager.py +160 -0
  15. water_column_sonar_annotation-26.1.8/water_column_sonar_annotation/__init__.py +5 -0
  16. water_column_sonar_annotation-26.1.8/water_column_sonar_annotation/astronomical/__init__.py +5 -0
  17. water_column_sonar_annotation-26.1.8/water_column_sonar_annotation/astronomical/astronomical_manager.py +82 -0
  18. water_column_sonar_annotation-26.1.8/water_column_sonar_annotation/cruise/__init__.py +5 -0
  19. water_column_sonar_annotation-26.1.8/water_column_sonar_annotation/cruise/cruise_manager.py +104 -0
  20. water_column_sonar_annotation-26.1.8/water_column_sonar_annotation/geospatial/__init__.py +5 -0
  21. water_column_sonar_annotation-26.1.8/water_column_sonar_annotation/geospatial/geospatial_manager.py +143 -0
  22. water_column_sonar_annotation-26.1.8/water_column_sonar_annotation/record/__init__.py +9 -0
  23. water_column_sonar_annotation-26.1.8/water_column_sonar_annotation/record/echoview_record_manager.py +426 -0
  24. water_column_sonar_annotation-26.1.8/water_column_sonar_annotation/record/graph_record_manager.py +82 -0
  25. water_column_sonar_annotation-26.1.8/water_column_sonar_annotation/record/parquet_record_manager.py +83 -0
  26. water_column_sonar_annotation-26.1.8/water_column_sonar_annotation/shape/__init__.py +5 -0
  27. water_column_sonar_annotation-26.1.8/water_column_sonar_annotation/shape/shape_manager.py +29 -0
  28. water_column_sonar_annotation-26.1.8/water_column_sonar_annotation.egg-info/PKG-INFO +109 -0
  29. water_column_sonar_annotation-26.1.8/water_column_sonar_annotation.egg-info/SOURCES.txt +30 -0
  30. water_column_sonar_annotation-26.1.8/water_column_sonar_annotation.egg-info/dependency_links.txt +1 -0
  31. water_column_sonar_annotation-26.1.8/water_column_sonar_annotation.egg-info/requires.txt +20 -0
  32. water_column_sonar_annotation-26.1.8/water_column_sonar_annotation.egg-info/top_level.txt +3 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Cooperative Institutes, Coastal and Marine Geophysics
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,109 @@
1
+ Metadata-Version: 2.4
2
+ Name: water-column-sonar-annotation
3
+ Version: 26.1.8
4
+ Summary: Processing Tool for Working with Water Column Sonar Annotations
5
+ Author-email: Rudy Klucik <rudy.klucik@noaa.gov>
6
+ Maintainer-email: Rudy Klucik <rudy.klucik@noaa.gov>
7
+ License-Expression: MIT
8
+ Project-URL: Homepage, https://echo.fish
9
+ Project-URL: Repository, https://github.com/CI-CMG/water-column-sonar-annotation
10
+ Project-URL: Documentation, https://github.com/CI-CMG/water-column-sonar-annotation
11
+ Project-URL: Issues, https://github.com/CI-CMG/water-column-sonar-annotation/issues
12
+ Keywords: ocean,sonar,water column
13
+ Requires-Python: >=3.12
14
+ Description-Content-Type: text/markdown
15
+ License-File: LICENSE
16
+ Requires-Dist: build
17
+ Requires-Dist: fiona
18
+ Requires-Dist: folium
19
+ Requires-Dist: geopandas
20
+ Requires-Dist: netcdf4
21
+ Requires-Dist: numpy
22
+ Requires-Dist: pandas
23
+ Requires-Dist: pandas-stubs
24
+ Requires-Dist: pooch
25
+ Requires-Dist: pvlib
26
+ Requires-Dist: pyarrow
27
+ Requires-Dist: pyogrio
28
+ Requires-Dist: python-dotenv
29
+ Requires-Dist: s3fs
30
+ Requires-Dist: scipy
31
+ Requires-Dist: shapely
32
+ Requires-Dist: setuptools
33
+ Requires-Dist: timezonefinder
34
+ Requires-Dist: xarray
35
+ Requires-Dist: zarr
36
+ Dynamic: license-file
37
+
38
+ # Water Column Sonar Annotation
39
+
40
+ Tool for converting EVR files to annotated regions of interest in parquet format
41
+
42
+ ![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/CI-CMG/water-column-sonar-annotation/test_action.yaml)
43
+ ![PyPI - Implementation](https://img.shields.io/pypi/v/water-column-sonar-annotation) ![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/CI-CMG/water-column-sonar-annotation) ![GitHub repo size](https://img.shields.io/github/repo-size/CI-CMG/water-column-sonar-annotation)
44
+
45
+ # Setting up the Python Environment
46
+
47
+ > Python 3.12.12
48
+
49
+ # Installing Dependencies
50
+
51
+ ```
52
+ source .venv/bin/activate
53
+
54
+ uv pip install --upgrade pip
55
+
56
+ uv pip install -r pyproject.toml --all-extras
57
+
58
+ uv run pre-commit install
59
+ ```
60
+
61
+ # Pytest
62
+
63
+ ```
64
+ uv run pytest tests -W ignore::DeprecationWarning
65
+ ```
66
+
67
+ or
68
+ > uv run pytest tests/cruise --cov=water_column_sonar_annotation --cov-report term-missing
69
+
70
+ ```
71
+ uv run pre-commit install --allow-missing-config
72
+ # or
73
+ uv run pre-commit install
74
+ ```
75
+
76
+ # Test Coverage
77
+
78
+ TODO
79
+
80
+ # Tag a Release
81
+
82
+ Step 1 --> increment the semantic version in the zarr_manager.py "metadata" & the "pyproject.toml"
83
+
84
+ ```commandline
85
+ git tag -a v26.1.0 -m "Releasing v26.1.0"
86
+ git push origin --tags
87
+ gh release create v26.1.0
88
+ ```
89
+
90
+ # To Publish To PROD
91
+
92
+ ```commandline
93
+ uv build --no-sources
94
+ uv publish
95
+ ```
96
+
97
+ # UV Debugging
98
+
99
+ ```
100
+ uv lock --check
101
+ uv lock
102
+ uv sync --extra dev
103
+ #uv run pytest tests
104
+ ```
105
+
106
+ ## Annotation format
107
+
108
+ - https://roboflow.com/formats/coco-json
109
+ - https://www.v7labs.com/blog/coco-dataset-guide
@@ -0,0 +1,72 @@
1
+ # Water Column Sonar Annotation
2
+
3
+ Tool for converting EVR files to annotated regions of interest in parquet format
4
+
5
+ ![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/CI-CMG/water-column-sonar-annotation/test_action.yaml)
6
+ ![PyPI - Implementation](https://img.shields.io/pypi/v/water-column-sonar-annotation) ![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/CI-CMG/water-column-sonar-annotation) ![GitHub repo size](https://img.shields.io/github/repo-size/CI-CMG/water-column-sonar-annotation)
7
+
8
+ # Setting up the Python Environment
9
+
10
+ > Python 3.12.12
11
+
12
+ # Installing Dependencies
13
+
14
+ ```
15
+ source .venv/bin/activate
16
+
17
+ uv pip install --upgrade pip
18
+
19
+ uv pip install -r pyproject.toml --all-extras
20
+
21
+ uv run pre-commit install
22
+ ```
23
+
24
+ # Pytest
25
+
26
+ ```
27
+ uv run pytest tests -W ignore::DeprecationWarning
28
+ ```
29
+
30
+ or
31
+ > uv run pytest tests/cruise --cov=water_column_sonar_annotation --cov-report term-missing
32
+
33
+ ```
34
+ uv run pre-commit install --allow-missing-config
35
+ # or
36
+ uv run pre-commit install
37
+ ```
38
+
39
+ # Test Coverage
40
+
41
+ TODO
42
+
43
+ # Tag a Release
44
+
45
+ Step 1 --> increment the semantic version in the zarr_manager.py "metadata" & the "pyproject.toml"
46
+
47
+ ```commandline
48
+ git tag -a v26.1.0 -m "Releasing v26.1.0"
49
+ git push origin --tags
50
+ gh release create v26.1.0
51
+ ```
52
+
53
+ # To Publish To PROD
54
+
55
+ ```commandline
56
+ uv build --no-sources
57
+ uv publish
58
+ ```
59
+
60
+ # UV Debugging
61
+
62
+ ```
63
+ uv lock --check
64
+ uv lock
65
+ uv sync --extra dev
66
+ #uv run pytest tests
67
+ ```
68
+
69
+ ## Annotation format
70
+
71
+ - https://roboflow.com/formats/coco-json
72
+ - https://www.v7labs.com/blog/coco-dataset-guide
@@ -0,0 +1,68 @@
1
+ [project]
2
+ name = "water-column-sonar-annotation"
3
+ version = "26.1.8"
4
+ authors = [
5
+ { name = "Rudy Klucik", email = "rudy.klucik@noaa.gov" },
6
+ ]
7
+ maintainers = [
8
+ { name = "Rudy Klucik", email = "rudy.klucik@noaa.gov" },
9
+ ]
10
+ description = "Processing Tool for Working with Water Column Sonar Annotations"
11
+ keywords = ["ocean", "sonar", "water column"]
12
+ readme = "README.md"
13
+ requires-python = ">=3.12"
14
+ license = "MIT"
15
+ license-files = ["LICENSE"]
16
+
17
+ # uv sync --all-groups --upgrade
18
+ dependencies = [
19
+ "build",
20
+ "fiona",
21
+ "folium",
22
+ "geopandas",
23
+ "netcdf4",
24
+ "numpy",
25
+ "pandas",
26
+ "pandas-stubs",
27
+ "pooch",
28
+ "pvlib",
29
+ "pyarrow",
30
+ "pyogrio",
31
+ "python-dotenv",
32
+ "s3fs", # problem here, uv finds the wrong one
33
+ "scipy",
34
+ "shapely",
35
+ "setuptools",
36
+ "timezonefinder",
37
+ # "wheel",
38
+ "xarray",
39
+ "zarr",
40
+ ]
41
+
42
+ # uv sync --all-groups --upgrade
43
+ [dependency-groups]
44
+ dev = [
45
+ "bandit[toml]",
46
+ "build",
47
+ "pooch",
48
+ "pre-commit",
49
+ "pytest",
50
+ "pytest-cov",
51
+ "ruff",
52
+ "tqdm",
53
+ ]
54
+
55
+ [project.urls]
56
+ Homepage = "https://echo.fish"
57
+ Repository = "https://github.com/CI-CMG/water-column-sonar-annotation"
58
+ Documentation = "https://github.com/CI-CMG/water-column-sonar-annotation"
59
+ Issues = "https://github.com/CI-CMG/water-column-sonar-annotation/issues"
60
+
61
+ [tool.bandit]
62
+ exclude_dirs = ["tests"]
63
+
64
+ [tool.pre-commit-hooks.bandit]
65
+ exclude = ["*/tests/*"]
66
+
67
+ [tool.setuptools.packages.find]
68
+ exclude = ["data*"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
File without changes
@@ -0,0 +1,148 @@
1
+ import numpy as np
2
+
3
+ from water_column_sonar_annotation.astronomical import AstronomicalManager
4
+
5
+
6
+ #######################################################
7
+ def setup_module():
8
+ print("setup")
9
+
10
+
11
+ def teardown_module():
12
+ print("teardown")
13
+
14
+
15
+ def test_get_solar_azimuth():
16
+ astronomical_manager = AstronomicalManager()
17
+ # https://www.suncalc.org/#/39.9812,-105.2495,13/2026.01.26/11:52/1/3
18
+ azimuth_noon = astronomical_manager.get_solar_azimuth(
19
+ iso_time="2026-01-26T19:00:00Z", # noon
20
+ latitude=39.9674884, # Boulder
21
+ longitude=-105.2532602,
22
+ )
23
+ assert np.isclose(azimuth_noon, 31.38) # 15)
24
+
25
+ azimuth_sunset = astronomical_manager.get_solar_azimuth(
26
+ iso_time="2026-01-26T00:00:00Z", # sunset
27
+ latitude=39.9674884,
28
+ longitude=-105.2532602,
29
+ )
30
+ assert np.isclose(azimuth_sunset, 1.25) # 27)
31
+
32
+
33
+ def test_get_solar_azimuth_boulder_2pm():
34
+ # 2026-01-29 @2pm is UTC: "2026-01-29T21:02:23Z"
35
+ astronomical_manager = AstronomicalManager()
36
+ # https://www.suncalc.org/#/39.9812,-105.2495,13/2026.01.26/11:52/1/3
37
+ azimuth_noon = astronomical_manager.get_solar_azimuth(
38
+ iso_time="2026-01-29T21:02:23Z", # 2pm
39
+ latitude=39.9674884, # Boulder
40
+ longitude=-105.2532602,
41
+ )
42
+ assert np.isclose(azimuth_noon, 27.01)
43
+
44
+
45
+ ### PHASE OF DAY ###
46
+ # { 'dawn': 1, 'day': 2, 'dusk': 3, 'night': 4 }
47
+ def test_phase_of_day_at_noon():
48
+ astronomical_manager = AstronomicalManager()
49
+ phase = astronomical_manager.phase_of_day(
50
+ iso_time="2026-01-27T19:00:00Z", # noon
51
+ latitude=39.9674884, # Boulder
52
+ longitude=-105.2532602,
53
+ )
54
+ assert phase == 2
55
+
56
+
57
+ def test_phase_of_day_at_midnight():
58
+ astronomical_manager = AstronomicalManager()
59
+ phase = astronomical_manager.phase_of_day(
60
+ iso_time="2026-01-28T07:00:00Z",
61
+ latitude=39.9674884, # Boulder
62
+ longitude=-105.2532602,
63
+ )
64
+ assert phase == 4
65
+
66
+
67
+ def test_phase_of_day_before_sunset():
68
+ astronomical_manager = AstronomicalManager()
69
+ phase = astronomical_manager.phase_of_day(
70
+ # sunset is at 5:13pm on jan 27th, per https://psl.noaa.gov/boulder/boulder.sunset.html
71
+ iso_time="2026-01-28T00:09:00Z", # sunset @ 5:13pm, nautical sunset @6:16pm
72
+ latitude=39.9674884, # Boulder
73
+ longitude=-105.2532602,
74
+ )
75
+ assert phase == 2 # day
76
+
77
+
78
+ def test_phase_of_day_after_sunset():
79
+ astronomical_manager = AstronomicalManager()
80
+ phase = astronomical_manager.phase_of_day(
81
+ # sunset is at 5:13pm on jan 27th, per https://psl.noaa.gov/boulder/boulder.sunset.html
82
+ iso_time="2026-01-28T00:10:00Z", # sunset @ 5:13pm, nautical sunset @6:16pm
83
+ latitude=39.9674884, # Boulder
84
+ longitude=-105.2532602,
85
+ )
86
+ assert phase == 3 # dusk
87
+
88
+
89
+ def test_phase_of_day_before_nautical_sunset():
90
+ astronomical_manager = AstronomicalManager()
91
+ # an hour'ish later is nautical sunset
92
+ phase_before_nautical_sunset = astronomical_manager.phase_of_day(
93
+ iso_time="2026-01-28T01:15:00Z", # sunset @5:13pm, nautical sunset @6:16pm
94
+ latitude=39.9674884, # Boulder
95
+ longitude=-105.2532602,
96
+ )
97
+ assert phase_before_nautical_sunset == 3 # dusk
98
+
99
+
100
+ def test_phase_of_day_after_nautical_sunset():
101
+ astronomical_manager = AstronomicalManager()
102
+ phase_after_nautical_sunset = astronomical_manager.phase_of_day(
103
+ iso_time="2026-01-28T01:17:00Z", # sunset @5:13pm, nautical sunset @6:16pm
104
+ latitude=39.9674884, # Boulder
105
+ longitude=-105.2532602,
106
+ )
107
+ assert phase_after_nautical_sunset == 4 # night
108
+
109
+
110
+ def test_phase_of_day_before_sunrise():
111
+ astronomical_manager = AstronomicalManager()
112
+ phase_at_sunrise = astronomical_manager.phase_of_day(
113
+ iso_time="2026-01-27T14:13:00Z", # sunrise @7:13am, nautical sunrise @6:12am
114
+ latitude=39.9674884, # Boulder
115
+ longitude=-105.2532602,
116
+ )
117
+ assert phase_at_sunrise == 1 # dusk
118
+
119
+
120
+ def test_phase_of_day_after_sunrise():
121
+ astronomical_manager = AstronomicalManager()
122
+ phase_at_sunrise = astronomical_manager.phase_of_day(
123
+ iso_time="2026-01-27T14:20:00Z", # sunrise @7:13am, nautical sunrise @6:12am
124
+ latitude=39.9674884, # Boulder
125
+ longitude=-105.2532602,
126
+ )
127
+ assert phase_at_sunrise == 2 # day
128
+
129
+
130
+ def test_phase_of_day_before_nautical_sunrise():
131
+ astronomical_manager = AstronomicalManager()
132
+ # about an hour before is nautical sunrise
133
+ phase_before_nautical_sunrise = astronomical_manager.phase_of_day(
134
+ iso_time="2026-01-27T13:12:00Z", # sunrise @7:13am, nautical sunrise @6:12am
135
+ latitude=39.9674884, # Boulder
136
+ longitude=-105.2532602,
137
+ )
138
+ assert phase_before_nautical_sunrise == 4 # night
139
+
140
+
141
+ def test_phase_of_day_after_nautical_sunrise():
142
+ astronomical_manager = AstronomicalManager()
143
+ phase = astronomical_manager.phase_of_day(
144
+ iso_time="2026-01-27T14:13:00Z", # sunrise @7:13am, nautical sunrise @6:12am
145
+ latitude=39.9674884, # Boulder
146
+ longitude=-105.2532602,
147
+ )
148
+ assert phase == 1
@@ -0,0 +1,60 @@
1
+ from pathlib import Path
2
+
3
+ import pooch
4
+ import pytest
5
+
6
+ HERE = Path(__file__).parent.absolute()
7
+ TEST_DATA_FOLDER = HERE / "test_resources"
8
+
9
+ HB1906_DATA = pooch.create(
10
+ path=pooch.os_cache("water-column-sonar-annotation"),
11
+ base_url="https://github.com/CI-CMG/water-column-sonar-annotation/releases/download/v26.1.0/",
12
+ retry_if_failed=1,
13
+ registry={
14
+ "HB201906_BOTTOMS.zip": "sha256:20609581493ea3326c1084b6868e02aafbb6c0eae871d946f30b8b5f0e7ba059",
15
+ "HB201906_EVR.zip": "sha256:ceed912a25301be8f1b8f91e134d0ca4cff717f52b6623a58677832fd60c2990",
16
+ #
17
+ # "ne_50m_coastline.shp": "sha256:797d675af9613f80b51ab6049fa32e589974d7a97c6497ca56772965f179ed26",
18
+ # "ne_50m_coastline.shx": "sha256:0ff1792f2d16b58246d074215edd9d12fa280880ecaad61a91b9382fee854065",
19
+ #
20
+ "ne_10m_coastline.shp": "sha256:459a4a97c09db19aadf5244026612de9d43748be27f83a360242b99f7fabb3c1",
21
+ "ne_10m_coastline.shx": "sha256:f873afee7f56779ce52253f740ec251c2f12244aea911dc40f0a85d75de8d5f2",
22
+ },
23
+ )
24
+
25
+
26
+ def fetch_raw_files():
27
+ HB1906_DATA.fetch(fname="HB201906_BOTTOMS.zip", progressbar=True)
28
+ HB1906_DATA.fetch(fname="HB201906_EVR.zip", progressbar=True)
29
+
30
+ # HB1906_DATA.fetch(fname="ne_50m_coastline.shp", progressbar=True)
31
+ # HB1906_DATA.fetch(fname="ne_50m_coastline.shx", progressbar=True)
32
+
33
+ HB1906_DATA.fetch(fname="ne_10m_coastline.shp", progressbar=True)
34
+ HB1906_DATA.fetch(fname="ne_10m_coastline.shx", progressbar=True)
35
+
36
+ file_name = HB1906_DATA.fetch(fname="HB201906_EVR.zip", progressbar=True)
37
+
38
+ """
39
+ water-column-sonar-annotation user$ ls /Users/user/Library/Caches/water-column-sonar-annotation
40
+ HB201906_BOTTOMS.zip HB201906_EVR.zip ne_10m_coastline.shp ne_10m_coastline.shx
41
+ """
42
+ return Path(file_name).parent
43
+
44
+
45
+ @pytest.fixture(scope="session")
46
+ def test_path():
47
+ return {
48
+ "DATA_TEST_PATH": fetch_raw_files(),
49
+ }
50
+
51
+
52
+ # """
53
+ # Folder locations in mac and windows:
54
+ #
55
+ # Windows
56
+ # C:\Users\<user>\AppData\Local\echopype\Cache\2024.12.23.10.10
57
+ #
58
+ # MacOS
59
+ # /Users//Library/Caches/echopype/2024.12.23.10.10
60
+ # """
@@ -0,0 +1,80 @@
1
+ import numpy as np
2
+ import pytest
3
+
4
+ from water_column_sonar_annotation.cruise import CruiseManager
5
+
6
+
7
+ #######################################################
8
+ def setup_module():
9
+ print("setup")
10
+
11
+
12
+ def teardown_module():
13
+ print("teardown")
14
+
15
+
16
+ @pytest.fixture
17
+ def process_cruise_path(test_path):
18
+ return test_path["DATA_TEST_PATH"]
19
+
20
+
21
+ #######################################################
22
+ # def test_get_cruise_bottom_nan(process_cruise_path, tmp_path):
23
+ # cruise_manager = CruiseManager()
24
+ # cruise = cruise_manager.get_cruise()
25
+ # # count of non-nan values np.count_nonzero(~np.isnan(cruise.bottom.values)) / cruise.Sv.shape[1]
26
+ # assert len(cruise.Sv.shape) == 3
27
+
28
+
29
+ def test_get_cruise(process_cruise_path, tmp_path):
30
+ cruise_manager = CruiseManager()
31
+ cruise = cruise_manager.get_cruise()
32
+ assert len(cruise.Sv.shape) == 3
33
+
34
+
35
+ def test_get_coordinates():
36
+ """This only gets the depth over the interval, need to calculate the 'altitude'"""
37
+ cruise_manager = CruiseManager()
38
+ lat, lon = cruise_manager.get_coordinates(
39
+ start_time="2019-10-16T16:20:00",
40
+ end_time="2019-10-16T16:30:00",
41
+ )
42
+ assert np.isclose(lat, 41.48177)
43
+ assert np.isclose(lon, -68.50478)
44
+
45
+
46
+ def test_get_depth():
47
+ """This only gets the depth over the interval, need to calculate the 'altitude'"""
48
+ cruise_manager = CruiseManager()
49
+ depth_value = cruise_manager.get_depth(
50
+ start_time="2019-10-16T16:20:00",
51
+ end_time="2019-10-16T16:50:00",
52
+ )
53
+ assert np.isclose(depth_value, 96.36) # 96.356674
54
+
55
+
56
+ def test_get_altitude():
57
+ """This gets the distance from EVR to the bottom"""
58
+ cruise_manager = CruiseManager()
59
+ altitude_value = cruise_manager.get_altitude(
60
+ start_time="2019-10-16T16:20:00",
61
+ end_time="2019-10-16T16:50:00",
62
+ bbox_max=80.0,
63
+ )
64
+ # bottom is at 96.356674
65
+ # setting the bbox at 80.
66
+ assert np.isclose(altitude_value, 16.36) # 96.356674
67
+
68
+
69
+ def test_get_altitude_nan_bottom():
70
+ """This gets the distance from EVR to the bottom when there are nan values"""
71
+ cruise_manager = CruiseManager()
72
+ altitude_value = cruise_manager.get_altitude(
73
+ start_time="2019-09-26T10:02:39.03",
74
+ end_time="2019-09-26T10:02:40.00",
75
+ bbox_max=10.0,
76
+ )
77
+ assert np.isclose(altitude_value, 0.0)
78
+
79
+
80
+ # get_gps
@@ -0,0 +1,86 @@
1
+ import numpy as np
2
+ import pytest
3
+
4
+ from water_column_sonar_annotation.geospatial import GeospatialManager
5
+
6
+
7
+ #######################################################
8
+ def setup_module():
9
+ print("setup")
10
+
11
+
12
+ def teardown_module():
13
+ print("teardown")
14
+
15
+
16
+ @pytest.fixture
17
+ def process_check_distance_from_coastline(test_path):
18
+ return test_path["DATA_TEST_PATH"]
19
+
20
+
21
+ #######################################################
22
+ def test_check_distance_from_coastline(process_check_distance_from_coastline, tmp_path):
23
+ geospatial_manager = GeospatialManager()
24
+ # Point in middle of atlantic https://wktmap.com/?ab28cbae
25
+ distance = geospatial_manager.check_distance_from_coastline(
26
+ latitude=51.508742,
27
+ longitude=-30.410156,
28
+ shapefile_path=process_check_distance_from_coastline,
29
+ )
30
+ # assert np.isclose(distance, 1_236_212.37356) # 1,200 km
31
+ assert np.isclose(distance, 1_233_910.720702243)
32
+
33
+
34
+ def test_check_distance_from_coastline_woods_hole(
35
+ process_check_distance_from_coastline, tmp_path
36
+ ):
37
+ geospatial_manager = GeospatialManager()
38
+ # Point in middle of woods hole vineyard sound: https://wktmap.com/?9b405aa9
39
+ distance = geospatial_manager.check_distance_from_coastline(
40
+ latitude=41.494692,
41
+ longitude=-70.647926,
42
+ shapefile_path=process_check_distance_from_coastline,
43
+ )
44
+ # The sound is 5 km across
45
+ # assert np.isclose(distance, 4_457.0347) # 4.5 km --> should be 2.5 km?
46
+ assert np.isclose(distance, 3_093) # 3_093.3015 km is close enough
47
+
48
+
49
+ def test_get_local_time():
50
+ geospatial_manager = GeospatialManager()
51
+ local_time = geospatial_manager.get_local_time(
52
+ iso_time="2026-01-26T20:35:00Z",
53
+ latitude=51.508742,
54
+ longitude=-30.410156,
55
+ )
56
+ assert local_time == "2026-01-26T18:35:00-02:00"
57
+
58
+
59
+ def test_get_local_hour_of_day():
60
+ geospatial_manager = GeospatialManager()
61
+ local_hour_of_day = geospatial_manager.get_local_hour_of_day(
62
+ iso_time="2026-01-26T20:35:00Z",
63
+ latitude=51.508742,
64
+ longitude=-30.410156,
65
+ )
66
+ assert local_hour_of_day == 18
67
+
68
+
69
+ def test_get_month_of_year_january():
70
+ geospatial_manager = GeospatialManager()
71
+ month_of_year = geospatial_manager.get_month_of_year(
72
+ iso_time="2026-01-26T20:35:00Z",
73
+ latitude=51.508742,
74
+ longitude=-30.410156,
75
+ )
76
+ assert month_of_year == 1
77
+
78
+
79
+ def test_get_month_of_year_july():
80
+ geospatial_manager = GeospatialManager()
81
+ month_of_year = geospatial_manager.get_month_of_year(
82
+ iso_time="2026-07-13T12:00:00Z",
83
+ latitude=51.508742,
84
+ longitude=-30.410156,
85
+ )
86
+ assert month_of_year == 7