-
Notifications
You must be signed in to change notification settings - Fork 135
Make use of Numpy-Arrays #138
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
c31e417
d6f7764
4716947
671b01d
aa5c63e
0d62c77
e66b38e
452db57
de4ac88
1f14c41
ebb2435
3ae6ea2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| import sys | ||
| from argparse import ArgumentParser | ||
| import os | ||
| import numpy | ||
| import pickle | ||
| import random | ||
| import worldengine.generation as geo | ||
|
|
@@ -95,7 +96,7 @@ def generate_plates(seed, world_name, output_dir, width, height, | |
| num_plates=num_plates) | ||
|
|
||
| world = World(world_name, width, height, seed, num_plates, -1.0, "plates") | ||
| world.set_elevation(array_to_matrix(elevation, width, height), None) | ||
| world.set_elevation(numpy.array(elevation).reshape(height, width), None) | ||
| world.set_plates(array_to_matrix(plates, width, height)) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since you flattened 2d array into 1d array with numpy, I know that numpy can take a 1d array and
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are right, it can do that. Is elevation a 1d-array, though? I didn't notice. Maybe it's not time to sleep yet, after all.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's done. Thanks for the hint, I totally missed this. |
||
|
|
||
| # Generate images | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| import sys | ||
| import copy | ||
| import numpy #for the _equal method only | ||
|
|
||
| # ---------------- | ||
| # Global variables | ||
|
|
@@ -80,32 +81,31 @@ def rescale_value(original, prev_min, prev_max, min, max): | |
| return min + ((max - min) * f) | ||
|
|
||
|
|
||
| def anti_alias(elevation, steps): | ||
| def anti_alias(map, steps):#TODO: There is probably a bit of numpy-optimization that can be done here. | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I spent an hour trying to optimize this, making heavy use of numpy. For some reason that ended up even slower, though. Somebody else could try himself, since this method is one of the last few that overall take a huge amount of processing time (20% of the total). |
||
| """ | ||
| Execute the anti_alias operation steps times on the given elevation map | ||
| Execute the anti_alias operation steps times on the given map | ||
| """ | ||
| width = len(elevation[0]) | ||
| height = len(elevation) | ||
| height, width = map.shape | ||
|
|
||
| def _anti_alias_step(original): | ||
| anti_aliased = copy.deepcopy(original) | ||
| for y in range(height): | ||
| for x in range(width): | ||
| anti_aliased[y][x] = anti_alias_point(original, x, y) | ||
| anti_aliased[y, x] = anti_alias_point(original, x, y) | ||
| return anti_aliased | ||
|
|
||
| def anti_alias_point(original, x, y): | ||
| n = 2 | ||
| tot = elevation[y][x] * 2 | ||
| tot = map[y, x] * 2 | ||
| for dy in range(-1, +2): | ||
| py = (y + dy) % height | ||
| for dx in range(-1, +2): | ||
| px = (x + dx) % width | ||
| n += 1 | ||
| tot += original[py][px] | ||
| tot += original[py, px] | ||
| return tot / n | ||
|
|
||
| current = elevation | ||
| current = map | ||
| for i in range(steps): | ||
| current = _anti_alias_step(current) | ||
| return current | ||
|
|
@@ -120,3 +120,33 @@ def array_to_matrix(array, width, height): | |
| for x in range(width): | ||
| matrix[y].append(array[y * width + x]) | ||
| return matrix | ||
|
|
||
| def _equal(a, b): | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I hope this doesn't seem too much like a hack. I just didn't know how to handle numpy.array== otherwise (it defaults to returning an array of bools instead of a single bool, which did cause problems at many places in the code).
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this function used in other parts of WE or just tests? If just tests, can it be moved to the tests please?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is used in/as World.operator== - removing it would leave worlds without a proper way of checking for equality. I said this already at some point, but: I think this method should stay here. |
||
| #recursion on subclasses of types: tuple, list, dict | ||
| #specifically checks : float, ndarray | ||
| if type(a) is float and type(b) is float:#float | ||
| return(numpy.allclose(a, b)) | ||
| elif type(a) is numpy.ndarray and type(b) is numpy.ndarray:#ndarray | ||
| return(numpy.array_equiv(a, b))#alternative for float-arrays: numpy.allclose(a, b[, rtol, atol]) | ||
| elif isinstance(a, dict) and isinstance(b, dict):#dict | ||
| if len(a) != len(b): | ||
| return(False) | ||
| t = True | ||
| for key, val in a.items(): | ||
| if key not in b: | ||
| return(False) | ||
| t = _equal(val, b[key]) | ||
| if not t: | ||
| return(False) | ||
| return(t) | ||
| elif (isinstance(a, list) and isinstance(b, list)) or (isinstance(a, tuple) and isinstance(b, tuple)):#list, tuples | ||
| if len(a) != len(b): | ||
| return(False) | ||
| t = True | ||
| for vala, valb in zip(a, b): | ||
| t = _equal(vala, valb) | ||
| if not t: | ||
| return(False) | ||
| return(t) | ||
| else:#fallback | ||
| return(a == b) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method ate huge amounts of time in comparison to everything else. I hope the replacement in line 215 below is ok, but I am scratching my head about that a bit. (tests and output, however, are perfect)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perfect, that is numpy's strong point. good job!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just profiled a<b<c to gain about a millisecond while this change gained about 25% of the total runtime. :D I shouldn't try to look into those super-small things anymore. :P