From 1272249e421c883c3c7e447abfc53ab72596636c Mon Sep 17 00:00:00 2001 From: tcl Date: Tue, 17 Nov 2015 12:51:05 +0100 Subject: [PATCH 1/2] Overlooked world.plates when switching to numpy. Added world.plates to the serialization-tests. Reworked center_land(). --- tests/common_test.py | 22 ++------------------ tests/serialization_test.py | 2 ++ worldengine/cli/main.py | 4 ++-- worldengine/common.py | 10 --------- worldengine/generation.py | 34 +++++++------------------------ worldengine/hdf5_serialization.py | 4 +--- worldengine/plates.py | 3 +-- worldengine/world.py | 14 ++++++------- 8 files changed, 21 insertions(+), 72 deletions(-) diff --git a/tests/common_test.py b/tests/common_test.py index fb374988..f1ecb64e 100644 --- a/tests/common_test.py +++ b/tests/common_test.py @@ -1,7 +1,7 @@ import unittest import numpy -from worldengine.common import Counter, anti_alias, array_to_matrix, get_verbose, \ - matrix_min_and_max, rescale_value, set_verbose +from worldengine.common import Counter, anti_alias, get_verbose, \ + rescale_value, set_verbose class TestCommon(unittest.TestCase): @@ -16,19 +16,6 @@ def test_get_and_set_verbose(self): set_verbose(False) self.assertEqual(False, get_verbose()) - def test_matrix_min_and_max(self): - m1 = [ - [-0.8, -0.5, 1.0, 2.6], - [-0.8, -1.5, 8.8, 2.7] - ] - m2 = [] - m3 = [[], []] - m4 = [[0.0]] - self.assertEqual((-1.5, 8.8), matrix_min_and_max(m1)) - self.assertEqual((None, None), matrix_min_and_max(m2)) - self.assertEqual((None, None), matrix_min_and_max(m3)) - self.assertEqual((0.0, 0.0), matrix_min_and_max(m4)) - def test_counter(self): c = Counter() self.assertEqual("", c.to_str()) @@ -71,10 +58,5 @@ def test_antialias(self): antialiased = anti_alias(original, 10) self.assertAlmostEquals(0.8, antialiased[0][0]) - def test_array_to_matrix(self): - array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] - self.assertEqual([[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]], array_to_matrix(array, 5, 2)) - self.assertEqual([[0, 1], [2, 3], [4, 5], [6, 7], [8, 9]], array_to_matrix(array, 2, 5)) - if __name__ == '__main__': unittest.main() diff --git a/tests/serialization_test.py b/tests/serialization_test.py index c4f9da46..f8509f6c 100644 --- a/tests/serialization_test.py +++ b/tests/serialization_test.py @@ -18,6 +18,7 @@ def test_protobuf_serialize_unserialize(self): unserialized = World.protobuf_unserialize(serialized) self.assertTrue(_equal(w.elevation['data'], unserialized.elevation['data'])) self.assertEqual(w.elevation['thresholds'], unserialized.elevation['thresholds']) + self.assertTrue(_equal(w.plates, unserialized.plates)) self.assertTrue(_equal(w.ocean, unserialized.ocean)) self.assertTrue(_equal(w.biome, unserialized.biome)) self.assertTrue(_equal(w.humidity, unserialized.humidity)) @@ -48,6 +49,7 @@ def test_hdf5_serialize_unserialize(self): unserialized = load_world_to_hdf5(filename) self.assertTrue(_equal(w.elevation['data'], unserialized.elevation['data'])) self.assertEqual(w.elevation['thresholds'], unserialized.elevation['thresholds']) + self.assertTrue(_equal(w.plates, unserialized.plates)) self.assertTrue(_equal(w.ocean, unserialized.ocean)) self.assertTrue(_equal(w.biome, unserialized.biome)) self.assertTrue(_equal(w.humidity['quantiles'], unserialized.humidity['quantiles'])) diff --git a/worldengine/cli/main.py b/worldengine/cli/main.py index af148bee..f07bd339 100644 --- a/worldengine/cli/main.py +++ b/worldengine/cli/main.py @@ -3,7 +3,7 @@ import os import numpy import worldengine.generation as geo -from worldengine.common import array_to_matrix, set_verbose, print_verbose +from worldengine.common import set_verbose, print_verbose from worldengine.draw import draw_ancientmap_on_file, draw_biome_on_file, draw_ocean_on_file, \ draw_precipitation_on_file, draw_grayscale_heightmap_on_file, draw_simple_elevation_on_file, \ draw_temperature_levels_on_file, draw_riversmap_on_file, draw_scatter_plot_on_file, \ @@ -114,7 +114,7 @@ def generate_plates(seed, world_name, output_dir, width, height, world = World(world_name, width, height, seed, num_plates, -1.0, "plates") world.set_elevation(numpy.array(elevation).reshape(height, width), None) - world.set_plates(array_to_matrix(plates, width, height)) + world.set_plates(numpy.array(plates, dtype=numpy.uint16).reshape(height, width)) # Generate images filename = '%s/plates_%s.png' % (output_dir, world_name) diff --git a/worldengine/common.py b/worldengine/common.py index 17725090..a3e4a49e 100644 --- a/worldengine/common.py +++ b/worldengine/common.py @@ -111,16 +111,6 @@ def anti_alias_point(original, x, y): return current -def array_to_matrix(array, width, height): - if len(array) != (width * height): - raise Exception("Array as not expected length") - matrix = [] - for y in range(height): - matrix.append([]) - for x in range(width): - matrix[y].append(array[y * width + x]) - return matrix - def _equal(a, b): #recursion on subclasses of types: tuple, list, dict #specifically checks : float, ndarray diff --git a/worldengine/generation.py b/worldengine/generation.py index b4a3f71f..7854f662 100644 --- a/worldengine/generation.py +++ b/worldengine/generation.py @@ -22,39 +22,19 @@ def center_land(world): """Translate the map horizontally and vertically to put as much ocean as possible at the borders. It operates on elevation and plates map""" - min_sum_on_y = None - y_with_min_sum = None - latshift = 0 - for y in range(world.height): - sum_on_y = world.elevation['data'][y].sum() - if min_sum_on_y is None or sum_on_y < min_sum_on_y: - min_sum_on_y = sum_on_y - y_with_min_sum = y + y_sums = world.elevation['data'].sum(1) # 1 == sum along x-axis + y_with_min_sum = y_sums.argmin() if get_verbose(): print("geo.center_land: height complete") - min_sum_on_x = None - x_with_min_sum = None - for x in range(world.width): - sum_on_x = world.elevation['data'].T[x].sum() - if min_sum_on_x is None or sum_on_x < min_sum_on_x: - min_sum_on_x = sum_on_x - x_with_min_sum = x + x_sums = world.elevation['data'].sum(0) # 0 == sum along y-axis + x_with_min_sum = x_sums.argmin() if get_verbose(): print("geo.center_land: width complete") - new_elevation_data = [] #TODO: this should fully use numpy - new_plates = [] - for y in range(world.height): - new_elevation_data.append([]) - new_plates.append([]) - src_y = (y_with_min_sum + y - latshift) % world.height - for x in range(world.width): - src_x = (x_with_min_sum + x) % world.width - new_elevation_data[y].append(world.elevation['data'][src_y, src_x]) - new_plates[y].append(world.plates[src_y][src_x]) - world.elevation['data'] = numpy.array(new_elevation_data) - world.plates = new_plates + latshift = 0 + world.elevation['data'] = numpy.roll(numpy.roll(world.elevation['data'], -y_with_min_sum + latshift, axis=0), -x_with_min_sum, axis=1) + world.plates = numpy.roll(numpy.roll(world.plates, -y_with_min_sum + latshift, axis=0), -x_with_min_sum, axis=1) if get_verbose(): print("geo.center_land: width complete") diff --git a/worldengine/hdf5_serialization.py b/worldengine/hdf5_serialization.py index e6415e6f..daa0c392 100644 --- a/worldengine/hdf5_serialization.py +++ b/worldengine/hdf5_serialization.py @@ -23,9 +23,7 @@ def save_world_to_hdf5(world, filename): elevation_data.write_direct(world.elevation['data']) plates_data = f.create_dataset("plates", (world.height, world.width), dtype=numpy.uint16) - for y in range(world.height): - for x in range(world.width): - plates_data[y, x] = world.plates[y][x] + plates_data.write_direct(world.plates) ocean_data = f.create_dataset("ocean", (world.height, world.width), dtype=numpy.bool) ocean_data.write_direct(world.ocean) diff --git a/worldengine/plates.py b/worldengine/plates.py index fca0ce3d..e45ec4af 100644 --- a/worldengine/plates.py +++ b/worldengine/plates.py @@ -7,7 +7,6 @@ from worldengine.generation import Step, add_noise_to_elevation, center_land, generate_world, \ get_verbose, initialize_ocean_and_thresholds, place_oceans_at_map_borders -from worldengine.common import array_to_matrix from worldengine.world import World @@ -48,7 +47,7 @@ def _plates_simulation(name, width, height, seed, temps= world = World(name, width, height, seed, num_plates, ocean_level, step, temps, humids, gamma_curve, curve_offset) world.set_elevation(numpy.array(e_as_array).reshape(height, width), None) - world.set_plates(array_to_matrix(p_as_array, width, height)) + world.set_plates(numpy.array(p_as_array, dtype=numpy.uint16).reshape(height, width)) return world diff --git a/worldengine/world.py b/worldengine/world.py index d9d86559..9bcb20d6 100644 --- a/worldengine/world.py +++ b/worldengine/world.py @@ -89,6 +89,8 @@ def _to_protobuf_matrix(matrix, p_matrix, transformation=None): ''' if type(cell) is numpy.bool_: value = bool(cell) + elif type(cell) is numpy.uint16: + value = int(cell) else: value = cell if transformation: @@ -246,7 +248,7 @@ def _from_protobuf_world(cls, p_world): w.set_elevation(e, e_th) # Plates - w.set_plates(World._from_protobuf_matrix(p_world.plates)) + w.set_plates(numpy.array(World._from_protobuf_matrix(p_world.plates))) # Ocean w.set_ocean(numpy.array(World._from_protobuf_matrix(p_world.ocean))) @@ -790,11 +792,7 @@ def is_chaparral(self, pos): # def n_actual_plates(self): - res = -1 - for row in self.plates: - for cell in row: - res = max([cell, res]) - return res + 1 + return self.plates.max() + 1 # # Setters @@ -809,11 +807,11 @@ def set_elevation(self, data, thresholds): self.elevation = {'data': data, 'thresholds': thresholds} def set_plates(self, data): - if (len(data) != self.height) or (len(data[0]) != self.width): + if (data.shape[0] != self.height) or (data.shape[1] != self.width): raise Exception( "Setting plates map with wrong dimension. " "Expected %d x %d, found %d x %d" % ( - self.width, self.height, len(data[0]), len(data))) + self.width, self.height, data.shape[1], data.shape[0])) self.plates = data def set_biome(self, biome): From ba0edf2b38669afe0868dc41a0ee6cb346e10a05 Mon Sep 17 00:00:00 2001 From: tcl Date: Wed, 18 Nov 2015 06:52:59 +0100 Subject: [PATCH 2/2] More removals of dead code. --- tests/common_test.py | 22 +--------------------- worldengine/common.py | 22 ---------------------- 2 files changed, 1 insertion(+), 43 deletions(-) diff --git a/tests/common_test.py b/tests/common_test.py index f1ecb64e..59831777 100644 --- a/tests/common_test.py +++ b/tests/common_test.py @@ -1,7 +1,6 @@ import unittest import numpy -from worldengine.common import Counter, anti_alias, get_verbose, \ - rescale_value, set_verbose +from worldengine.common import Counter, anti_alias, get_verbose, set_verbose class TestCommon(unittest.TestCase): @@ -27,25 +26,6 @@ def test_counter(self): c.count("a") self.assertEqual("a : 1\nb : 3\n", c.to_str()) - def test_rescale_value(self): - self.assertAlmostEqual(0.0, rescale_value(0.0, 0.0, 1.0, 0.0, 10.0)) - self.assertAlmostEqual(2.5, rescale_value(0.25, 0.0, 1.0, 0.0, 10.0)) - self.assertAlmostEqual(5.0, rescale_value(0.5, 0.0, 1.0, 0.0, 10.0)) - self.assertAlmostEqual(7.5, rescale_value(0.75, 0.0, 1.0, 0.0, 10.0)) - self.assertAlmostEqual(10.0, rescale_value(1.0, 0.0, 1.0, 0.0, 10.0)) - - self.assertAlmostEqual(5.0, rescale_value(0.0, 0.0, 1.0, 5.0, 10.0)) - self.assertAlmostEqual(6.25, rescale_value(0.25, 0.0, 1.0, 5.0, 10.0)) - self.assertAlmostEqual(7.5, rescale_value(0.5, 0.0, 1.0, 5.0, 10.0)) - self.assertAlmostEqual(8.75, rescale_value(0.75, 0.0, 1.0, 5.0, 10.0)) - self.assertAlmostEqual(10.0, rescale_value(1.0, 0.0, 1.0, 5.0, 10.0)) - - self.assertAlmostEqual(-10.0, rescale_value(0.0, 0.0, 1.0, -10.0, 10.0)) - self.assertAlmostEqual(-5.0, rescale_value(0.25, 0.0, 1.0, -10.0, 10.0)) - self.assertAlmostEqual(0.0, rescale_value(0.5, 0.0, 1.0, -10.0, 10.0)) - self.assertAlmostEqual(5.0, rescale_value(0.75, 0.0, 1.0, -10.0, 10.0)) - self.assertAlmostEqual(10.0, rescale_value(1.0, 0.0, 1.0, -10.0, 10.0)) - def test_antialias(self): original = numpy.array([[0.5, 0.12, 0.7, 0.15, 0.0], [0.0, 0.12, 0.7, 0.7, 8.0], diff --git a/worldengine/common.py b/worldengine/common.py index a3e4a49e..90659c6a 100644 --- a/worldengine/common.py +++ b/worldengine/common.py @@ -59,28 +59,6 @@ def print_self(self): sys.stdout.write(self.to_str) -def matrix_min_and_max(matrix): - _min = None - _max = None - for row in matrix: - for el in row: - val = el - if _min is None or val < _min: - _min = val - if _max is None or val > _max: - _max = val - return _min, _max - - -def rescale_value(original, prev_min, prev_max, min, max): - """Rescale a given value. - Given the value, the current min and max and the new min and max - produce the rescaled value - """ - f = float(original - prev_min) / (prev_max - prev_min) - return min + ((max - min) * f) - - def anti_alias(map, steps):#TODO: There is probably a bit of numpy-optimization that can be done here. """ Execute the anti_alias operation steps times on the given map