Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Test Coverage and Refactor Test for mslib.utils.coordinate #2596

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
207 changes: 94 additions & 113 deletions tests/_test_utils/test_coordinate.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@
See the License for the specific language governing permissions and
limitations under the License.
"""

import logging
import datetime

import numpy as np
import pytest

Expand All @@ -39,140 +39,127 @@

class TestGetDistance:
"""
tests for distance based calculations
Tests for distance-based calculations in `coordinate` module.
"""
# we don't test the utils method here, may be that method should me refactored off

def test_get_distance(self):
coordinates_distance = [(50.355136, 7.566077, 50.353968, 4.577915, 212),
(-5.135943, -42.792442, 4.606085, 120.028077, 18130)]
for lat0, lon0, lat1, lon1, distance in coordinates_distance:
assert int(coordinate.get_distance(lat0, lon0, lat1, lon1)) == distance

def test_find_location(self):
assert find_location(50.92, 6.36) == ([50.92, 6.36], 'Juelich')
assert find_location(50.9200002, 6.36) == ([50.92, 6.36], 'Juelich')
@pytest.mark.parametrize("lat0, lon0, lat1, lon1, expected_distance", [
(50.355136, 7.566077, 50.353968, 4.577915, 212),
(-5.135943, -42.792442, 4.606085, 120.028077, 18130),
])
def test_get_distance(self, lat0, lon0, lat1, lon1, expected_distance):
"""
Test the calculation of distances between coordinate pairs.
"""
assert int(coordinate.get_distance(lat0, lon0, lat1, lon1)) == expected_distance

@pytest.mark.parametrize("lat, lon, expected_location", [
(50.92, 6.36, ([50.92, 6.36], 'Juelich')),
(50.9200002, 6.36, ([50.92, 6.36], 'Juelich')),
])
def test_find_location(self, lat, lon, expected_location):
"""
Test finding the location from coordinates.
"""
assert find_location(lat, lon) == expected_location


class TestProjections:
"""
Tests for handling coordinate projections.
"""

def test_get_projection_params(self):
"""
Test fetching projection parameters for various EPSG codes.
"""
assert get_projection_params("epsg:4839") == {'basemap': {'epsg': '4839'}, 'bbox': 'meter(10.5,51)'}
with pytest.raises(ValueError):
get_projection_params('auto2:42005')
with pytest.raises(ValueError):
get_projection_params('auto:42001')
with pytest.raises(ValueError):
get_projection_params('crs:83')
for invalid_code in ['auto2:42005', 'auto:42001', 'crs:83']:
with pytest.raises(ValueError):
get_projection_params(invalid_code)


class TestAngles:
"""
tests about angles
Tests for angle normalization and point rotation.
"""

def test_normalize_angle(self):
assert coordinate.fix_angle(0) == 0
assert coordinate.fix_angle(180) == 180
assert coordinate.fix_angle(270) == 270
assert coordinate.fix_angle(-90) == 270
assert coordinate.fix_angle(-180) == 180
assert coordinate.fix_angle(-181) == 179
assert coordinate.fix_angle(420) == 60

def test_rotate_point(self):
assert coordinate.rotate_point([0, 0], 0) == (0.0, 0.0)
assert coordinate.rotate_point([0, 0], 180) == (0.0, 0.0)
assert coordinate.rotate_point([1, 0], 0) == (1.0, 0.0)
assert coordinate.rotate_point([100, 90], 90) == (-90, 100)
@pytest.mark.parametrize("angle, normalized", [
(0, 0),
(180, 180),
(270, 270),
(-90, 270),
(-180, 180),
(-181, 179),
(420, 60),
])
def test_normalize_angle(self, angle, normalized):
"""
Test normalizing angles to the range [0, 360).
"""
assert coordinate.fix_angle(angle) == normalized

@pytest.mark.parametrize("point, angle, rotated_point", [
([0, 0], 0, (0.0, 0.0)),
([0, 0], 180, (0.0, 0.0)),
([1, 0], 0, (1.0, 0.0)),
([100, 90], 90, (-90.0, 100.0)),
saiabhinav001 marked this conversation as resolved.
Show resolved Hide resolved
])
def test_rotate_point(self, point, angle, rotated_point):
"""
Test rotating points around the origin.
"""
assert coordinate.rotate_point(point, angle) == rotated_point


class TestLatLonPoints:
def test_linear(self):
ref_lats = [0, 10]
ref_lons = [0, 0]

lats, lons = coordinate.latlon_points(ref_lats[0], ref_lons[0], ref_lats[1], ref_lons[1],
numpoints=2, connection="linear")
assert len(lats) == len(ref_lats)
assert all(lats == ref_lats)
assert len(lons) == len(ref_lons)
assert all(lons == ref_lons)

lats, lons = coordinate.latlon_points(ref_lats[0], ref_lons[0], ref_lats[1], ref_lons[1],
numpoints=3, connection="linear")
assert len(lats) == 3
assert len(lons) == 3
assert all(lats == [0, 5, 10])

ref_lats = [0, 0]
ref_lons = [0, 10]
lats, lons = coordinate.latlon_points(ref_lats[0], ref_lons[0], ref_lats[1], ref_lons[1],
numpoints=3, connection="linear")
assert len(lats) == 3
assert len(lons) == 3
assert all(lons == [0, 5, 10])

lats, lons = coordinate.latlon_points(ref_lats[0], ref_lons[0], ref_lats[1], ref_lons[1],
numpoints=3, connection="linear")
assert len(lats) == 3
assert len(lons) == 3
assert all(lons == [0, 5, 10])

def test_greatcircle(self):
ref_lats = [0, 10]
ref_lons = [0, 0]

lats, lons = coordinate.latlon_points(ref_lats[0], ref_lons[0], ref_lats[1], ref_lons[1],
numpoints=2, connection="greatcircle")
assert len(lats) == len(ref_lats)
assert lats == ref_lats
assert len(lons) == len(ref_lons)
assert lons == ref_lons
"""
Tests for generating lat/lon points along paths.
"""

@pytest.mark.parametrize("ref_lats, ref_lons, numpoints, connection, expected_lats, expected_lons", [
([0, 10], [0, 0], 2, "linear", [0, 10], [0, 0]),
([0, 10], [0, 0], 3, "linear", [0, 5, 10], [0, 0, 0]),
([0, 0], [0, 10], 3, "linear", [0, 0, 0], [0, 5, 10]),
])
def test_linear(self, ref_lats, ref_lons, numpoints, connection, expected_lats, expected_lons):
"""
Test generating linear lat/lon points.
"""
lats, lons = coordinate.latlon_points(ref_lats[0], ref_lons[0], ref_lats[1], ref_lons[1],
numpoints=3, connection="linear")
assert len(lats) == 3
assert len(lons) == 3
assert all(np.asarray(lats) == [0, 5, 10])

ref_lats = [0, 0]
ref_lons = [0, 10]
numpoints=numpoints, connection=connection)
np.testing.assert_array_equal(lats, expected_lats)
np.testing.assert_array_equal(lons, expected_lons)

@pytest.mark.parametrize("ref_lats, ref_lons, numpoints", [
([0, 10], [0, 0], 2),
([0, 10], [0, 0], 3),
Copy link
Member

@ReimarBauer ReimarBauer Jan 8, 2025

Choose a reason for hiding this comment

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

the second one had before ([0, 0], [0, 10] ,3)

])
def test_greatcircle(self, ref_lats, ref_lons, numpoints):
"""
Test generating lat/lon points along a great circle path.
"""
lats, lons = coordinate.latlon_points(ref_lats[0], ref_lons[0], ref_lats[1], ref_lons[1],
numpoints=3, connection="linear")
assert len(lats) == 3
assert len(lons) == 3
assert all(np.asarray(lons) == [0, 5, 10])
numpoints=numpoints, connection="greatcircle")
assert len(lats) == numpoints
assert len(lons) == numpoints
Copy link
Member

Choose a reason for hiding this comment

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

We should also check for the expected value, like in assert all(np.asarray(lons) == [0, 5, 10])



def test_pathpoints():
"""
Test generating path points with timestamps for different connections.
"""
lats = [0, 10]
lons = [0, 10]
times = [datetime.datetime(2012, 7, 1, 10, 30),
datetime.datetime(2012, 7, 1, 10, 40)]
ref = [lats, lons, times]
result = coordinate.path_points(lats, lons, 100, times=times, connection="linear")
assert all(len(_x) == 100 for _x in result)
for i in range(3):
assert pytest.approx(result[i][0]) == ref[i][0]
assert pytest.approx(result[i][-1]) == ref[i][-1]

result = coordinate.path_points(lats, lons, 100, times=times, connection="greatcircle")
assert all(len(_x) == 100 for _x in result)
for i in range(3):
assert pytest.approx(result[i][0]) == ref[i][0]
assert pytest.approx(result[i][-1]) == ref[i][-1]

result = coordinate.path_points(lats, lons, 200, times=times, connection="linear")
assert all(len(_x) == 200 for _x in result)
for i in range(3):
assert pytest.approx(result[i][0]) == ref[i][0]
assert pytest.approx(result[i][-1]) == ref[i][-1]

result = coordinate.path_points(lats, lons, 200, times=times, connection="greatcircle")
assert all(len(_x) == 200 for _x in result)
for i in range(3):
assert pytest.approx(result[i][0]) == ref[i][0]
assert pytest.approx(result[i][-1]) == ref[i][-1]
for numpoints, connection in [(100, "linear"), (100, "greatcircle"), (200, "linear"), (200, "greatcircle")]:
result = coordinate.path_points(lats, lons, numpoints, times=times, connection=connection)
assert all(len(_x) == numpoints for _x in result)
for i in range(3):
assert pytest.approx(result[i][0]) == ref[i][0]
assert pytest.approx(result[i][-1]) == ref[i][-1]

lats = [0, 10, -20]
lons = [0, 10, 20]
Expand All @@ -182,12 +169,6 @@ def test_pathpoints():
ref = [lats, lons, times]

result = coordinate.path_points(lats, lons, 100, times=times, connection="linear")
assert all([len(_x) == 100 for _x in result])
for i in range(3):
assert pytest.approx(result[i][0]) == ref[i][0]
assert pytest.approx(result[i][-1]) == ref[i][-1]

result = coordinate.path_points(lats, lons, 100, times=times, connection="greatcircle")
assert all(len(_x) == 100 for _x in result)
for i in range(3):
assert pytest.approx(result[i][0]) == ref[i][0]
Expand Down
Loading