.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/experiment.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_experiment.py: Setting up your hardware ======================== This script sets constant experimental parameters and implements camera and SLM drivers. You will have to do this for your own hardware. .. GENERATED FROM PYTHON SOURCE LINES 8-18 .. code-block:: Python import time import numpy as np from hologradpy import hardware as hw # These modules are only needed for our camera and SLM drivers import cv2 as cv from harvesters.core import Harvester from screeninfo import get_monitors import imageio .. GENERATED FROM PYTHON SOURCE LINES 19-24 Setting experimental parameters and other constant parameters ------------------------------------------------------------- To start off, we write our own subclass of ``hardware.ParamsBase`` which sets some experimental parameters and other constants needed in this script. .. GENERATED FROM PYTHON SOURCE LINES 24-43 .. code-block:: Python class Params(hw.ParamsBase): wavelength = 670e-9 # Wavelength [m] beam_diameter = 7.25e-3 # Diameter of incident beam [m] fl = 0.25 # Focal length [m] data_path = '../../holography_data/' # Path to measured constant SLM phase and intenstiy phi_path = data_path + '23-09-13_13-20-49_measure_slm_wavefront/dphi_uw.npy' i_path = data_path + '23-09-13_11-47-42_measure_slm_intensity/i_rec.npy' phi_filter_size = 2 crop = 64 pms_obj = Params() .. GENERATED FROM PYTHON SOURCE LINES 44-50 Implementing SLM and camera drivers ----------------------------------- This module provides the ``hardware.CameraBase`` class and the ``hardware.SlmDisp`` class to interface with the camera and the SLM. You will have to write your own subclasses for the specific devices you are using. Here, we defined the subclasses ``Camera`` and ``SlmDisp`` to interface with a MatrixVision BlueFox 3 camera and a Hamamatsu SLM. Make sure you implement all abstract methods of ``hw.CameraBase`` and ``hw.SlmBase`` in your own subclasses. .. GENERATED FROM PYTHON SOURCE LINES 50-223 .. code-block:: Python class Camera(hw.CameraBase): def __init__(self, res, pitch, name='before', roi=None, gain=0, bayer=False): if roi is None: roi = [1280, 960, 0, 0] self.roi = roi super().__init__(res, pitch, self.roi) self.count = 0 self.gain = gain self.bayer = bayer self.name = name self.h = None self.ia = None self.bayer_slope = 0.010487497932442524 self.bayer_offset = 2.195178550143578 self.max_frame_count = 2 ** 16 - 1 def start(self, n=1): if n >= self.max_frame_count: n = self.max_frame_count self.h = Harvester() self.h.add_file('C:/Program Files/MATRIX VISION/mvIMPACT Acquire/bin/x64/mvGenTLProducer.cti') self.h.update() print("start init ia") serial_numbers = [] for info in self.h.device_info_list: serial_numbers.append(info.serial_number) if self.name == 'before': n_cam = serial_numbers.index('F0600075') if self.name == 'after': n_cam = serial_numbers.index('F0600086') self.ia = self.h.create(n_cam) self.ia.remote_device.node_map.ExposureAuto.value = 'Off' self.ia.remote_device.node_map.mvLowLight.value = 'Off' self.ia.remote_device.node_map.ExposureAuto.value = 'Off' self.ia.remote_device.node_map.BlackLevelAuto.value = 'Off' self.ia.remote_device.node_map.GainAuto.value = 'Off' self.ia.remote_device.node_map.ExposureTime.value = 100 self.ia.remote_device.node_map.PixelFormat.value = 'Mono16' self.ia.remote_device.node_map.AcquisitionMode.value = 'MultiFrame' self.ia.remote_device.node_map.AcquisitionFrameRateEnable.value = True self.ia.remote_device.node_map.AcquisitionFrameRate.value = 12 if self.name == 'before': self.ia.remote_device.node_map.ReverseX.value = True self.ia.remote_device.node_map.ReverseY.value = True elif self.name == 'after': self.ia.remote_device.node_map.ReverseX.value = False self.ia.remote_device.node_map.ReverseY.value = True self.ia.remote_device.node_map.TriggerMode.value = 'On' self.ia.remote_device.node_map.TriggerSource.value = 'Software' self.ia.remote_device.node_map.TriggerSelector.value = 'FrameStart' w, h, dx, dy = self.roi self.ia.remote_device.node_map.AcquisitionFrameCount.value = n self.ia.remote_device.node_map.Gain.value = self.gain if dx <= self.ia.remote_device.node_map.OffsetX.value: self.ia.remote_device.node_map.OffsetX.value = dx self.ia.remote_device.node_map.OffsetY.value = dy self.ia.remote_device.node_map.Width.value = w self.ia.remote_device.node_map.Height.value = h else: self.ia.remote_device.node_map.Width.value = w self.ia.remote_device.node_map.Height.value = h self.ia.remote_device.node_map.OffsetX.value = dx self.ia.remote_device.node_map.OffsetY.value = dy self.ia.start() print("start acquisition") def get_image(self, exp_time_): if self.count >= self.max_frame_count: self.stop() self.start(n=self.max_frame_count) self.ia.remote_device.node_map.ExposureTime.value = exp_time_ self.ia.remote_device.node_map.TriggerSoftware.execute() with self.ia.fetch() as buffer: component = buffer.payload.components[0] width = component.width height = component.height im = np.array(component.data.reshape(height, width)).astype(np.double) if self.bayer is True: im[0::2, 1::2] = im[0::2, 1::2] * (1 + self.bayer_slope) + self.bayer_offset im[1::2, 0::2] = im[1::2, 0::2] * (1 + self.bayer_slope) + self.bayer_offset self.count += 1 return im def stop(self): self.ia.stop() print("stopped acquisition") self.ia.destroy() self.h.reset() class SlmDisp(hw.SlmBase): def __init__(self, res, pitch, calib=None, delay=0.2, dx=0, dy=0): super().__init__(res, pitch) self.max_phase = 2 * np.pi # Largest value for phase wrapping self.slm_norm = 128 # Gray level on the SLM corresponding to max_phase # Gray level vs phase lookup table self.lut = np.load(pms_obj.data_path + '23-02-17_13-49-14_calibrate_grey_values/phase.npy') self.idx_lut = np.argmin(np.abs(self.lut - self.max_phase)) # Index of max_phase in lut self.lut = self.lut[:self.idx_lut] # Path to Hamamatsu SLM correction pattern. self.cal_path = pms_obj.data_path + 'deformation_correction_pattern/CAL_LSH0802439_' + '{:.0f}'.\ format(np.around(pms_obj.wavelength * 1e9, decimals=-1)) + 'nm.bmp' self.delay = 0.2 # Time to wait after displaying a phase pattern on the SLM [s] if calib == 1 or calib is True: self.calib_flag = True self.calib = imageio.imread(self.cal_path) self.calib = np.pad(self.calib, ((0, 0), (0, 8))) elif calib == 0 or calib is False or calib is None: self.calib_flag = False self.calib = np.zeros((self.res[1], self.res[0])) self.delay = delay self.dx = dx self.dy = dy monitor = get_monitors()[-1] cv.namedWindow('screen', cv.WINDOW_NORMAL) cv.resizeWindow('screen', self.res[1], self.res[0]) cv.moveWindow('screen', monitor.x, monitor.y) cv.setWindowProperty('screen', cv.WND_PROP_FULLSCREEN, cv.WINDOW_FULLSCREEN) cv.waitKey(100) print("SlmDisp initialised") def display(self, phi_slm): im_res_y, im_res_x = phi_slm.shape slm_res_y, slm_res_x = self.res slm_pad_x = (slm_res_x - im_res_x) // 2 slm_pad_y = (slm_res_y - im_res_y) // 2 slm_norm = self.slm_norm if slm_pad_x == 0 and slm_pad_y == 0: phi_zeros = slm_norm * phi_slm / (2 * np.pi) elif -slm_pad_y - self.dy == 0: phi_zeros = np.zeros((slm_res_y, slm_res_x)) phi_disp = slm_norm * phi_slm / (2 * np.pi) phi_zeros[slm_pad_y - self.dy:, slm_pad_x - self.dx:-slm_pad_x - self.dx] = phi_disp elif -slm_pad_x - self.dx == 0: phi_zeros = np.zeros((slm_res_y, slm_res_x)) phi_disp = slm_norm * phi_slm / (2 * np.pi) phi_zeros[slm_pad_y - self.dy:-slm_pad_y - self.dy, slm_pad_x - self.dx:] = phi_disp else: phi_zeros = np.zeros((slm_res_y, slm_res_x)) phi_disp = slm_norm * phi_slm / (2 * np.pi) phi_zeros[slm_pad_y - self.dy:-slm_pad_y - self.dy, slm_pad_x - self.dx:-slm_pad_x - self.dx] = phi_disp if self.calib_flag is False: phi_zeros = phi_zeros.astype('uint8') else: phi_zeros = np.remainder(phi_zeros + self.calib, slm_norm).astype('uint8') cv.imshow('screen', phi_zeros) cv.waitKey(1) time.sleep(self.delay) .. GENERATED FROM PYTHON SOURCE LINES 224-225 We can now use the classes ``Params``, ``Camera`` and ``SlmDisp`` in other scripts. .. _sphx_glr_download_auto_examples_experiment.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: experiment.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: experiment.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: experiment.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_