Skip to content

Commit

Permalink
Merge pull request #233 from spacetelescope/feature/delta-example-sim…
Browse files Browse the repository at this point in the history
…ulator

Add example optical model and example simulator
  • Loading branch information
erinpougheon authored Jul 19, 2024
2 parents aaea162 + 124fa02 commit 8f235c3
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 3 deletions.
4 changes: 2 additions & 2 deletions testbed_example/config/services.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
simulator:
service_type: simple_simulator
service_type: example_simulator
requires_safety: false

science_camera:
detector:
service_type: allied_vision_camera
simulated_service_type: camera_sim
interface: camera
Expand Down
7 changes: 7 additions & 0 deletions testbed_example/config/simulator.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pupil_mask:
diameter: 1
grid_size: 1.1

detector:
pixel_size: 6.5e-6
roi: 400
2 changes: 1 addition & 1 deletion testbed_example/config/testbed.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
default_port: 1234
simulator:
service_id: simple_simulator
service_id: example_simulator
startup_services: []
base_data_path:
default: !path "~/catkit2_example_data"
Expand Down
52 changes: 52 additions & 0 deletions testbed_example/example_optical_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from catkit2.simulator import OpticalModel, with_cached_result
import hcipy
import numpy as np


class ExampleOpticalModel(OpticalModel):
"""An example optical model for use with the example testbed.
This class simulates a simple pupil mask and simple science camera. All parameters are read from
the simulator configuration file, testbed_example/config/simulator.yml.
"""
def __init__(self, config):
super().__init__()

self.config = config

@self.register_plane('detector', 'pupil')
def detector(wf):
return self.prop(wf)

@self.register_plane('pupil', 'light_source')
def pupil(wf):
return self.pupil_mask(wf)

@property
def pupil_grid(self):
dimensions = self.config['pupil_mask']['dimensions']
dims = np.array([dimensions, dimensions])
size = self.config['pupil_mask']['grid_size']

return hcipy.make_uniform_grid(dims, size)

@property
def detector_grid(self):
roi = self.config['detector']['roi']
dims = np.array([roi, roi])
pixel_size = self.config['detector']['pixel_size']

return hcipy.make_uniform_grid(dims, dims * pixel_size)

@property
@with_cached_result
def prop(self):
return hcipy.FraunhoferPropagator(self.pupil_grid, self.detector_grid)

@property
@with_cached_result
def pupil_mask(self):
diameter = self.config['pupil_mask']['diameter']
mask = hcipy.circular_aperture(diameter)(self.pupil_grid)

return hcipy.Apodizer(mask)
40 changes: 40 additions & 0 deletions testbed_example/services/example_simulator/example_simulator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from catkit2.simulator import Simulator
from testbed_example.example_optical_model import ExampleOpticalModel
import hcipy


class ExampleSimulator(Simulator):
"""A very simple example simulator for the example testbed.
This service provides the simulator interface to the connected optical model.
"""
def __init__(self):
super().__init__('example_simulator')

def open(self):
self.model = ExampleOpticalModel()
wavefronts = [hcipy.Wavefront(self.model.pupil_grid.ones() * 1e6)]
self.model.set_wavefronts('pre_pupil', wavefronts)

self.images = self.make_data_stream('images', 'float64', self.model.focal_grid.shape, 20)

def camera_readout(self, camera_name, power):
image = power.shaped
image = hcipy.large_poisson(image)
image[image > 2**16] = 2**16
image = image.astype('float32')

try:
self.testbed.detector.images.update_parameters('float32', image.shape, 20)
self.testbed.detector.images.submit_data(image)
except Exception as e:
self.log.error(str(e))

def get_camera_power(self, camera_name):
wavefronts = self.model.get_wavefronts(camera_name)
return sum(wf.power for wf in wavefronts)


if __name__ == '__main__':
service = ExampleSimulator()
service.run()

0 comments on commit 8f235c3

Please sign in to comment.