Skip to content

Commit

Permalink
Added gridpp::gridding unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
tnipen committed Mar 15, 2024
1 parent 117809a commit b2b7593
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 0 deletions.
16 changes: 16 additions & 0 deletions src/api/gridding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ using namespace gridpp;
vec2 gridpp::gridding(const Grid& grid, const Points& points, const vec& values, float radius, int min_num, gridpp::Statistic statistic) {
if(!gridpp::compatible_size(points, values))
throw std::invalid_argument("Points size is not the same as values");
if(!gridpp::is_valid(radius) || radius < 0)
throw std::invalid_argument("radius must be >= 0");
if(!gridpp::is_valid(min_num) || min_num < 0)
throw std::invalid_argument("min_num must be >= 0");

int Y = grid.size()[0];
int X = grid.size()[1];
vec2 lats = grid.get_lats();
Expand All @@ -31,6 +36,11 @@ vec2 gridpp::gridding(const Grid& grid, const Points& points, const vec& values,
vec gridpp::gridding(const Points& opoints, const Points& ipoints, const vec& values, float radius, int min_num, gridpp::Statistic statistic) {
if(!gridpp::compatible_size(ipoints, values))
throw std::invalid_argument("Points size is not the same as values");
if(!gridpp::is_valid(radius) || radius < 0)
throw std::invalid_argument("radius must be >= 0");
if(!gridpp::is_valid(min_num) || min_num < 0)
throw std::invalid_argument("min_num must be >= 0");

int N = opoints.size();
vec lats = opoints.get_lats();
vec lons = opoints.get_lons();
Expand All @@ -53,6 +63,9 @@ vec gridpp::gridding(const Points& opoints, const Points& ipoints, const vec& va
vec2 gridpp::gridding_nearest(const Grid& grid, const Points& ipoints, const vec& values, int min_num, gridpp::Statistic statistic) {
if(!gridpp::compatible_size(ipoints, values))
throw std::invalid_argument("Points size is not the same as values");
if(!gridpp::is_valid(min_num) || min_num < 0)
throw std::invalid_argument("min_num must be >= 0");

int Y = grid.size()[0];
int X = grid.size()[1];
vec lats = ipoints.get_lats();
Expand Down Expand Up @@ -88,6 +101,9 @@ vec2 gridpp::gridding_nearest(const Grid& grid, const Points& ipoints, const vec
vec gridpp::gridding_nearest(const Points& opoints, const Points& ipoints, const vec& values, int min_num, gridpp::Statistic statistic) {
if(!gridpp::compatible_size(ipoints, values))
throw std::invalid_argument("Points size is not the same as values");
if(!gridpp::is_valid(min_num) || min_num < 0)
throw std::invalid_argument("min_num must be >= 0");

int N = opoints.size();
vec lats = ipoints.get_lats();
vec lons = ipoints.get_lons();
Expand Down
118 changes: 118 additions & 0 deletions tests/test_gridding.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
from __future__ import print_function
import unittest
import gridpp
import numpy as np


def get_shape(grid):
shape = grid.size()
if isinstance(shape, int):
shape = [shape,]
return shape

class Test(unittest.TestCase):
def setUp(self):
y, x = np.meshgrid(np.linspace(0, 1, 2), np.linspace(0, 1, 3))
self.grid = gridpp.Grid(y, x, 0*y, 0*y, gridpp.Cartesian)
self.grid_as_points = self.grid.to_points()
self.points = gridpp.Points([-0.2, 0.5, 1], [-0.2, 0.5, 1], [0, 0, 0], [0, 0, 0], gridpp.Cartesian)
self.values = [1, 2, 3]
self.radius = 0.6
self.statistic = gridpp.Sum
self.min_num = 0

def test_min_num(self):
expected_list = {
0: [[1, np.nan], [2, 5], [np.nan, 3]],
1: [[1, np.nan], [2, 5], [np.nan, 3]],
2: [[np.nan, np.nan], [np.nan, 5], [np.nan, np.nan]],
}

for grid in [self.grid, self.grid_as_points]:
for min_num, expected in expected_list.items():
with self.subTest(grid=grid, min_num=min_num):
output = gridpp.gridding(grid, self.points, self.values, self.radius, min_num, self.statistic)
np.testing.assert_array_almost_equal(output.shape, get_shape(grid))
np.testing.assert_array_almost_equal(output.flatten(), np.array(expected).flatten())

def test_statistic(self):
expected_list = {
gridpp.Sum:[[1, np.nan], [2, 5], [np.nan, 3]],
gridpp.Mean: [[1, np.nan], [2, 2.5], [np.nan, 3]],
gridpp.Count: [[1, 0], [1, 2], [0, 1]],
}

for grid in [self.grid, self.grid_as_points]:
for statistic, expected in expected_list.items():
with self.subTest(grid=grid, statistic=statistic):
output = gridpp.gridding(grid, self.points, self.values, self.radius, self.min_num, statistic)
np.testing.assert_array_almost_equal(output.shape, get_shape(grid))
np.testing.assert_array_almost_equal(output.flatten(), np.array(expected).flatten())

def test_radius(self):
expected_list = {
0.001:[[np.nan, np.nan], [np.nan, np.nan], [np.nan, 3]],
0.6: [[1, np.nan], [2, 5], [np.nan, 3]],
10: [[6, 6], [6, 6], [6, 6]],
}

for grid in [self.grid, self.grid_as_points]:
for radius, expected in expected_list.items():
with self.subTest(grid=grid, radius=radius):
output = gridpp.gridding(grid, self.points, self.values, radius, self.min_num, self.statistic)
np.testing.assert_array_almost_equal(output.shape, get_shape(grid))
np.testing.assert_array_almost_equal(output.flatten(), np.array(expected).flatten())

def test_invalid_arguments(self):
# Values don't match point size
for grid in [self.grid, self.grid_as_points]:
with self.subTest(grid=grid):
with self.assertRaises(ValueError) as e:
output = gridpp.gridding(grid, self.points, [0], self.radius, self.min_num, self.statistic)

def test_empty_input(self):
# Empty points should give all nans
points = gridpp.Points([], [], [], [], gridpp.Cartesian)
values = []
expected = np.nan * np.zeros(self.grid.size())
for grid in [self.grid, self.grid_as_points]:
for statistic in [gridpp.Sum, gridpp.Mean]:
output = gridpp.gridding(grid, points, values, self.radius, self.min_num, statistic)
np.testing.assert_array_almost_equal(output.shape, get_shape(grid))
np.testing.assert_array_almost_equal(output.flatten(), np.array(expected).flatten())

# Count should be 0
output = gridpp.gridding(self.grid, points, values, self.radius, self.min_num, gridpp.Count)
expected = np.zeros(self.grid.size())
np.testing.assert_array_almost_equal(output, expected)

def test_empty_grid(self):
grid = gridpp.Grid([[]], [[]], [[]], [[]], gridpp.Cartesian)
for statistic in [gridpp.Sum, gridpp.Mean, gridpp.Count]:
output = gridpp.gridding(grid, self.points, self.values, self.radius, self.min_num, statistic)
np.testing.assert_array_almost_equal(output, np.zeros([0,0]))

def test_empty_grid_as_points(self):
grid_as_points = gridpp.Points([], [], [], [], gridpp.Cartesian)
for statistic in [gridpp.Sum, gridpp.Mean, gridpp.Count]:
output = gridpp.gridding(grid_as_points, self.points, self.values, self.radius, self.min_num, statistic)
np.testing.assert_array_almost_equal(output, np.zeros([0]))

def test_invalid_radius(self):
radii = [-1, np.nan]
for grid in [self.grid, self.grid_as_points]:
for radius in radii:
with self.subTest(grid=grid, radius=radius):
with self.assertRaises(ValueError) as e:
output = gridpp.gridding(grid, self.points, self.values, radius, self.min_num, self.statistic)

def test_invalid_min_num(self):
min_num = -1 # Can't check np.nan, since this is not an int, and will fail with a TypeError
for grid in [self.grid, self.grid_as_points]:
with self.subTest(grid=grid):
with self.assertRaises(ValueError) as e:
output = gridpp.gridding(grid, self.points, self.values, self.radius, min_num, self.statistic)


if __name__ == '__main__':
unittest.main()

0 comments on commit b2b7593

Please sign in to comment.