polliwog
polliwog copied to clipboard
Fix point-on-plane detection for NumPy 1.19.0 in Linux
This fixes the tests that are failing in NumPy 1.19.0.
See https://app.circleci.com/pipelines/github/lace/polliwog/836/workflows/b88ac698-51bc-46ea-80b8-f9e57e7157d9/jobs/2618/steps
_________ test_open_starts_in_front_ends_in_back_with_vertex_on_plane __________
def test_open_starts_in_front_ends_in_back_with_vertex_on_plane():
signs = np.array([1, 1, 1, 0, -1, -1, -1, -1])
> vertices = vertices_with_signs(signs)
polliwog/polyline/test_slice_by_plane.py:62:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
signs = array([ 1, 1, 1, 0, -1, -1, -1, -1])
def vertices_with_signs(signs):
num_verts = len(signs)
random_points_on_plane = plane.project_point(rand_nonzero(num_verts, 3))
random_displacement_along_normal = (
rand_nonzero(num_verts).reshape(-1, 1) * plane_normal
)
vertices = (
random_points_on_plane + signs.reshape(-1, 1) * random_displacement_along_normal
)
# Because of rounding, the random points don't necessarily return 0 for
# sign, so pick one that does.
vertices[signs == 0] = plane.reference_point
> np.testing.assert_array_equal(plane.sign(vertices), signs)
E AssertionError:
E Arrays are not equal
E
E Mismatched elements: 1 / 8 (12.5%)
E Max absolute difference: 1.
E Max relative difference: 0.
E x: array([ 1., 1., 1., 1., -1., -1., -1., -1.])
E y: array([ 1, 1, 1, 0, -1, -1, -1, -1])
polliwog/polyline/test_slice_by_plane.py:28: AssertionError
_________ test_open_starts_in_back_ends_in_front_with_vertex_on_plane __________
def test_open_starts_in_back_ends_in_front_with_vertex_on_plane():
signs = np.array([-1, -1, -1, -1, -1, 0, 1, 1, 1])
> vertices = vertices_with_signs(signs)
polliwog/polyline/test_slice_by_plane.py:88:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
signs = array([-1, -1, -1, -1, -1, 0, 1, 1, 1])
def vertices_with_signs(signs):
num_verts = len(signs)
random_points_on_plane = plane.project_point(rand_nonzero(num_verts, 3))
random_displacement_along_normal = (
rand_nonzero(num_verts).reshape(-1, 1) * plane_normal
)
vertices = (
random_points_on_plane + signs.reshape(-1, 1) * random_displacement_along_normal
)
# Because of rounding, the random points don't necessarily return 0 for
# sign, so pick one that does.
vertices[signs == 0] = plane.reference_point
> np.testing.assert_array_equal(plane.sign(vertices), signs)
E AssertionError:
E Arrays are not equal
E
E Mismatched elements: 1 / 9 (11.1%)
E Max absolute difference: 1.
E Max relative difference: 0.
E x: array([-1., -1., -1., -1., -1., 1., 1., 1., 1.])
E y: array([-1, -1, -1, -1, -1, 0, 1, 1, 1])
polliwog/polyline/test_slice_by_plane.py:28: AssertionError
___________________ test_open_starts_on_plane_ends_in_front ____________________
def test_open_starts_on_plane_ends_in_front():
signs = np.array([0, 1, 1, 1, 1])
> vertices = vertices_with_signs(signs)
polliwog/polyline/test_slice_by_plane.py:97:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
signs = array([0, 1, 1, 1, 1])
def vertices_with_signs(signs):
num_verts = len(signs)
random_points_on_plane = plane.project_point(rand_nonzero(num_verts, 3))
random_displacement_along_normal = (
rand_nonzero(num_verts).reshape(-1, 1) * plane_normal
)
vertices = (
random_points_on_plane + signs.reshape(-1, 1) * random_displacement_along_normal
)
# Because of rounding, the random points don't necessarily return 0 for
# sign, so pick one that does.
vertices[signs == 0] = plane.reference_point
> np.testing.assert_array_equal(plane.sign(vertices), signs)
E AssertionError:
E Arrays are not equal
E
E Mismatched elements: 1 / 5 (20%)
E Max absolute difference: 1.
E Max relative difference: 0.
E x: array([1., 1., 1., 1., 1.])
E y: array([0, 1, 1, 1, 1])
polliwog/polyline/test_slice_by_plane.py:28: AssertionError
____________ test_open_starts_with_edges_along_plane_ends_in_front _____________
def test_open_starts_with_edges_along_plane_ends_in_front():
signs = np.array([0, 0, 1, 1, 1, 1])
> vertices = vertices_with_signs(signs)
polliwog/polyline/test_slice_by_plane.py:106:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
signs = array([0, 0, 1, 1, 1, 1])
def vertices_with_signs(signs):
num_verts = len(signs)
random_points_on_plane = plane.project_point(rand_nonzero(num_verts, 3))
random_displacement_along_normal = (
rand_nonzero(num_verts).reshape(-1, 1) * plane_normal
)
vertices = (
random_points_on_plane + signs.reshape(-1, 1) * random_displacement_along_normal
)
# Because of rounding, the random points don't necessarily return 0 for
# sign, so pick one that does.
vertices[signs == 0] = plane.reference_point
> np.testing.assert_array_equal(plane.sign(vertices), signs)
E AssertionError:
E Arrays are not equal
E
E Mismatched elements: 2 / 6 (33.3%)
E Max absolute difference: 1.
E Max relative difference: 0.
E x: array([1., 1., 1., 1., 1., 1.])
E y: array([0, 0, 1, 1, 1, 1])
polliwog/polyline/test_slice_by_plane.py:28: AssertionError
____________________ test_open_starts_on_plane_ends_in_back ____________________
def test_open_starts_on_plane_ends_in_back():
signs = np.array([0, -1, -1, -1, -1])
> vertices = vertices_with_signs(signs)
polliwog/polyline/test_slice_by_plane.py:115:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
signs = array([ 0, -1, -1, -1, -1])
def vertices_with_signs(signs):
num_verts = len(signs)
random_points_on_plane = plane.project_point(rand_nonzero(num_verts, 3))
random_displacement_along_normal = (
rand_nonzero(num_verts).reshape(-1, 1) * plane_normal
)
vertices = (
random_points_on_plane + signs.reshape(-1, 1) * random_displacement_along_normal
)
# Because of rounding, the random points don't necessarily return 0 for
# sign, so pick one that does.
vertices[signs == 0] = plane.reference_point
> np.testing.assert_array_equal(plane.sign(vertices), signs)
E AssertionError:
E Arrays are not equal
E
E Mismatched elements: 1 / 5 (20%)
E Max absolute difference: 1.
E Max relative difference: 0.
E x: array([ 1., -1., -1., -1., -1.])
E y: array([ 0, -1, -1, -1, -1])
polliwog/polyline/test_slice_by_plane.py:28: AssertionError
___________________ test_open_starts_in_front_ends_on_plane ____________________
def test_open_starts_in_front_ends_on_plane():
signs = np.array([1, 1, 1, 1, 0])
> vertices = vertices_with_signs(signs)
polliwog/polyline/test_slice_by_plane.py:125:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
signs = array([1, 1, 1, 1, 0])
def vertices_with_signs(signs):
num_verts = len(signs)
random_points_on_plane = plane.project_point(rand_nonzero(num_verts, 3))
random_displacement_along_normal = (
rand_nonzero(num_verts).reshape(-1, 1) * plane_normal
)
vertices = (
random_points_on_plane + signs.reshape(-1, 1) * random_displacement_along_normal
)
# Because of rounding, the random points don't necessarily return 0 for
# sign, so pick one that does.
vertices[signs == 0] = plane.reference_point
> np.testing.assert_array_equal(plane.sign(vertices), signs)
E AssertionError:
E Arrays are not equal
E
E Mismatched elements: 1 / 5 (20%)
E Max absolute difference: 1.
E Max relative difference: 0.
E x: array([1., 1., 1., 1., 1.])
E y: array([1, 1, 1, 1, 0])
polliwog/polyline/test_slice_by_plane.py:28: AssertionError
____________ test_open_starts_in_front_ends_with_edges_along_plane _____________
def test_open_starts_in_front_ends_with_edges_along_plane():
signs = np.array([1, 1, 1, 1, 0, 0])
> vertices = vertices_with_signs(signs)
polliwog/polyline/test_slice_by_plane.py:134:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
signs = array([1, 1, 1, 1, 0, 0])
def vertices_with_signs(signs):
num_verts = len(signs)
random_points_on_plane = plane.project_point(rand_nonzero(num_verts, 3))
random_displacement_along_normal = (
rand_nonzero(num_verts).reshape(-1, 1) * plane_normal
)
vertices = (
random_points_on_plane + signs.reshape(-1, 1) * random_displacement_along_normal
)
# Because of rounding, the random points don't necessarily return 0 for
# sign, so pick one that does.
vertices[signs == 0] = plane.reference_point
> np.testing.assert_array_equal(plane.sign(vertices), signs)
E AssertionError:
E Arrays are not equal
E
E Mismatched elements: 2 / 6 (33.3%)
E Max absolute difference: 1.
E Max relative difference: 0.
E x: array([1., 1., 1., 1., 1., 1.])
E y: array([1, 1, 1, 1, 0, 0])
polliwog/polyline/test_slice_by_plane.py:28: AssertionError
_____________________ test_open_in_back_then_ends_on_plane _____________________
def test_open_in_back_then_ends_on_plane():
signs = np.array([-1, -1, -1, -1, 0])
> vertices = vertices_with_signs(signs)
polliwog/polyline/test_slice_by_plane.py:143:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
signs = array([-1, -1, -1, -1, 0])
def vertices_with_signs(signs):
num_verts = len(signs)
random_points_on_plane = plane.project_point(rand_nonzero(num_verts, 3))
random_displacement_along_normal = (
rand_nonzero(num_verts).reshape(-1, 1) * plane_normal
)
vertices = (
random_points_on_plane + signs.reshape(-1, 1) * random_displacement_along_normal
)
# Because of rounding, the random points don't necessarily return 0 for
# sign, so pick one that does.
vertices[signs == 0] = plane.reference_point
> np.testing.assert_array_equal(plane.sign(vertices), signs)
E AssertionError:
E Arrays are not equal
E
E Mismatched elements: 1 / 5 (20%)
E Max absolute difference: 1.
E Max relative difference: 0.
E x: array([-1., -1., -1., -1., 1.])
E y: array([-1, -1, -1, -1, 0])
polliwog/polyline/test_slice_by_plane.py:28: AssertionError
________ test_open_starts_in_front_then_along_plane_then_in_front_again ________
def test_open_starts_in_front_then_along_plane_then_in_front_again():
signs = np.array([1, 1, 0, 0, 1])
> vertices = vertices_with_signs(signs)
polliwog/polyline/test_slice_by_plane.py:153:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
signs = array([1, 1, 0, 0, 1])
def vertices_with_signs(signs):
num_verts = len(signs)
random_points_on_plane = plane.project_point(rand_nonzero(num_verts, 3))
random_displacement_along_normal = (
rand_nonzero(num_verts).reshape(-1, 1) * plane_normal
)
vertices = (
random_points_on_plane + signs.reshape(-1, 1) * random_displacement_along_normal
)
# Because of rounding, the random points don't necessarily return 0 for
# sign, so pick one that does.
vertices[signs == 0] = plane.reference_point
> np.testing.assert_array_equal(plane.sign(vertices), signs)
E AssertionError:
E Arrays are not equal
E
E Mismatched elements: 2 / 5 (40%)
E Max absolute difference: 1.
E Max relative difference: 0.
E x: array([1., 1., 1., 1., 1.])
E y: array([1, 1, 0, 0, 1])
polliwog/polyline/test_slice_by_plane.py:28: AssertionError
__ test_open_starts_in_back_then_along_plane_then_in_front_then_in_back_again __
def test_open_starts_in_back_then_along_plane_then_in_front_then_in_back_again():
signs = np.array([-1, -1, 0, 0, 1, 1, 1, -1, -1])
> vertices = vertices_with_signs(signs)
polliwog/polyline/test_slice_by_plane.py:181:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
signs = array([-1, -1, 0, 0, 1, 1, 1, -1, -1])
def vertices_with_signs(signs):
num_verts = len(signs)
random_points_on_plane = plane.project_point(rand_nonzero(num_verts, 3))
random_displacement_along_normal = (
rand_nonzero(num_verts).reshape(-1, 1) * plane_normal
)
vertices = (
random_points_on_plane + signs.reshape(-1, 1) * random_displacement_along_normal
)
# Because of rounding, the random points don't necessarily return 0 for
# sign, so pick one that does.
vertices[signs == 0] = plane.reference_point
> np.testing.assert_array_equal(plane.sign(vertices), signs)
E AssertionError:
E Arrays are not equal
E
E Mismatched elements: 2 / 9 (22.2%)
E Max absolute difference: 1.
E Max relative difference: 0.
E x: array([-1., -1., 1., 1., 1., 1., 1., -1., -1.])
E y: array([-1, -1, 0, 0, 1, 1, 1, -1, -1])
polliwog/polyline/test_slice_by_plane.py:28: AssertionError
___________ test_open_starts_in_front_then_along_plane_then_in_back ____________
def test_open_starts_in_front_then_along_plane_then_in_back():
signs = np.array([1, 1, 0, 0, -1])
> vertices = vertices_with_signs(signs)
polliwog/polyline/test_slice_by_plane.py:199:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
signs = array([ 1, 1, 0, 0, -1])
def vertices_with_signs(signs):
num_verts = len(signs)
random_points_on_plane = plane.project_point(rand_nonzero(num_verts, 3))
random_displacement_along_normal = (
rand_nonzero(num_verts).reshape(-1, 1) * plane_normal
)
vertices = (
random_points_on_plane + signs.reshape(-1, 1) * random_displacement_along_normal
)
# Because of rounding, the random points don't necessarily return 0 for
# sign, so pick one that does.
vertices[signs == 0] = plane.reference_point
> np.testing.assert_array_equal(plane.sign(vertices), signs)
E AssertionError:
E Arrays are not equal
E
E Mismatched elements: 2 / 5 (40%)
E Max absolute difference: 1.
E Max relative difference: 0.
E x: array([ 1., 1., 1., 1., -1.])
E y: array([ 1, 1, 0, 0, -1])
polliwog/polyline/test_slice_by_plane.py:28: AssertionError
____________________________ test_open_all_in_plane ____________________________
def test_open_all_in_plane():
signs = np.array([0, 0])
> vertices = vertices_with_signs(signs)
polliwog/polyline/test_slice_by_plane.py:228:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
signs = array([0, 0])
def vertices_with_signs(signs):
num_verts = len(signs)
random_points_on_plane = plane.project_point(rand_nonzero(num_verts, 3))
random_displacement_along_normal = (
rand_nonzero(num_verts).reshape(-1, 1) * plane_normal
)
vertices = (
random_points_on_plane + signs.reshape(-1, 1) * random_displacement_along_normal
)
# Because of rounding, the random points don't necessarily return 0 for
# sign, so pick one that does.
vertices[signs == 0] = plane.reference_point
> np.testing.assert_array_equal(plane.sign(vertices), signs)
E AssertionError:
E Arrays are not equal
E
E Mismatched elements: 2 / 2 (100%)
E Max absolute difference: 1.
E Max relative difference: inf
E x: array([1., 1.])
E y: array([0, 0])
polliwog/polyline/test_slice_by_plane.py:28: AssertionError
_________________________ test_open_one_vert_on_plane __________________________
def test_open_one_vert_on_plane():
signs = np.array([0])
> vertices = vertices_with_signs(signs)
polliwog/polyline/test_slice_by_plane.py:258:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
signs = array([0])
def vertices_with_signs(signs):
num_verts = len(signs)
random_points_on_plane = plane.project_point(rand_nonzero(num_verts, 3))
random_displacement_along_normal = (
rand_nonzero(num_verts).reshape(-1, 1) * plane_normal
)
vertices = (
random_points_on_plane + signs.reshape(-1, 1) * random_displacement_along_normal
)
# Because of rounding, the random points don't necessarily return 0 for
# sign, so pick one that does.
vertices[signs == 0] = plane.reference_point
> np.testing.assert_array_equal(plane.sign(vertices), signs)
E AssertionError:
E Arrays are not equal
E
E Mismatched elements: 1 / 1 (100%)
E Max absolute difference: 1.
E Max relative difference: inf
E x: array([1.])
E y: array([0])
polliwog/polyline/test_slice_by_plane.py:28: AssertionError
Closes #198
@paulmelnikow Can you confirm that the idea behind this PR is to work around small numerical precision differences in Numpy 1.19 between your local OS X development machine, and the remote Linux CI server?
I forget whether or not it's reproducible on OS X. Though yes, the way I'd put it is that the goal is to make the code work the same in NumPy 1.19 on Linux as it did in earlier versions of NumPy on Linux.
These tests started failing when NumPy 1.19 was released and I had to pin the NumPy version back to 1.18 to get them working again.
I can re-check OS X tomorrow if it's helpful.
I am fine with this fix, but I wonder if it would be better to regard it as a workaround to a regression in numpy. Do you think this is an issue that should get reported upstream?
I am fine with this fix, but I wonder if it would be better to regard it as a workaround to a regression in numpy. Do you think this is an issue that should get reported upstream?
I do not know for sure whether or not this is a regression. It's possible. Though in general, I do not expect floating point multiplication and division to produce values which exactly equal zero. However that's what NumPy used to do until 1.19.
It's not the first time a NumPy upgrade has caused unexpected regressions in downstream code. I do know that NumPy 1.19 dropped Python 2 and a bunch of legacy code along the way.
Would you like to try to isolate the issue and report it?
I do think if this is a temporary workaround for a regression we should mark it up in the codebase with TODO comments.
Let's confirm with upstream numpy that this is the expected behavior going forward, then merge this PR into our codebase.