diff --git a/testbed_example/config/services.yml b/testbed_example/config/services.yml index 700fa363..c0db8682 100644 --- a/testbed_example/config/services.yml +++ b/testbed_example/config/services.yml @@ -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 diff --git a/testbed_example/config/simulator.yml b/testbed_example/config/simulator.yml new file mode 100644 index 00000000..fc954351 --- /dev/null +++ b/testbed_example/config/simulator.yml @@ -0,0 +1,7 @@ +pupil_mask: + diameter: 1 + grid_size: 1.1 + +detector: + pixel_size: 6.5e-6 + roi: 400 diff --git a/testbed_example/config/testbed.yml b/testbed_example/config/testbed.yml index 0396e89c..e8eb06cf 100644 --- a/testbed_example/config/testbed.yml +++ b/testbed_example/config/testbed.yml @@ -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" diff --git a/testbed_example/example_optical_model.py b/testbed_example/example_optical_model.py new file mode 100644 index 00000000..05991598 --- /dev/null +++ b/testbed_example/example_optical_model.py @@ -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) diff --git a/testbed_example/services/example_simulator/example_simulator.py b/testbed_example/services/example_simulator/example_simulator.py new file mode 100644 index 00000000..65a45a3f --- /dev/null +++ b/testbed_example/services/example_simulator/example_simulator.py @@ -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()