Skip to content

Commit

Permalink
Add Keck Lyot stop that was originally in #155
Browse files Browse the repository at this point in the history
  • Loading branch information
ivalaginja committed Feb 25, 2023
1 parent 87ca967 commit 76f8ac8
Showing 1 changed file with 73 additions and 0 deletions.
73 changes: 73 additions & 0 deletions hcipy/aperture/realistic.py
Original file line number Diff line number Diff line change
Expand Up @@ -1519,3 +1519,76 @@ def func(grid):
segments = [segment_with_strut(segment) for segment in segments]

return func, segments

def make_keck_lyot_stop(normalized=True, gap_padding=10, segment_transmissions=1):
"""Make the Keck L-band Lyot stop.
Create the L-band Lyot stop used with the vortex charge 2 coronagraph that is installed on Keck 2
that is available for science with NIRC2. The values were extracted from drawings of the mask
and represent that mask installed around 2018 that is currently available in 2022.
Parameters
----------
normalized : boolean
If this is True, the outer diameter will be scaled to 1. Otherwise, the
diameter of the pupil will be 10.95 meters.
gap_padding : scalar
Arbitrary padding of gap size to represent gaps on smaller arrays - this effectively
makes the gaps larger and the segments smaller to preserve the same segment pitch.
segment_transmissions : scalar or array_like
The transmission for each of the segments. If this is a scalar, this transmission
will be used for all segments.
Returns
-------
lyot_stop : Field generator
A field generator for the Lyot stop.
"""
conversion = 10.95 / (2 * 12.05 / 1000) # based on drawing
pupil_diameter = 10.95 # m actual circumscribed diameter
actual_segment_flat_diameter = np.sqrt(3) / 2 * 0.00337 * conversion # m actual segment flat-to-flat diameter
central_obscuration_diameter = 0.00698 * conversion
actual_segment_gap = 0#0.003 # m actual gap size between segments
spider_width = 0.0005 * conversion # m actual strut size
num_rings = 3 # number of full rings of hexagons around central segment

if normalized:
actual_segment_flat_diameter /= pupil_diameter
actual_segment_gap /= pupil_diameter
spider_width /= pupil_diameter
central_obscuration_diameter /= pupil_diameter
pupil_diameter = 1.0

# padding out the segmentation gaps so they are visible and not sub-pixel
segment_gap = actual_segment_gap * gap_padding

segment_flat_diameter = actual_segment_flat_diameter - (segment_gap - actual_segment_gap)
segment_circum_diameter = 2 / np.sqrt(3) * segment_flat_diameter # segment circumscribed diameter

segment_positions = make_hexagonal_grid(actual_segment_flat_diameter + actual_segment_gap, num_rings)
segment_positions = segment_positions.subset(lambda grid: ~(make_circular_aperture(segment_circum_diameter)(grid) > 0))

segment = make_hexagonal_aperture(segment_circum_diameter, np.pi / 2)

spider1 = make_spider_infinite([0, 0], 0, spider_width)
spider2 = make_spider_infinite([0, 0], 60, spider_width)
spider3 = make_spider_infinite([0, 0], 120, spider_width)
spider4 = make_spider_infinite([0, 0], 180, spider_width)
spider5 = make_spider_infinite([0, 0], 240, spider_width)
spider6 = make_spider_infinite([0, 0], 300, spider_width)

segmented_aperture = make_segmented_aperture(segment, segment_positions, segment_transmissions, return_segments=True)
segmentation, segments = segmented_aperture

def segment_with_spider(segment):
return lambda grid: segment(grid) * spider1(grid) * spider2(grid) * spider3(grid) * spider4(grid) * spider5(grid) * spider6(grid)

segments = [segment_with_spider(s) for s in segments]
contour = make_segmented_aperture(segment, segment_positions)

def func(grid):
res = contour(grid)
res *= make_circular_aperture(central_obscuration_diameter)(grid)
return Field(res, grid)

return func

0 comments on commit 76f8ac8

Please sign in to comment.