aboutsummaryrefslogtreecommitdiffziptar.gz
path: root/tests/test_grid.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_grid.py')
-rw-r--r--tests/test_grid.py83
1 files changed, 83 insertions, 0 deletions
diff --git a/tests/test_grid.py b/tests/test_grid.py
new file mode 100644
index 0000000..a6b0848
--- /dev/null
+++ b/tests/test_grid.py
@@ -0,0 +1,83 @@
+import unittest
+
+import numpy as np
+
+from mapgen.grid import Grid
+from tests.helpers import small_grid
+
+
+class GridTest(unittest.TestCase):
+ def test_counts_and_pentagons(self):
+ g = small_grid(2)
+ self.assertEqual(g.n, 5882)
+ self.assertTrue(np.all(np.diff(g.ids.astype(np.int64)) > 0))
+ self.assertEqual(int(np.sum(g.counts == 5)), 12)
+ self.assertEqual(int(np.sum(g.counts == 6)), g.n - 12)
+
+ def test_neighbours_symmetric(self):
+ g = small_grid(2)
+ pairs = set(zip(g.src.tolist(), g.dst.tolist()))
+ self.assertTrue(all((b, a) in pairs for a, b in pairs))
+
+ def test_area_sums_to_sphere(self):
+ g = small_grid(2)
+ self.assertAlmostEqual(g.area_km2.sum() / (4 * np.pi * 12742.0**2), 1.0, places=6)
+
+ def test_spacing_and_tangents(self):
+ g = small_grid(2)
+ self.assertTrue(500 < g.spacing_km < 800) # res 2 ≈ 632 km
+ np.testing.assert_allclose(np.linalg.norm(g.edge_tangents, axis=1), 1.0)
+ np.testing.assert_allclose(np.sum(g.edge_tangents * g.xyz[g.src], axis=1), 0.0, atol=1e-12)
+
+ def test_roundtrip_arrays_and_lookup(self):
+ g = small_grid(2)
+ h = Grid.from_arrays(g.to_arrays(), g.res, g.radius_km)
+ np.testing.assert_array_equal(h.nbr_idx, g.nbr_idx)
+ i = g.cell_index(10.0, 20.0)
+ self.assertLess(abs(g.lat[i] - 10.0), 5.0)
+
+
+class CellParentsTest(unittest.TestCase):
+ def test_same_as_h3_cell_to_parent(self):
+ import h3.api.basic_int as h3
+ import numpy as np
+ from mapgen.grid import cell_parents
+ rng = np.random.default_rng(5)
+ for res in (1, 3, 6, 9):
+ cells = [h3.latlng_to_cell(float(la), float(lo), res + int(k))
+ for la, lo, k in zip(rng.uniform(-90, 90, 300), rng.uniform(-180, 180, 300), rng.integers(0, 4, 300))]
+ pent = h3.get_pentagons(max(res - 2, 0))[:2] + [h3.latlng_to_cell(10.0, 20.0, max(res - 2, 0))]
+ cells += [c for p in pent for c in h3.cell_to_children(p, res)] # incl. pentagons
+ for pr in range(0, res + 1):
+ want = np.array([h3.cell_to_parent(c, pr) for c in cells], np.uint64)
+ self.assertTrue(np.array_equal(cell_parents(cells, pr), want), (res, pr))
+ with self.assertRaises(ValueError):
+ cell_parents([h3.latlng_to_cell(0.0, 0.0, 2)], 3)
+
+
+class EdgeBlocksTest(unittest.TestCase):
+ def test_blocked_edge_fields_same_as_whole(self):
+ from unittest import mock
+ from mapgen import grid as GR
+ from mapgen import plates as PL
+ from mapgen.sphere import tangent_dir
+ g = small_grid(3)
+ xyz, src, dst = g.xyz, g.src, g.dst
+ want_t = tangent_dir(xyz[src], xyz[dst]) # the whole-array formulas, written out
+ want_km = g.radius_km * np.arccos(np.clip(np.sum(xyz[src] * xyz[dst], axis=1), -1.0, 1.0))
+ vel = np.random.default_rng(2).normal(size=(g.n, 3))
+ rel = vel[dst] - vel[src]
+ along = np.sum(rel * want_t, axis=1)
+ want_tang = np.linalg.norm(rel - along[:, None] * want_t, axis=1)
+ with mock.patch.object(GR, "EDGE_BLOCK", 997): # many uneven blocks
+ g2 = small_grid(3)
+ self.assertTrue(np.array_equal(g2.edge_tangents, want_t))
+ self.assertTrue(np.array_equal(g2.edge_km, want_km))
+ conv, tang = PL.edge_convergence(g2, vel)
+ self.assertTrue(np.array_equal(conv, -along))
+ self.assertTrue(np.array_equal(tang, want_tang))
+ self.assertGreater(len(GR.edge_blocks(len(dst), 997)), 3)
+ with mock.patch.object(GR, "EDGE_BLOCK", 997):
+ for idx in (src, dst):
+ self.assertTrue(np.array_equal(GR.rowdot_at(vel, idx, want_t), np.sum(vel[idx] * want_t, axis=1)))
+ self.assertTrue(np.array_equal(GR.rowdot_at(vel, idx, want_t), np.sum(want_t * vel[idx], axis=1)))