From b132edadc34b3b473cad07967023df6e980f8a14 Mon Sep 17 00:00:00 2001 From: "William F. Broderick" Date: Wed, 13 Nov 2024 12:00:49 -0500 Subject: [PATCH 1/3] remove unnecessary deprecated --- src/plenoptic/tools/data.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plenoptic/tools/data.py b/src/plenoptic/tools/data.py index 79835d9f..266788e8 100644 --- a/src/plenoptic/tools/data.py +++ b/src/plenoptic/tools/data.py @@ -159,7 +159,6 @@ def load_images(paths: str | list[str], as_gray: bool = True) -> Tensor: return images -@deprecated("Load images using :py:func:`load_images` instead", "1.1.0") def convert_float_to_int(im: np.ndarray, dtype=np.uint8) -> np.ndarray: r"""Convert image from float to 8 or 16 bit image From 1602604973d937aaff203efeb2d380dcd6a7264d Mon Sep 17 00:00:00 2001 From: "William F. Broderick" Date: Wed, 13 Nov 2024 12:20:17 -0500 Subject: [PATCH 2/3] adds direction arg to polar_angle --- src/plenoptic/tools/data.py | 21 ++++++++++++++++++--- tests/test_tools.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/src/plenoptic/tools/data.py b/src/plenoptic/tools/data.py index 266788e8..2d493412 100644 --- a/src/plenoptic/tools/data.py +++ b/src/plenoptic/tools/data.py @@ -1,6 +1,7 @@ import contextlib import pathlib import warnings +from typing import Literal import imageio import numpy as np @@ -345,13 +346,14 @@ def polar_angle( size: int | tuple[int, int], phase: float = 0.0, origin: int | tuple[float, float] | None = None, + direction: Literal["clockwise", "counter-clockwise"] = "clockwise", device: torch.device | None = None, ) -> Tensor: """Make polar angle matrix (in radians). - Compute a matrix of given size containing samples of the polar angle (in radians, CW - from the X-axis, ranging from -pi to pi), relative to given phase, about the given - origin pixel. + Compute a matrix of given size containing samples of the polar angle (in radians, + increasing in user-defined direction from the X-axis, ranging from -pi to pi), + relative to given phase, about the given origin pixel. Parameters ---------- @@ -365,6 +367,10 @@ def polar_angle( `(origin, origin)`. if a tuple, must be a 2-tuple of ints specifying the origin (where `(0, 0)` is the upper left). If None, we assume the origin lies at the center of the matrix, `(size+1)/2`. + direction + Whether the angle increases in a clockwise or counter-clockwise direction from + the x-axis. The standard mathematical convention is to increase + counter-clockwise, so that 90 degrees corresponds to the positive y-axis. device The device to create this tensor on. @@ -372,7 +378,14 @@ def polar_angle( ------- res The polar angle matrix + """ + if direction not in ["clockwise", "counter-clockwise"]: + raise ValueError( + "direction must be one of {'clockwise', 'counter-clockwise'}, " + f"but received {direction}!" + ) + if not hasattr(size, "__iter__"): size = (size, size) @@ -390,6 +403,8 @@ def polar_angle( torch.arange(1, size[0] + 1, device=device) - origin[0], torch.arange(1, size[1] + 1, device=device) - origin[1], ) + if direction == "counter-clockwise": + yramp = torch.flip(yramp, [0]) res = torch.atan2(yramp, xramp) diff --git a/tests/test_tools.py b/tests/test_tools.py index 03697d5c..04ee49f5 100644 --- a/tests/test_tools.py +++ b/tests/test_tools.py @@ -578,3 +578,31 @@ def test_penalize_range_below(self): img = 0.5 * torch.ones((1, 1, 4, 4)) img[..., 0, :] = -1 assert po.tools.optim.penalize_range(img).item() == 4 + + +class TestPolarImages: + def test_polar_angle_clockwise(self): + ang = po.tools.polar_angle(100, direction="clockwise") + idx = np.argmin((ang - np.pi / 2) ** 2) + assert ( + np.unravel_index(idx, (100, 100))[0] > 50 + ), "pi/2 should be in bottom half of image!" + idx = np.argmin((ang + np.pi / 2) ** 2) + assert ( + np.unravel_index(idx, (100, 100))[0] < 50 + ), "pi/2 should be in top half of image!" + + def test_polar_angle_counterclockwise(self): + ang = po.tools.polar_angle(100, direction="counter-clockwise") + idx = np.argmin((ang - np.pi / 2) ** 2) + assert ( + np.unravel_index(idx, (100, 100))[0] < 50 + ), "pi/2 should be in top half of image!" + idx = np.argmin((ang + np.pi / 2) ** 2) + assert ( + np.unravel_index(idx, (100, 100))[0] > 50 + ), "pi/2 should be in bottom half of image!" + + def test_polar_angle_direction(self): + with pytest.raises(ValueError, match="direction must be one of"): + po.tools.polar_angle(100, direction="-clockwise") From f0024465eeebf07bd1e9dfe3285380f4509b36b4 Mon Sep 17 00:00:00 2001 From: "William F. Broderick" Date: Fri, 15 Nov 2024 12:46:01 -0500 Subject: [PATCH 3/3] adds longer desription --- src/plenoptic/tools/data.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/plenoptic/tools/data.py b/src/plenoptic/tools/data.py index 2d493412..85d02103 100644 --- a/src/plenoptic/tools/data.py +++ b/src/plenoptic/tools/data.py @@ -355,6 +355,10 @@ def polar_angle( increasing in user-defined direction from the X-axis, ranging from -pi to pi), relative to given phase, about the given origin pixel. + Note that by default, the angle increases in a clockwise direction, which is NOT the + standard mathematical convention. Use the ``direction`` argument to change that + behavior. + Parameters ---------- size