Loading knoten/utils.py +139 −16 Original line number Original line Diff line number Diff line import pyproj import pyproj import numpy as np import numpy as np from collections import namedtuple # from collections import namedtuple from typing import NamedTuple def sep_angle(a_pt, b_pt, c_pt): class Point(NamedTuple): return sep_angle(a_pt - b_pt, c_pt - b_pt) x: float y: float z: float class LatLon(NamedTuple): lat: float lon: float class Sphere(NamedTuple): lat: float lon: float radius: float class Matrix(NamedTuple): vec_a: Point vec_b: Point vec_c: Point def sep_angle(a_vec, b_vec): def sep_angle(a_vec, b_vec): """ Parameters ---------- a_vec : Point object (x, y, z) b_vec : Point object (x, y, z) Returns ------- : float """ dot_prod = a_vec.x * b_vec.x + a_vec.y * b_vec.y + a_vec.z * b_vec.z dot_prod = a_vec.x * b_vec.x + a_vec.y * b_vec.y + a_vec.z * b_vec.z dot_prod /= magnitude(a_vec) * magnitude(b_vec) dot_prod /= magnitude(a_vec) * magnitude(b_vec) Loading @@ -15,17 +43,43 @@ def sep_angle(a_vec, b_vec): return np.arccos(dot_prod) return np.arccos(dot_prod) def magnitude(vec): def magnitude(vec): """ Parameters ---------- vec : Point object (x, y, z) Returns ------- : float """ return np.sqrt(vec.x * vec.x + vec.y * vec.y + vec.z * vec.z) return np.sqrt(vec.x * vec.x + vec.y * vec.y + vec.z * vec.z) def distance(start, stop): def distance(start, stop): Point = namedtuple("Point", 'x, y, z') """ Parameters ---------- start : Point object (x, y, z) stop : Point object (x, y, z) Returns ------- : float """ diff = Point(stop.x - start.x, stop.y - start.y, stop.z - start.z) diff = Point(stop.x - start.x, stop.y - start.y, stop.z - start.z) return magnitude(diff) return magnitude(diff) def radiansToDegrees(radian_lat_lon): def radiansToDegrees(radian_lat_lon): LatLon = namedtuple("LatLon", 'lat lon') """ Parameters ---------- radian_lat_lon : LatLon object (lat, lon) in radians Returns ------- : LatLon object (lat, lon) in degrees """ degree_lon = radian_lat_lon.lon degree_lon = radian_lat_lon.lon if (degree_lon < 0): if (degree_lon < 0): degree_lon += 2 * np.pi degree_lon += 2 * np.pi Loading @@ -35,8 +89,15 @@ def radiansToDegrees(radian_lat_lon): return LatLon(degreeLat, degree_lon) return LatLon(degreeLat, degree_lon) def spherical_to_rect(spherical): def spherical_to_rect(spherical): Point = namedtuple("Point", 'x, y, z') """ Parameters ---------- spherical : Sphere object (lat, lon, radius) Returns ------- : Point object (x, y, z) """ x = spherical.radius * np.cos(spherical.lat) * np.cos(spherical.lon) x = spherical.radius * np.cos(spherical.lat) * np.cos(spherical.lon) y = spherical.radius * np.cos(spherical.lat) * np.sin(spherical.lon) y = spherical.radius * np.cos(spherical.lat) * np.sin(spherical.lon) z = spherical.radius * np.sin(spherical.lat) z = spherical.radius * np.sin(spherical.lat) Loading @@ -44,8 +105,15 @@ def spherical_to_rect(spherical): return Point(x, y, z) return Point(x, y, z) def rect_to_spherical(rectangular): def rect_to_spherical(rectangular): Sphere = namedtuple("Sphere", 'lat, lon, radius') """ Parameters ---------- rectangular : Point object (x, y, z) Returns ------- : Sphere object (lat, lon, radius) """ rad = magnitude(rectangular) rad = magnitude(rectangular) if (rad < 1e-15): if (rad < 1e-15): return Sphere(0.0, 0.0, 0.0) return Sphere(0.0, 0.0, 0.0) Loading @@ -57,8 +125,17 @@ def rect_to_spherical(rectangular): ) ) def ground_azimuth(ground_pt, sub_pt): def ground_azimuth(ground_pt, sub_pt): LatLon = namedtuple("LatLon", 'lat lon') """ Parameters ---------- ground_pt : LatLon object (lat, lon) sub_pt : LatLon object (lat, lon) Returns ------- : float """ if (ground_pt.lat >= 0.0): if (ground_pt.lat >= 0.0): a = (90.0 - sub_pt.lat) * np.pi / 180.0 a = (90.0 - sub_pt.lat) * np.pi / 180.0 b = (90.0 - ground_pt.lat) * np.pi / 180.0 b = (90.0 - ground_pt.lat) * np.pi / 180.0 Loading Loading @@ -128,19 +205,47 @@ def ground_azimuth(ground_pt, sub_pt): return azimuth return azimuth def crossProduct(a_vec, b_vec): def crossProduct(a_vec, b_vec): Point = namedtuple("Point", 'x, y, z') """ Parameters ---------- a_vec : Point object (x, y, z) b_vec : Point object (x, y, z) Returns ------- : Point object (x, y, z) """ x = a_vec.y * b_vec.z - a_vec.z * b_vec.y x = a_vec.y * b_vec.z - a_vec.z * b_vec.y y = a_vec.z * b_vec.x - a_vec.x * b_vec.z y = a_vec.z * b_vec.x - a_vec.x * b_vec.z z = a_vec.x * b_vec.y - a_vec.y * b_vec.x z = a_vec.x * b_vec.y - a_vec.y * b_vec.x return Point(x, y, z) return Point(x, y, z) def unit_vector(vec): def unit_vector(vec): """ Parameters ---------- vec : Point object (x, y, z) Returns ------- : Point object (x, y, z) """ mag = magnitude(vec) mag = magnitude(vec) return vec / mag return vec / mag def perpendicular_vector(a_vec, b_vec): def perpendicular_vector(a_vec, b_vec): """ Parameters ---------- a_vec : Point object (x, y, z) b_vec : Point object (x, y, z) Returns ------- : Point object (x, y, z) """ if (magnitude(a_vec) == 0): if (magnitude(a_vec) == 0): return b_vec return b_vec Loading @@ -157,16 +262,34 @@ def perpendicular_vector(a_vec, b_vec): return q return q def scale_vector(vec, scalar): def scale_vector(vec, scalar): Point = namedtuple("Point", 'x, y, z') """ Parameters ---------- vec : Point object (x, y, z) scalar : float Returns ------- : Point object (x, y, z) """ return Point(vec.x * scalar, vec.y * scalar, vec.z * scalar) return Point(vec.x * scalar, vec.y * scalar, vec.z * scalar) def matrixVecProduct(mat, vec): def matrix_vec_product(mat, vec): Point = namedtuple("Point", 'x, y, z') """ Parameters ---------- mat : Matrix object (vec_a, vec_b, vec_c) vec : Point object (x, y, z) x = mat.a.x * vec.x + mat.a.y * vec.y + mat.a.z * vec.z Returns y = mat.b.x * vec.x + mat.b.y * vec.y + mat.b.z * vec.z ------- z = mat.c.x * vec.x + mat.c.y * vec.y + mat.c.z * vec.z : Point object (x, y, z) """ x = mat.vec_a.x * vec.x + mat.vec_a.y * vec.y + mat.vec_a.z * vec.z y = mat.vec_b.x * vec.x + mat.vec_b.y * vec.y + mat.vec_b.z * vec.z z = mat.vec_c.x * vec.x + mat.vec_c.y * vec.y + mat.vec_c.z * vec.z return Point(x, y, z) return Point(x, y, z) Loading tests/test_utils.py +48 −44 Original line number Original line Diff line number Diff line import numpy as np import numpy as np from knoten import utils from knoten import utils from collections import namedtuple Point = namedtuple("Point", 'x, y, z') Sphere = namedtuple("Sphere", 'lat, lon, radius') def test_sep_angle_right(): def test_sep_angle_right(): pt1 = Point(1, 0, 0) pt1 = utils.Point(1, 0, 0) pt2 = Point(0, 1, 0) pt2 = utils.Point(0, 1, 0) np.testing.assert_array_equal(utils.sep_angle(pt1, pt2), np.pi / 2.0) np.testing.assert_array_equal(utils.sep_angle(pt1, pt2), np.pi / 2.0) def test_sep_angle_acute(): def test_sep_angle_acute(): pt1 = Point(1, 0, 0) pt1 = utils.Point(1, 0, 0) pt2 = Point(1, 1, 0) pt2 = utils.Point(1, 1, 0) np.testing.assert_allclose(utils.sep_angle(pt1, pt2), np.pi / 4.0, atol=1e-12) np.testing.assert_allclose(utils.sep_angle(pt1, pt2), np.pi / 4.0, atol=1e-12) def test_sep_angle_obtuse(): def test_sep_angle_obtuse(): pt1 = Point(1, 0, 0) pt1 = utils.Point(1, 0, 0) pt2 = Point(-1, 1, 0) pt2 = utils.Point(-1, 1, 0) np.testing.assert_array_equal(utils.sep_angle(pt1, pt2), 3.0 * np.pi / 4.0) np.testing.assert_array_equal(utils.sep_angle(pt1, pt2), 3.0 * np.pi / 4.0) def test_sep_angle_normalization(): def test_sep_angle_normalization(): pt1 = Point(1, 0, 0) pt1 = utils.Point(1, 0, 0) pt2 = Point(1, 1, 0) pt2 = utils.Point(1, 1, 0) pt3 = Point(100, 0, 0) pt3 = utils.Point(100, 0, 0) pt4 = Point(100, 100, 0) pt4 = utils.Point(100, 100, 0) np.testing.assert_array_equal(utils.sep_angle(pt1, pt2), utils.sep_angle(pt3, pt4)) np.testing.assert_array_equal(utils.sep_angle(pt1, pt2), utils.sep_angle(pt3, pt4)) def test_magnitude_unit(): def test_magnitude_unit(): assert utils.magnitude(Point(1.0, 0.0, 0.0)) == 1.0 assert utils.magnitude(utils.Point(1.0, 0.0, 0.0)) == 1.0 assert utils.magnitude(Point(0.0, 1.0, 0.0)) == 1.0 assert utils.magnitude(utils.Point(0.0, 1.0, 0.0)) == 1.0 assert utils.magnitude(Point(0.0, 0.0, 1.0)) == 1.0 assert utils.magnitude(utils.Point(0.0, 0.0, 1.0)) == 1.0 def test_magnitude_nonunit(): def test_magnitude_nonunit(): assert utils.magnitude(Point(0.0, 0.0, 0.0)) == 0.0 assert utils.magnitude(utils.Point(0.0, 0.0, 0.0)) == 0.0 assert utils.magnitude(Point(2.0, 1.0, 4.0)) == np.sqrt(21.0) assert utils.magnitude(utils.Point(2.0, 1.0, 4.0)) == np.sqrt(21.0) np.testing.assert_allclose(utils.magnitude(Point(0.2, 0.1, 0.4)), np.sqrt(0.21), atol=1e-12) np.testing.assert_allclose(utils.magnitude(utils.Point(0.2, 0.1, 0.4)), np.sqrt(0.21), atol=1e-12) def test_distance(): def test_distance(): assert utils.distance(Point(1.0, 2.0, 3.0), Point(6.0, 5.0, 4.0)) == np.sqrt(35) assert utils.distance(utils.Point(1.0, 2.0, 3.0), utils.Point(6.0, 5.0, 4.0)) == np.sqrt(35) def test_spherical_to_rect(): def test_spherical_to_rect(): result = utils.spherical_to_rect(Sphere(0.0, 0.0, 1000.0)) result = utils.spherical_to_rect(utils.Sphere(0.0, 0.0, 1000.0)) np.testing.assert_allclose(result.x, 1000.0, atol=1e-12) np.testing.assert_allclose(result.x, 1000.0, atol=1e-12) np.testing.assert_allclose(result.y, 0.0, atol=1e-12) np.testing.assert_allclose(result.y, 0.0, atol=1e-12) np.testing.assert_allclose(result.z, 0.0, atol=1e-12) np.testing.assert_allclose(result.z, 0.0, atol=1e-12) result = utils.spherical_to_rect(Sphere(0.0, np.pi, 1000.0)) result = utils.spherical_to_rect(utils.Sphere(0.0, np.pi, 1000.0)) np.testing.assert_allclose( result.x, -1000.0, atol=1e-12) np.testing.assert_allclose( result.x, -1000.0, atol=1e-12) np.testing.assert_allclose( result.y, 0.0, atol=1e-12) np.testing.assert_allclose( result.y, 0.0, atol=1e-12) np.testing.assert_allclose( result.z, 0.0, atol=1e-12) np.testing.assert_allclose( result.z, 0.0, atol=1e-12) result = utils.spherical_to_rect(Sphere(np.pi / 2.0, 0.0, 1000.0)) result = utils.spherical_to_rect(utils.Sphere(np.pi / 2.0, 0.0, 1000.0)) np.testing.assert_allclose( result.x, 0.0, atol=1e-12) np.testing.assert_allclose( result.x, 0.0, atol=1e-12) np.testing.assert_allclose( result.y, 0.0, atol=1e-12) np.testing.assert_allclose( result.y, 0.0, atol=1e-12) np.testing.assert_allclose( result.z, 1000.0, atol=1e-12) np.testing.assert_allclose( result.z, 1000.0, atol=1e-12) result = utils.spherical_to_rect(Sphere(np.pi / -2.0, 0.0, 1000.0)) result = utils.spherical_to_rect(utils.Sphere(np.pi / -2.0, 0.0, 1000.0)) np.testing.assert_allclose( result.x, 0.0, atol=1e-12) np.testing.assert_allclose( result.x, 0.0, atol=1e-12) np.testing.assert_allclose( result.y, 0.0, atol=1e-12) np.testing.assert_allclose( result.y, 0.0, atol=1e-12) np.testing.assert_allclose( result.z, -1000.0, atol=1e-12) np.testing.assert_allclose( result.z, -1000.0, atol=1e-12) def test_rect_to_spherical(): def test_rect_to_spherical(): result = utils.rect_to_spherical(Point(1000.0, 0.0, 0.0)) result = utils.rect_to_spherical(utils.Point(1000.0, 0.0, 0.0)) np.testing.assert_array_equal(result, Sphere(0.0, 0.0, 1000.0)) np.testing.assert_array_equal(result, utils.Sphere(0.0, 0.0, 1000.0)) result = utils.rect_to_spherical(Point(-1000.0, 0.0, 0.0)) result = utils.rect_to_spherical(utils.Point(-1000.0, 0.0, 0.0)) np.testing.assert_array_equal(result, Sphere(0.0, np.pi, 1000.0)) np.testing.assert_array_equal(result, utils.Sphere(0.0, np.pi, 1000.0)) result = utils.rect_to_spherical(Point(0.0, 0.0, 1000.0)) result = utils.rect_to_spherical(utils.Point(0.0, 0.0, 1000.0)) np.testing.assert_array_equal(result, Sphere(np.pi / 2.0, 0.0, 1000.0)) np.testing.assert_array_equal(result, utils.Sphere(np.pi / 2.0, 0.0, 1000.0)) result = utils.rect_to_spherical(Point(0.0, 0.0, -1000.0)) result = utils.rect_to_spherical(utils.Point(0.0, 0.0, -1000.0)) np.testing.assert_array_equal(result, Sphere(np.pi / -2.0, 0.0, 1000.0)) np.testing.assert_array_equal(result, utils.Sphere(np.pi / -2.0, 0.0, 1000.0)) def test_ground_azimuth(): def test_ground_azimuth(): LatLon = namedtuple("LatLon", "lat lon") ground_pt = utils.LatLon(0, -180) subsolar_pt = utils.LatLon(0, 90) ground_pt = LatLon(0, -180) subsolar_pt = LatLon(0, 90) np.testing.assert_array_equal(270.0, utils.ground_azimuth(ground_pt, subsolar_pt)) np.testing.assert_array_equal(270.0, utils.ground_azimuth(ground_pt, subsolar_pt)) def test_perpendicular_vector(): def test_perpendicular_vector(): vec_a = Point(6.0, 6.0, 6.0) vec_a = utils.Point(6.0, 6.0, 6.0) vec_b = Point(2.0, 0.0, 0.0) vec_b = utils.Point(2.0, 0.0, 0.0) result = Point(0.0, 6.0, 6.0) result = utils.Point(0.0, 6.0, 6.0) np.testing.assert_array_equal(utils.perpendicular_vector(vec_a, vec_b), result) np.testing.assert_array_equal(utils.perpendicular_vector(vec_a, vec_b), result) def test_unit_vector(): def test_unit_vector(): result = utils.unit_vector(Point(5.0, 12.0, 0.0)) result = utils.unit_vector(utils.Point(5.0, 12.0, 0.0)) np.testing.assert_allclose(result[0], 0.384615, atol=1e-6) np.testing.assert_allclose(result[0], 0.384615, atol=1e-6) np.testing.assert_allclose(result[1], 0.923077, atol=1e-6) np.testing.assert_allclose(result[1], 0.923077, atol=1e-6) np.testing.assert_array_equal(result[2], 0.0) np.testing.assert_array_equal(result[2], 0.0) def test_scale_vector(): def test_scale_vector(): vec = Point(1.0, 2.0, -3.0) vec = utils.Point(1.0, 2.0, -3.0) scalar = 3.0 scalar = 3.0 result = Point(3.0, 6.0, -9.0) result = utils.Point(3.0, 6.0, -9.0) np.testing.assert_array_equal(utils.scale_vector(vec, scalar), result) np.testing.assert_array_equal(utils.scale_vector(vec, scalar), result) def test_matrix_vec_product(): vec_a = utils.Point(0.0, 1.0, 0.0) vec_b = utils.Point(-1.0, 0.0, 0.0) vec_c = utils.Point(0.0, 0.0, 1.0) mat = utils.Matrix(vec_a, vec_b, vec_c) vec = utils.Point(1.0, 2.0, 3.0) result = utils.Point(2.0, -1.0, 3.0) np.testing.assert_array_equal(result, utils.matrix_vec_product(mat, vec)) No newline at end of file Loading
knoten/utils.py +139 −16 Original line number Original line Diff line number Diff line import pyproj import pyproj import numpy as np import numpy as np from collections import namedtuple # from collections import namedtuple from typing import NamedTuple def sep_angle(a_pt, b_pt, c_pt): class Point(NamedTuple): return sep_angle(a_pt - b_pt, c_pt - b_pt) x: float y: float z: float class LatLon(NamedTuple): lat: float lon: float class Sphere(NamedTuple): lat: float lon: float radius: float class Matrix(NamedTuple): vec_a: Point vec_b: Point vec_c: Point def sep_angle(a_vec, b_vec): def sep_angle(a_vec, b_vec): """ Parameters ---------- a_vec : Point object (x, y, z) b_vec : Point object (x, y, z) Returns ------- : float """ dot_prod = a_vec.x * b_vec.x + a_vec.y * b_vec.y + a_vec.z * b_vec.z dot_prod = a_vec.x * b_vec.x + a_vec.y * b_vec.y + a_vec.z * b_vec.z dot_prod /= magnitude(a_vec) * magnitude(b_vec) dot_prod /= magnitude(a_vec) * magnitude(b_vec) Loading @@ -15,17 +43,43 @@ def sep_angle(a_vec, b_vec): return np.arccos(dot_prod) return np.arccos(dot_prod) def magnitude(vec): def magnitude(vec): """ Parameters ---------- vec : Point object (x, y, z) Returns ------- : float """ return np.sqrt(vec.x * vec.x + vec.y * vec.y + vec.z * vec.z) return np.sqrt(vec.x * vec.x + vec.y * vec.y + vec.z * vec.z) def distance(start, stop): def distance(start, stop): Point = namedtuple("Point", 'x, y, z') """ Parameters ---------- start : Point object (x, y, z) stop : Point object (x, y, z) Returns ------- : float """ diff = Point(stop.x - start.x, stop.y - start.y, stop.z - start.z) diff = Point(stop.x - start.x, stop.y - start.y, stop.z - start.z) return magnitude(diff) return magnitude(diff) def radiansToDegrees(radian_lat_lon): def radiansToDegrees(radian_lat_lon): LatLon = namedtuple("LatLon", 'lat lon') """ Parameters ---------- radian_lat_lon : LatLon object (lat, lon) in radians Returns ------- : LatLon object (lat, lon) in degrees """ degree_lon = radian_lat_lon.lon degree_lon = radian_lat_lon.lon if (degree_lon < 0): if (degree_lon < 0): degree_lon += 2 * np.pi degree_lon += 2 * np.pi Loading @@ -35,8 +89,15 @@ def radiansToDegrees(radian_lat_lon): return LatLon(degreeLat, degree_lon) return LatLon(degreeLat, degree_lon) def spherical_to_rect(spherical): def spherical_to_rect(spherical): Point = namedtuple("Point", 'x, y, z') """ Parameters ---------- spherical : Sphere object (lat, lon, radius) Returns ------- : Point object (x, y, z) """ x = spherical.radius * np.cos(spherical.lat) * np.cos(spherical.lon) x = spherical.radius * np.cos(spherical.lat) * np.cos(spherical.lon) y = spherical.radius * np.cos(spherical.lat) * np.sin(spherical.lon) y = spherical.radius * np.cos(spherical.lat) * np.sin(spherical.lon) z = spherical.radius * np.sin(spherical.lat) z = spherical.radius * np.sin(spherical.lat) Loading @@ -44,8 +105,15 @@ def spherical_to_rect(spherical): return Point(x, y, z) return Point(x, y, z) def rect_to_spherical(rectangular): def rect_to_spherical(rectangular): Sphere = namedtuple("Sphere", 'lat, lon, radius') """ Parameters ---------- rectangular : Point object (x, y, z) Returns ------- : Sphere object (lat, lon, radius) """ rad = magnitude(rectangular) rad = magnitude(rectangular) if (rad < 1e-15): if (rad < 1e-15): return Sphere(0.0, 0.0, 0.0) return Sphere(0.0, 0.0, 0.0) Loading @@ -57,8 +125,17 @@ def rect_to_spherical(rectangular): ) ) def ground_azimuth(ground_pt, sub_pt): def ground_azimuth(ground_pt, sub_pt): LatLon = namedtuple("LatLon", 'lat lon') """ Parameters ---------- ground_pt : LatLon object (lat, lon) sub_pt : LatLon object (lat, lon) Returns ------- : float """ if (ground_pt.lat >= 0.0): if (ground_pt.lat >= 0.0): a = (90.0 - sub_pt.lat) * np.pi / 180.0 a = (90.0 - sub_pt.lat) * np.pi / 180.0 b = (90.0 - ground_pt.lat) * np.pi / 180.0 b = (90.0 - ground_pt.lat) * np.pi / 180.0 Loading Loading @@ -128,19 +205,47 @@ def ground_azimuth(ground_pt, sub_pt): return azimuth return azimuth def crossProduct(a_vec, b_vec): def crossProduct(a_vec, b_vec): Point = namedtuple("Point", 'x, y, z') """ Parameters ---------- a_vec : Point object (x, y, z) b_vec : Point object (x, y, z) Returns ------- : Point object (x, y, z) """ x = a_vec.y * b_vec.z - a_vec.z * b_vec.y x = a_vec.y * b_vec.z - a_vec.z * b_vec.y y = a_vec.z * b_vec.x - a_vec.x * b_vec.z y = a_vec.z * b_vec.x - a_vec.x * b_vec.z z = a_vec.x * b_vec.y - a_vec.y * b_vec.x z = a_vec.x * b_vec.y - a_vec.y * b_vec.x return Point(x, y, z) return Point(x, y, z) def unit_vector(vec): def unit_vector(vec): """ Parameters ---------- vec : Point object (x, y, z) Returns ------- : Point object (x, y, z) """ mag = magnitude(vec) mag = magnitude(vec) return vec / mag return vec / mag def perpendicular_vector(a_vec, b_vec): def perpendicular_vector(a_vec, b_vec): """ Parameters ---------- a_vec : Point object (x, y, z) b_vec : Point object (x, y, z) Returns ------- : Point object (x, y, z) """ if (magnitude(a_vec) == 0): if (magnitude(a_vec) == 0): return b_vec return b_vec Loading @@ -157,16 +262,34 @@ def perpendicular_vector(a_vec, b_vec): return q return q def scale_vector(vec, scalar): def scale_vector(vec, scalar): Point = namedtuple("Point", 'x, y, z') """ Parameters ---------- vec : Point object (x, y, z) scalar : float Returns ------- : Point object (x, y, z) """ return Point(vec.x * scalar, vec.y * scalar, vec.z * scalar) return Point(vec.x * scalar, vec.y * scalar, vec.z * scalar) def matrixVecProduct(mat, vec): def matrix_vec_product(mat, vec): Point = namedtuple("Point", 'x, y, z') """ Parameters ---------- mat : Matrix object (vec_a, vec_b, vec_c) vec : Point object (x, y, z) x = mat.a.x * vec.x + mat.a.y * vec.y + mat.a.z * vec.z Returns y = mat.b.x * vec.x + mat.b.y * vec.y + mat.b.z * vec.z ------- z = mat.c.x * vec.x + mat.c.y * vec.y + mat.c.z * vec.z : Point object (x, y, z) """ x = mat.vec_a.x * vec.x + mat.vec_a.y * vec.y + mat.vec_a.z * vec.z y = mat.vec_b.x * vec.x + mat.vec_b.y * vec.y + mat.vec_b.z * vec.z z = mat.vec_c.x * vec.x + mat.vec_c.y * vec.y + mat.vec_c.z * vec.z return Point(x, y, z) return Point(x, y, z) Loading
tests/test_utils.py +48 −44 Original line number Original line Diff line number Diff line import numpy as np import numpy as np from knoten import utils from knoten import utils from collections import namedtuple Point = namedtuple("Point", 'x, y, z') Sphere = namedtuple("Sphere", 'lat, lon, radius') def test_sep_angle_right(): def test_sep_angle_right(): pt1 = Point(1, 0, 0) pt1 = utils.Point(1, 0, 0) pt2 = Point(0, 1, 0) pt2 = utils.Point(0, 1, 0) np.testing.assert_array_equal(utils.sep_angle(pt1, pt2), np.pi / 2.0) np.testing.assert_array_equal(utils.sep_angle(pt1, pt2), np.pi / 2.0) def test_sep_angle_acute(): def test_sep_angle_acute(): pt1 = Point(1, 0, 0) pt1 = utils.Point(1, 0, 0) pt2 = Point(1, 1, 0) pt2 = utils.Point(1, 1, 0) np.testing.assert_allclose(utils.sep_angle(pt1, pt2), np.pi / 4.0, atol=1e-12) np.testing.assert_allclose(utils.sep_angle(pt1, pt2), np.pi / 4.0, atol=1e-12) def test_sep_angle_obtuse(): def test_sep_angle_obtuse(): pt1 = Point(1, 0, 0) pt1 = utils.Point(1, 0, 0) pt2 = Point(-1, 1, 0) pt2 = utils.Point(-1, 1, 0) np.testing.assert_array_equal(utils.sep_angle(pt1, pt2), 3.0 * np.pi / 4.0) np.testing.assert_array_equal(utils.sep_angle(pt1, pt2), 3.0 * np.pi / 4.0) def test_sep_angle_normalization(): def test_sep_angle_normalization(): pt1 = Point(1, 0, 0) pt1 = utils.Point(1, 0, 0) pt2 = Point(1, 1, 0) pt2 = utils.Point(1, 1, 0) pt3 = Point(100, 0, 0) pt3 = utils.Point(100, 0, 0) pt4 = Point(100, 100, 0) pt4 = utils.Point(100, 100, 0) np.testing.assert_array_equal(utils.sep_angle(pt1, pt2), utils.sep_angle(pt3, pt4)) np.testing.assert_array_equal(utils.sep_angle(pt1, pt2), utils.sep_angle(pt3, pt4)) def test_magnitude_unit(): def test_magnitude_unit(): assert utils.magnitude(Point(1.0, 0.0, 0.0)) == 1.0 assert utils.magnitude(utils.Point(1.0, 0.0, 0.0)) == 1.0 assert utils.magnitude(Point(0.0, 1.0, 0.0)) == 1.0 assert utils.magnitude(utils.Point(0.0, 1.0, 0.0)) == 1.0 assert utils.magnitude(Point(0.0, 0.0, 1.0)) == 1.0 assert utils.magnitude(utils.Point(0.0, 0.0, 1.0)) == 1.0 def test_magnitude_nonunit(): def test_magnitude_nonunit(): assert utils.magnitude(Point(0.0, 0.0, 0.0)) == 0.0 assert utils.magnitude(utils.Point(0.0, 0.0, 0.0)) == 0.0 assert utils.magnitude(Point(2.0, 1.0, 4.0)) == np.sqrt(21.0) assert utils.magnitude(utils.Point(2.0, 1.0, 4.0)) == np.sqrt(21.0) np.testing.assert_allclose(utils.magnitude(Point(0.2, 0.1, 0.4)), np.sqrt(0.21), atol=1e-12) np.testing.assert_allclose(utils.magnitude(utils.Point(0.2, 0.1, 0.4)), np.sqrt(0.21), atol=1e-12) def test_distance(): def test_distance(): assert utils.distance(Point(1.0, 2.0, 3.0), Point(6.0, 5.0, 4.0)) == np.sqrt(35) assert utils.distance(utils.Point(1.0, 2.0, 3.0), utils.Point(6.0, 5.0, 4.0)) == np.sqrt(35) def test_spherical_to_rect(): def test_spherical_to_rect(): result = utils.spherical_to_rect(Sphere(0.0, 0.0, 1000.0)) result = utils.spherical_to_rect(utils.Sphere(0.0, 0.0, 1000.0)) np.testing.assert_allclose(result.x, 1000.0, atol=1e-12) np.testing.assert_allclose(result.x, 1000.0, atol=1e-12) np.testing.assert_allclose(result.y, 0.0, atol=1e-12) np.testing.assert_allclose(result.y, 0.0, atol=1e-12) np.testing.assert_allclose(result.z, 0.0, atol=1e-12) np.testing.assert_allclose(result.z, 0.0, atol=1e-12) result = utils.spherical_to_rect(Sphere(0.0, np.pi, 1000.0)) result = utils.spherical_to_rect(utils.Sphere(0.0, np.pi, 1000.0)) np.testing.assert_allclose( result.x, -1000.0, atol=1e-12) np.testing.assert_allclose( result.x, -1000.0, atol=1e-12) np.testing.assert_allclose( result.y, 0.0, atol=1e-12) np.testing.assert_allclose( result.y, 0.0, atol=1e-12) np.testing.assert_allclose( result.z, 0.0, atol=1e-12) np.testing.assert_allclose( result.z, 0.0, atol=1e-12) result = utils.spherical_to_rect(Sphere(np.pi / 2.0, 0.0, 1000.0)) result = utils.spherical_to_rect(utils.Sphere(np.pi / 2.0, 0.0, 1000.0)) np.testing.assert_allclose( result.x, 0.0, atol=1e-12) np.testing.assert_allclose( result.x, 0.0, atol=1e-12) np.testing.assert_allclose( result.y, 0.0, atol=1e-12) np.testing.assert_allclose( result.y, 0.0, atol=1e-12) np.testing.assert_allclose( result.z, 1000.0, atol=1e-12) np.testing.assert_allclose( result.z, 1000.0, atol=1e-12) result = utils.spherical_to_rect(Sphere(np.pi / -2.0, 0.0, 1000.0)) result = utils.spherical_to_rect(utils.Sphere(np.pi / -2.0, 0.0, 1000.0)) np.testing.assert_allclose( result.x, 0.0, atol=1e-12) np.testing.assert_allclose( result.x, 0.0, atol=1e-12) np.testing.assert_allclose( result.y, 0.0, atol=1e-12) np.testing.assert_allclose( result.y, 0.0, atol=1e-12) np.testing.assert_allclose( result.z, -1000.0, atol=1e-12) np.testing.assert_allclose( result.z, -1000.0, atol=1e-12) def test_rect_to_spherical(): def test_rect_to_spherical(): result = utils.rect_to_spherical(Point(1000.0, 0.0, 0.0)) result = utils.rect_to_spherical(utils.Point(1000.0, 0.0, 0.0)) np.testing.assert_array_equal(result, Sphere(0.0, 0.0, 1000.0)) np.testing.assert_array_equal(result, utils.Sphere(0.0, 0.0, 1000.0)) result = utils.rect_to_spherical(Point(-1000.0, 0.0, 0.0)) result = utils.rect_to_spherical(utils.Point(-1000.0, 0.0, 0.0)) np.testing.assert_array_equal(result, Sphere(0.0, np.pi, 1000.0)) np.testing.assert_array_equal(result, utils.Sphere(0.0, np.pi, 1000.0)) result = utils.rect_to_spherical(Point(0.0, 0.0, 1000.0)) result = utils.rect_to_spherical(utils.Point(0.0, 0.0, 1000.0)) np.testing.assert_array_equal(result, Sphere(np.pi / 2.0, 0.0, 1000.0)) np.testing.assert_array_equal(result, utils.Sphere(np.pi / 2.0, 0.0, 1000.0)) result = utils.rect_to_spherical(Point(0.0, 0.0, -1000.0)) result = utils.rect_to_spherical(utils.Point(0.0, 0.0, -1000.0)) np.testing.assert_array_equal(result, Sphere(np.pi / -2.0, 0.0, 1000.0)) np.testing.assert_array_equal(result, utils.Sphere(np.pi / -2.0, 0.0, 1000.0)) def test_ground_azimuth(): def test_ground_azimuth(): LatLon = namedtuple("LatLon", "lat lon") ground_pt = utils.LatLon(0, -180) subsolar_pt = utils.LatLon(0, 90) ground_pt = LatLon(0, -180) subsolar_pt = LatLon(0, 90) np.testing.assert_array_equal(270.0, utils.ground_azimuth(ground_pt, subsolar_pt)) np.testing.assert_array_equal(270.0, utils.ground_azimuth(ground_pt, subsolar_pt)) def test_perpendicular_vector(): def test_perpendicular_vector(): vec_a = Point(6.0, 6.0, 6.0) vec_a = utils.Point(6.0, 6.0, 6.0) vec_b = Point(2.0, 0.0, 0.0) vec_b = utils.Point(2.0, 0.0, 0.0) result = Point(0.0, 6.0, 6.0) result = utils.Point(0.0, 6.0, 6.0) np.testing.assert_array_equal(utils.perpendicular_vector(vec_a, vec_b), result) np.testing.assert_array_equal(utils.perpendicular_vector(vec_a, vec_b), result) def test_unit_vector(): def test_unit_vector(): result = utils.unit_vector(Point(5.0, 12.0, 0.0)) result = utils.unit_vector(utils.Point(5.0, 12.0, 0.0)) np.testing.assert_allclose(result[0], 0.384615, atol=1e-6) np.testing.assert_allclose(result[0], 0.384615, atol=1e-6) np.testing.assert_allclose(result[1], 0.923077, atol=1e-6) np.testing.assert_allclose(result[1], 0.923077, atol=1e-6) np.testing.assert_array_equal(result[2], 0.0) np.testing.assert_array_equal(result[2], 0.0) def test_scale_vector(): def test_scale_vector(): vec = Point(1.0, 2.0, -3.0) vec = utils.Point(1.0, 2.0, -3.0) scalar = 3.0 scalar = 3.0 result = Point(3.0, 6.0, -9.0) result = utils.Point(3.0, 6.0, -9.0) np.testing.assert_array_equal(utils.scale_vector(vec, scalar), result) np.testing.assert_array_equal(utils.scale_vector(vec, scalar), result) def test_matrix_vec_product(): vec_a = utils.Point(0.0, 1.0, 0.0) vec_b = utils.Point(-1.0, 0.0, 0.0) vec_c = utils.Point(0.0, 0.0, 1.0) mat = utils.Matrix(vec_a, vec_b, vec_c) vec = utils.Point(1.0, 2.0, 3.0) result = utils.Point(2.0, -1.0, 3.0) np.testing.assert_array_equal(result, utils.matrix_vec_product(mat, vec)) No newline at end of file