raw ยท 9281 bytes
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 | import unittest import numpy as np from mapgen import environment as EN from tests.helpers import make_ctx def name(bio, p, tmin): z, _ = EN.holdridge(np.array([bio]), np.array([p]), np.array([tmin])) return EN.HOLDRIDGE_NAMES[z[0]] class HoldridgeTest(unittest.TestCase): def test_count(self): self.assertEqual(len(EN.HOLDRIDGE_NAMES), 38) def test_table(self): self.assertEqual(name(26, 3000, 20), "tropical moist forest") self.assertEqual(name(26, 9000, 20), "tropical rain forest") self.assertEqual(name(26, 100, 20), "tropical desert") self.assertEqual(name(0.5, 100, -30), "polar desert") self.assertEqual(name(8, 300, -10), "cool temperate steppe") self.assertEqual(name(15, 1500, -5), "warm temperate moist forest") self.assertEqual(name(15, 1500, 5), "subtropical moist forest") self.assertEqual(name(4, 700, -20), "boreal wet forest") self.assertEqual(name(2, 200, -25), "subpolar moist tundra") def test_polar_desert_with_summer_monsoon(self): tag = EN.seasonality(np.array([180.0, 20.0]), np.array([20.0, 180.0]), np.array([80.0, 80.0]), np.array([-30.0, -30.0]), np.array([100.0, 100.0]), EN.DEFAULTS) self.assertEqual(tag[0], EN.SEAS_W) # NH: wet June (summer), dry December self.assertEqual(tag[1], EN.SEAS_S) # NH: dry summer sh = EN.seasonality(np.array([20.0]), np.array([180.0]), np.array([-80.0]), np.array([-30.0]), np.array([100.0]), EN.DEFAULTS) self.assertEqual(sh[0], EN.SEAS_W) # SH summer is December def test_tropical_monsoon(self): tag = EN.seasonality(np.array([3000.0]), np.array([200.0]), np.array([15.0]), np.array([20.0]), np.array([1800.0]), EN.DEFAULTS) self.assertEqual(tag[0], EN.SEAS_M) class StageTest(unittest.TestCase): def test_run(self): ctx = make_ctx(3) g = ctx.grid n = g.n land = (np.abs(g.lat) < 40) & (np.abs(g.lon) < 60) z = np.where(land, 300.0, -4000.0) z = np.where(land & (np.abs(g.lon) < 4), 4000.0, z) zeros = np.zeros(n) ctx.data.update({ "elevation_eroded_m": z, "continental": land, "age_class": np.where(land, 1, 0).astype(np.int8), "d_over_km": np.full(n, np.inf), "T_mean": np.where(np.abs(g.lat) > 30, -5.0, 20.0), "T_min": np.full(n, -10.0), "T_range": np.full(n, 20.0), "P_ann": np.full(n, 800.0), "P_jun": np.full(n, 800.0), "P_dec": np.full(n, 800.0), "biotemp": np.full(n, 10.0), "dist_ocean_km": np.where(land, 1000.0, 0.0), "river": np.zeros(n, bool), "strahler": np.zeros(n, np.int8), "discharge_km3_yr": zeros, "lake": np.zeros(n, bool), "salt_flat": np.zeros(n, bool)}) out = EN.run(ctx) self.assertEqual(out["landform"][g.cell_index(0.0, 0.0)], EN.LF_MOUNTAINS) self.assertEqual(out["landform"][g.cell_index(0.0, 150.0)], EN.LF_OCEAN) self.assertEqual(out["ground"][g.cell_index(35.0, 40.0)], EN.GR_PERMAFROST) for k in ("holdridge", "hold_region", "seasonality", "landform", "relief_m", "lithology", "ground", "coal_potential", "iron_potential"): self.assertEqual(len(out[k]), n) class OceanMaskEnvTest(unittest.TestCase): def test_inland_basin_not_ocean_landform(self): ctx = make_ctx(3) g = ctx.grid n = g.n land = (np.abs(g.lat) < 40) & (np.abs(g.lon) < 60) z = np.where(land, 300.0, -4000.0) basin = (np.abs(g.lat) < 6) & (np.abs(g.lon) < 6) z[basin] = -30.0 zeros = np.zeros(n) ctx.data.update({ "elevation_eroded_m": z, "ocean": ~land, "continental": land, "age_class": np.where(land, 1, 0).astype(np.int8), "d_over_km": np.full(n, np.inf), "T_mean": np.full(n, 20.0), "T_min": np.full(n, 10.0), "T_range": np.full(n, 10.0), "P_ann": np.full(n, 800.0), "P_jun": np.full(n, 800.0), "P_dec": np.full(n, 800.0), "biotemp": np.full(n, 20.0), "dist_ocean_km": np.where(land, 1000.0, 0.0), "river": np.zeros(n, bool), "strahler": np.zeros(n, np.int8), "discharge_km3_yr": zeros, "lake": np.zeros(n, bool), "salt_flat": np.zeros(n, bool)}) out = EN.run(ctx) self.assertFalse(np.any(out["landform"][basin] == EN.LF_OCEAN)) class ReliefResolutionTest(unittest.TestCase): def test_relief_window_is_in_km(self): from tests.helpers import small_grid med = [] for res in (2, 3): g = small_grid(res) z = 1000.0 * np.sin(10.0 * g.xyz[:, 0]) + 800.0 * np.cos(9.0 * g.xyz[:, 1]) _, relief = EN.landform(g, z, np.ones(g.n, np.int8), np.ones(g.n, np.int8), np.full(g.n, np.inf), np.full(g.n, 800.0), np.zeros(g.n, bool), relief_km=700.0) med.append(np.median(relief)) self.assertAlmostEqual(med[0] / med[1], 1.0, delta=0.3) class WetlandRuleTest(unittest.TestCase): def test_wetlands_need_real_rivers_on_real_flats(self): from types import SimpleNamespace from mapgen import graph as G g = small_grid_env() n = g.n z = np.where(g.lat > -30, 100.0 + 0.0001 * g.lat, -3000.0) # a very flat humid plain common = dict(lit=np.full(n, EN.LI_GRANITE, np.int8), t_mean=np.full(n, 15.0), t_min=np.full(n, 5.0), p_ann=np.full(n, 1200.0), dist_ocean=np.full(n, 2000.0), river=np.zeros(n, bool), strahler=np.zeros(n, np.int8), lake=np.zeros(n, bool), salt_flat=np.zeros(n, bool)) def wet(q): gr = EN.ground(g, z, common["lit"], common["t_mean"], common["t_min"], common["p_ann"], common["dist_ocean"], common["river"], common["strahler"], np.full(n, q), common["lake"], common["salt_flat"], EN.DEFAULTS, g.lat <= -30) return np.mean(gr[g.lat > 0] == EN.GR_WETLAND) self.assertLess(wet(3.0), 0.05) # small streams don't make a wetland self.assertGreater(wet(8.0), 0.9) # a big river across a flat does def small_grid_env(): from tests.helpers import small_grid return small_grid(3) class DepositsTest(unittest.TestCase): def test_shares_rules_and_main(self): from mapgen import minerals as MN from mapgen import environment as EN from mapgen.crust import CRATON, POST_OROGEN g = make_ctx(4).grid n = g.n land = np.abs(g.lat) < 60 mountain = land & (g.lon > 0) & (g.lon < 60) f = {"land": land, "z": np.where(mountain, 3500.0, 200.0), "lit": np.where(mountain, EN.LI_METAMORPHIC, EN.LI_SANDSTONE).astype(np.int8), "age": np.where(mountain, POST_OROGEN, CRATON), "lf": np.where(mountain, EN.LF_MOUNTAINS, EN.LF_PLAIN), "relief": np.where(mountain, 2500.0, 50.0), "t_mean": np.full(n, 15.0), "p_ann": np.full(n, 900.0), "d_coll": np.full(n, np.inf), "salt": np.zeros(n, bool), "endo": np.zeros(n, bool), "dist_ocean": np.full(n, 500.0), "coal": land & ~mountain} bits, main = MN.place(g, f, 7) self.assertEqual(len(MN.DEPOSITS), 32) self.assertFalse(bits[~land].any()) for name in ("ironstone", "oil_gas", "iron_high", "tungsten"): has = (bits & np.uint32(MN.BIT[name])) > 0 share = dict((d[0], d[2]) for d in MN.DEPOSITS)[name] self.assertLessEqual(has.sum(), round(share * land.sum()) + 1, name) self.assertTrue(has.any(), name) for name in MN.DEEP[:2]: # the good stuff: in the mountains only here has = (bits & np.uint32(MN.BIT[name])) > 0 self.assertTrue(np.all(mountain[has]), name) some = bits > 0 self.assertTrue(np.all(main[some] > 0) and np.all(main[~some] == 0)) k = np.flatnonzero(some)[0] self.assertTrue(bits[k] & np.uint32(1 << (int(main[k]) - 1))) def test_deposits_are_sprinkled_not_one_hotspot(self): from mapgen import minerals as MN g = make_ctx(4).grid land = np.abs(g.lat) < 60 hot = land & (g.lat > 0) & (g.lat < 30) & (g.lon > 0) & (g.lon < 40) # a world-class district score = np.where(hot, 3.0, np.where(land, 1.0, 0.0)) prov = MN.provinces(g, 7) sel = MN._rank_select(score, 0.02, land, prov) self.assertEqual(sel.sum(), round(0.02 * land.sum())) self.assertFalse(sel[~land].any()) self.assertGreater((sel & hot).sum(), 0.3 * sel.sum()) # the district keeps the most self.assertGreater((sel & ~hot).sum(), 0.3 * sel.sum()) # the rest is sprinkled self.assertGreater(len(np.unique(prov[sel & ~hot])), 0.3 * len(np.unique(prov[land & ~hot]))) self.assertFalse(MN._rank_select(np.where(hot, 1.0, 0.0), 0.02, land, prov)[~hot].any()) # rules still rule poor = MN._rank_select(np.where(hot, 10.0, np.where(land, 1.0, 0.0)), 0.02, land, prov) self.assertFalse(poor[~hot].any()) # far poorer ground: no local mines |