Skip to content

Commit 5e2ba97

Browse files
authored
Accelerated AbstractPolygonalAperture using numba. (#145)
1 parent 73f7d16 commit 5e2ba97

File tree

4 files changed

+35
-27
lines changed

4 files changed

+35
-27
lines changed

.github/workflows/tests.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ jobs:
1818
windows-latest,
1919
macOS-latest,
2020
]
21-
python-version: ["3.10", "3.12"]
22-
name: ${{ matrix.os }}, Python ${{ matrix.python-version }} lint and test
21+
python-version: ["3.11", "3.13"]
22+
name: ${{ matrix.os }}, Python ${{ matrix.python-version }} tests
2323
steps:
2424
- uses: actions/checkout@v4
2525
- name: Set up Python ${{ matrix.python-version }}

optika/apertures/_apertures.py

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ class CircularSectorAperture(
374374
"""
375375

376376
angle_stop: u.Quantity | na.AbstractScalar = 180 * u.deg
377-
"""
377+
r"""
378378
The ending angle of the circular sector.
379379
Must be between :math:`-2 \pi` and :math:`+2 \pi` radians and
380380
counterclockwise from `angle_start`.
@@ -606,34 +606,40 @@ def __call__(
606606
self,
607607
position: na.AbstractCartesian3dVectorArray,
608608
) -> na.AbstractScalar:
609+
609610
vertices = self.vertices
610611
active = self.active
611612
inverted = self.inverted
613+
612614
if self.transformation is not None:
613615
position = self.transformation.inverse(position)
614616

615-
shape = na.shape_broadcasted(
616-
vertices[dict(vertex=0)],
617-
active,
618-
inverted,
619-
position,
620-
)
617+
if np.any(active):
618+
result = na.geometry.point_in_polygon(
619+
x=position.x,
620+
y=position.y,
621+
vertices_x=vertices.x,
622+
vertices_y=vertices.y,
623+
axis="vertex",
624+
)
621625

622-
active = na.broadcast_to(active, shape)
623-
inverted = na.broadcast_to(inverted, shape)
624-
position = na.broadcast_to(position, shape)
626+
if np.any(inverted):
627+
if np.all(inverted):
628+
result = ~result
629+
else:
630+
shape_inverted = na.shape_broadcasted(result, inverted)
631+
if shape_inverted != result.shape:
632+
result = na.broadcast_to(result, shape_inverted).copy()
633+
result[inverted] = ~result[inverted]
634+
635+
if not np.all(active):
636+
shape_active = na.shape_broadcasted(result, active)
637+
if shape_active != result.shape:
638+
result = na.broadcast_to(result, shape_active).copy()
639+
result[~active] = True
625640

626-
result = False
627-
for v in range(vertices.shape["vertex"]):
628-
vert_j = na.broadcast_to(vertices[dict(vertex=v - 1)], shape)
629-
vert_i = na.broadcast_to(vertices[dict(vertex=v)], shape)
630-
slope = (vert_j.y - vert_i.y) / (vert_j.x - vert_i.x)
631-
condition_1 = (vert_i.y > position.y) != (vert_j.y > position.y)
632-
condition_2 = position.x < ((position.y - vert_i.y) / slope + vert_i.x)
633-
result = result ^ (condition_1 & condition_2)
634-
635-
result[inverted] = ~result[inverted]
636-
result[~active] = True
641+
else:
642+
result = na.ScalarArray(True)
637643

638644
return result
639645

optika/apertures/_apertures_test.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010

1111
active_parameterization = [
1212
True,
13+
False,
1314
na.linspace(-1, 1, "active", 3) >= 0,
1415
]
1516

1617
inverted_parameterization = [
18+
True,
1719
False,
1820
na.linspace(-1, 1, "inverted", 4) >= 0,
1921
]
@@ -52,7 +54,8 @@ def test__call__(self, a: optika.apertures.AbstractAperture):
5254

5355
result = a(position)
5456
assert np.issubdtype(na.get_dtype(result), bool)
55-
assert np.any(result)
57+
58+
assert np.all(result[~na.as_named_array(a.active)])
5659

5760
@pytest.mark.parametrize("rays", optika.rays._tests.test_ray_vectors.rays)
5861
def test_clip_rays(

pyproject.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ authors = [
99
]
1010
description = "A Python library for simulating optical systems, similar to Zemax"
1111
readme = "README.md"
12-
requires-python = ">=3.10"
12+
requires-python = ">=3.11"
1313
classifiers = [
1414
"Programming Language :: Python :: 3",
1515
]
1616
dependencies = [
1717
"astropy!=6.1.5",
18-
"named-arrays>=0.27.1",
18+
"named-arrays~=1.0",
1919
"pymupdf",
2020
"joblib",
2121
]
@@ -29,7 +29,6 @@ doc = [
2929
"pytest",
3030
"matplotlib",
3131
"graphviz",
32-
"Sphinx<8.2",
3332
"sphinx-autodoc-typehints",
3433
"sphinxcontrib-bibtex",
3534
"pydata-sphinx-theme",

0 commit comments

Comments
 (0)