aboutsummaryrefslogtreecommitdiffziptar.gz
path: root/tests/test_zones.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_zones.py')
-rw-r--r--tests/test_zones.py66
1 files changed, 66 insertions, 0 deletions
diff --git a/tests/test_zones.py b/tests/test_zones.py
new file mode 100644
index 0000000..f5b73c1
--- /dev/null
+++ b/tests/test_zones.py
@@ -0,0 +1,66 @@
+# map/tests/test_zones.py
+import tempfile
+import unittest
+from pathlib import Path
+
+import numpy as np
+from PIL import Image
+
+from mapgen import sketch as SK, zones as ZN
+from mapgen.sphere import east_north, great_circle_point, latlon_to_xyz
+from tests.helpers import make_ctx
+
+R = 12742.0
+R1 = {"name": "R1", "field": "o2", "center": [-5.6, -118.8], "radius_km": 3200.0, "v": 1.0}
+L1 = {"name": "L1", "field": "gravity", "center": [-26.3, -133.7], "radius_km": 2200.0, "v": -0.6}
+
+
+def ray(zone, az_deg, step_km=5.0):
+ p0 = latlon_to_xyz(*zone["center"])
+ e, n = east_north(p0[None])
+ a = np.radians(az_deg)
+ t = np.sin(a) * e[0] + np.cos(a) * n[0]
+ s = np.arange(0.0, 1.4 * zone["radius_km"], step_km)
+ return s, np.array([great_circle_point(p0, t, si, R) for si in s])
+
+
+class ZoneProfileTest(unittest.TestCase):
+ def test_peak_at_the_centre_and_nothing_beyond_the_warped_radius(self):
+ for z in (R1, L1):
+ s, pts = ray(z, 40.0)
+ f = ZN.contribution(pts, z, 1296, R)
+ self.assertAlmostEqual(f[0], z["v"])
+ self.assertTrue(np.all(f[s > z["radius_km"] / (1 - ZN.WARP) + 1] == 0.0))
+
+ def test_steepest_change_is_hard_to_notice_over_a_days_walk(self):
+ """≤ 0.23 O₂ points and ≤ 0.014 g per 30 km, for the strongest O₂ and low-gravity zones."""
+ for z, per_unit, limit in ((R1, 0.21 * 0.5 * 100.0, 0.23), (L1, 1.05 * 0.7, 0.014)):
+ worst = 0.0
+ for az in range(0, 360, 5):
+ _, pts = ray(z, az)
+ f = ZN.contribution(pts, z, 1296, R) * per_unit
+ worst = max(worst, float(np.max(np.abs(np.diff(f)))) / 5.0 * 30.0)
+ self.assertLessEqual(worst, limit, z["name"])
+
+ def test_outline_is_not_a_circle(self):
+ at = [ZN.contribution(ray(R1, az)[1][[400]], R1, 1296, R)[0] for az in range(0, 360, 30)] # 2,000 km out
+ self.assertGreater(max(at) - min(at), 0.02)
+
+
+class SketchZonesTest(unittest.TestCase):
+ def test_config_zones_add_to_painted_masks_and_clip(self):
+ root = Path(tempfile.mkdtemp())
+ (root / "sketch").mkdir()
+ (root / "masks").mkdir()
+ for n in SK.SKETCH:
+ Image.fromarray(np.zeros((10, 20), np.uint8), "L").save(root / "sketch" / f"{n}.png")
+ Image.fromarray(np.full((10, 20), 191, np.uint8), "L").save(root / "masks" / "o2_zones.png") # ≈ +0.5
+ zones = [{**R1, "center": [0.0, 0.0]}, {**L1, "center": [0.0, 0.0]}]
+ ctx = make_ctx(2, tect={"plate": [], "zone": zones}, root=root)
+ out = SK.run(ctx)
+ g = ctx.grid
+ c, far = g.cell_index(0.0, 0.0), g.cell_index(0.0, 180.0)
+ self.assertEqual(out["m_o2_zones"][c], 1.0, "mask + zone, clipped")
+ self.assertAlmostEqual(out["m_o2_zones"][far], 0.498, places=2)
+ self.assertAlmostEqual(out["m_gravity_zones"][c], -0.6, delta=0.05)
+ self.assertEqual(out["m_gravity_zones"][far], 0.0)