133 lines
6.0 KiB
Python

"""
Tests the transformers in :mod:`pyrate.common.raster_datasets.transformer_base` and in
:mod:`pyrate.common.raster_datasets.transformers_concrete`.
"""
# Testing
from unittest import TestCase
# Scientific
from numpy import array
from numpy import empty
from numpy import float32
from numpy import int16
from numpy.testing import assert_array_equal
from numpy import uint16
from numpy import uint32
from pandas import DataFrame
from pandas import Series
from pandas.testing import assert_frame_equal
from pandas.testing import assert_series_equal
# Module under test
from pyrate.common.raster_datasets.transformers_concrete import BathymetricTransformer
from pyrate.common.raster_datasets.transformers_concrete import ConstantTransformer
# Graph generation
from pyrate.plan.graph import create_earth_graph
from pyrate.plan.graph import GeoNavigationGraph
from pyrate.plan.graph import min_required_frequency
# CI/Testing helpers
from ... import _open_test_geo_dataset
class TestGetNodePropertiesWithConstantTransformer(TestCase):
"""Ensure that the :meth:`pyrate.plan.graph.GeoNavigationGraph.append_properties` works correctly."""
def test_get_node_properties_empty_coordinates(self) -> None:
"""Tests getting properties for a graph without nodes."""
graph = GeoNavigationGraph.from_coordinates_degrees(
latitudes=empty((0,)), longitudes=empty((0,)), edges=empty((0, 2)), node_radius=111.111
)
transformers = [ConstantTransformer(42, uint32, "prop_1"), ConstantTransformer(43, uint16, "prop_2")]
graph.append_properties(transformers)
self.assertEqual(len(graph.node_properties), 0)
assert_array_equal(graph.node_properties.columns, ["prop_1", "prop_2"])
def test_get_node_properties_no_transformers(self) -> None:
"""Tests getting properties without a transformer."""
graph = GeoNavigationGraph.from_coordinates_degrees(
latitudes=array([0, 1]), longitudes=array([0, 0]), edges=array([[0, 1]]), node_radius=111.111
)
graph.append_properties([]) # empty!
self.assertEqual(len(graph.node_properties), 2)
assert_array_equal(graph.node_properties.columns, [])
def test_get_node_properties_single_transformer(self) -> None:
"""Tests getting properties using only a single transformer."""
graph = GeoNavigationGraph.from_coordinates_degrees(
latitudes=array([0, 1]),
longitudes=array([0, 0]),
edges=array([[0, 1]]),
node_radius=0.0, # some weird radius
)
# now we use `append_property` to append a single one
graph.append_property(ConstantTransformer(33, uint32, "prop_1"))
self.assertEqual(len(graph.node_properties), 2)
assert_frame_equal(graph.node_properties, DataFrame(data={"prop_1": [33, 33]}, dtype=uint32))
def test_get_node_properties_single_transformer_str_datatype(self) -> None:
"""Tests getting properties using only a single transformer and a string datatype."""
graph = GeoNavigationGraph.from_coordinates_degrees(
latitudes=array([0]),
longitudes=array([0]),
edges=array([[0, 0]]), # edge to itself
node_radius=111.111,
)
# now we use `append_property` to append a single one
data_type = "U10" # must give string data type explicitly and not with np.str or "U"
graph.append_property(ConstantTransformer("content", data_type, "prop_1"))
self.assertEqual(len(graph.node_properties), 1)
assert_frame_equal(graph.node_properties, DataFrame(data={"prop_1": ["content"]}, dtype=data_type))
def test_get_node_properties_multiple_transformers(self) -> None:
"""Tests getting properties using multiple transformers."""
graph = GeoNavigationGraph.from_coordinates_degrees(
latitudes=array([0, 1]), longitudes=array([0, 0]), edges=array([[0, 1]]), node_radius=111.111
)
# now we use `append_property` to append a single one
graph.append_properties(
[ConstantTransformer(33, uint32, "prop_1"), ConstantTransformer(99, int16, "prop_2")]
)
self.assertEqual(len(graph.node_properties), 2)
assert_array_equal(graph.node_properties.columns, ["prop_1", "prop_2"])
assert_series_equal(
graph.node_properties["prop_1"], Series(data=[33, 33], dtype=uint32, name="prop_1")
)
assert_series_equal(
graph.node_properties["prop_2"], Series(data=[99, 99], dtype=int16, name="prop_2")
)
class TestBathymetricTransformer(TestCase):
"""Tests :class:`pyrate.common.raster_datasets.transformers_concrete.BathymetricTransformer`."""
def test_all_modes(self) -> None:
"""Tests all modes at once."""
# create a coarse grid
distance_meters = 1000_000
graph = create_earth_graph(min_required_frequency(distance_meters, in_meters=True))
# fetch properties
modes = list(BathymetricTransformer.Modes)
graph.append_property(BathymetricTransformer(_open_test_geo_dataset(), modes))
properties = graph.node_properties
# check that the returned properties are all floats
self.assertTrue((properties.dtypes == float32).all())
def test_no_data(self) -> None:
"""Tests that querying for data where there are no data points in the result range raises an error."""
for mode in list(BathymetricTransformer.Modes):
with self.subTest(mode.name), self.assertRaises(ValueError):
with BathymetricTransformer(_open_test_geo_dataset(), [mode]) as transformer:
# This works by querying for a point (at 1e-3°N 1e-3°E), where there is no data point
# within 1e-9 meters in the underlying dataset
# This should trigger an exception (e.g. because the average depth over zero data
# points is not clearly)
transformer.get_transformed_at_nodes(
latitudes=array([1e-3]), longitudes=array([1e-3]), radius=1e-9
)