Skip to content

Commit

Permalink
Added optika.apertures.IsoscelesTrapezoidalAperture.
Browse files Browse the repository at this point in the history
  • Loading branch information
byrdie committed Oct 8, 2023
1 parent 728c1c5 commit f1cb71d
Show file tree
Hide file tree
Showing 2 changed files with 143 additions and 0 deletions.
45 changes: 45 additions & 0 deletions optika/_tests/test_apertures.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,3 +226,48 @@ class TestOctagonalAperture(
AbstractTestAbstractOctagonalAperture,
):
pass


class AbstractTestAbstractIsoscelesTrapezoidalAperture(
AbstractTestAbstractPolygonalAperture,
):
def test_x_left(self, a: optika.apertures.AbstractIsoscelesTrapezoidalAperture):
assert isinstance(na.as_named_array(a.x_left), na.AbstractScalar)

def test_x_right(self, a: optika.apertures.AbstractIsoscelesTrapezoidalAperture):
assert isinstance(na.as_named_array(a.x_right), na.AbstractScalar)

def test_angle(self, a: optika.apertures.AbstractIsoscelesTrapezoidalAperture):
assert isinstance(na.as_named_array(a.angle), na.AbstractScalar)


x_left_parameterization = [
25 * u.mm,
na.linspace(25, 30, axis="x_left", num=2) * u.mm,
]


@pytest.mark.parametrize(
argnames="a",
argvalues=[
optika.apertures.IsoscelesTrapezoidalAperture(
x_left=x_left,
x_right=50 * u.mm,
angle=45 * u.deg,
samples_wire=21,
active=active,
inverted=inverted,
transformation=transformation,
kwargs_plot=kwargs_plot,
)
for x_left in x_left_parameterization
for active in active_parameterization
for inverted in inverted_parameterization
for transformation in transform_parameterization
for kwargs_plot in test_plotting.kwargs_plot_parameterization
],
)
class TestIsoscelesTrapezoidalAperture(
AbstractTestAbstractIsoscelesTrapezoidalAperture,
):
pass
98 changes: 98 additions & 0 deletions optika/apertures.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
"AbstractRegularPolygonalAperture",
"AbstractOctagonalAperture",
"OctagonalAperture",
"AbstractIsoscelesTrapezoidalAperture",
"IsoscelesTrapezoidalAperture",
]


Expand Down Expand Up @@ -564,3 +566,99 @@ class OctagonalAperture(
inverted: bool | na.AbstractScalar = False
transformation: None | na.transformations.AbstractTransformation = None
kwargs_plot: None | dict = None


@dataclasses.dataclass(eq=False, repr=False)
class AbstractIsoscelesTrapezoidalAperture(
AbstractPolygonalAperture,
):
@property
@abc.abstractmethod
def x_left(self) -> na.ScalarLike:
""":math:`x` coordinate of the left base of the trapezoid"""

@property
@abc.abstractmethod
def x_right(self) -> na.ScalarLike:
""":math:`x` coordinate of the right base of the trapezoid"""

@property
@abc.abstractmethod
def angle(self) -> na.ScalarLike:
"""angle between the two legs of the trapezoid"""

@property
def vertices(self) -> na.Cartesian3dVectorArray:
x_left = self.x_left
x_right = self.x_right
angle = self.angle

m = np.tan(angle / 2)
left = na.Cartesian3dVectorArray(
x=x_left,
y=m * x_left,
z=0 * x_left,
)
right = na.Cartesian3dVectorArray(
x=x_right,
y=m * x_right,
z=0 * x_right,
)

upper = na.stack([left, right], axis="vertex")

lower = upper[dict(vertex=slice(None, None, -1))]
lower = lower * na.Cartesian3dVectorArray(1, -1, 1)

result = na.concatenate([upper, lower], axis="vertex")

if self.transformation is not None:
result = self.transformation(result)

return result


@dataclasses.dataclass(eq=False, repr=False)
class IsoscelesTrapezoidalAperture(
AbstractIsoscelesTrapezoidalAperture,
):
"""
This aperture is useful if you want to break a circular aperture up
into different sectors.
.. jupyter-execute::
import matplotlib.pyplot as plt
import astropy.units as u
import astropy.visualization
import named_arrays as na
import optika
num_sectors = 8
roll = na.linspace(0, 360, axis="roll", num=num_sectors, endpoint=False) * u.deg
aperture = optika.apertures.IsoscelesTrapezoidalAperture(
x_left=10 * u.mm,
x_right=40 * u.mm,
angle=(360 * u.deg) / num_sectors,
transformation=na.transformations.TransformationList([
na.transformations.Cartesian3dTranslation(x=5 * u.mm),
na.transformations.Cartesian3dRotationZ(roll),
])
)
with astropy.visualization.quantity_support():
plt.figure()
plt.gca().set_aspect("equal")
aperture.plot(components=("x", "y"), color="black")
"""

x_left: na.ScalarLike = 0 * u.mm
x_right: na.ScalarLike = 0 * u.mm
angle: na.ScalarLike = 0 * u.deg
samples_wire: int = 101
active: bool | na.AbstractScalar = True
inverted: bool | na.AbstractScalar = False
transformation: None | na.transformations.AbstractTransformation = None
kwargs_plot: None | dict = None

0 comments on commit f1cb71d

Please sign in to comment.