def __init__(self, serial_number: typing.Optional[str] = None, **kwargs) -> None: super().__init__(**kwargs) self._acquiring = False self._handle = xiapi.Camera() self._img = xiapi.Image() self._serial_number = serial_number self._sensor_shape = (0, 0) self._roi = microscope.ROI(None, None, None, None) self._binning = microscope.Binning(1, 1) # When using the Settings system, enums are not really enums # and even when using lists we get indices sent back and forth # (works fine only when using EnumInt. The gymnastic here # makes it work with the rest of enums which are there to make # it work with TriggerTargetMixin. trg_source_names = [x.name for x in TrgSourceMap] def _trigger_source_setter(index: int) -> None: trigger_mode = TrgSourceMap[trg_source_names[index]].value self.set_trigger(trigger_mode, self.trigger_mode) self.add_setting( "trigger source", "enum", lambda: TrgSourceMap(self.trigger_type).name, _trigger_source_setter, trg_source_names, ) self.initialize()
def _get_roi(self): return microscope.ROI( self._aoi_left.get_value(), self._aoi_top.get_value(), self._aoi_width.get_value(), self._aoi_height.get_value(), )
def set_roi(self, roi): """Set the ROI according to the provided rectangle. ROI is a tuple (left, right, width, height) Return True if ROI set correctly, False otherwise.""" maxw, maxh = self.get_sensor_shape() binning = self.get_binning() left, top, width, height = roi if not width: # 0 or None width = maxw // binning.h if not height: # 0 or None height = maxh // binning.v if self._transform[2]: roi = microscope.ROI(left, top, height, width) else: roi = microscope.ROI(left, top, width, height) return self._set_roi(roi)
def _get_roi(self) -> microscope.ROI: assert self._roi == microscope.ROI( self._handle.get_offsetX(), self._handle.get_offsetY(), self._handle.get_width(), self._handle.get_height(), ), "ROI attribute is out of sync with internal camera setting" return self._roi
def __init__(self, **kwargs): super().__init__(**kwargs) # Binning and ROI self._roi = microscope.ROI(0, 0, 512, 512) self._binning = microscope.Binning(1, 1) # Function used to generate test image self._image_generator = _ImageGenerator() self.add_setting( "image pattern", "enum", self._image_generator.method, self._image_generator.set_method, self._image_generator.get_methods, ) self.add_setting( "image data type", "enum", self._image_generator.data_type, self._image_generator.set_data_type, self._image_generator.get_data_types, ) self.add_setting( "display image number", "bool", lambda: self._image_generator.numbering, self._image_generator.enable_numbering, None, ) # Software buffers and parameters for data conversion. self._a_setting = 0 self.add_setting( "a_setting", "int", lambda: self._a_setting, lambda val: setattr(self, "_a_setting", val), lambda: (1, 100), ) self._error_percent = 0 self.add_setting( "_error_percent", "int", lambda: self._error_percent, self._set_error_percent, lambda: (0, 100), ) self._gain = 0 self.add_setting( "gain", "int", lambda: self._gain, self._set_gain, lambda: (0, 8192), ) self._acquiring = False self._exposure_time = 0.1 self._triggered = 0 # Count number of images sent since last enable. self._sent = 0
def get_roi(self): """Return ROI as a rectangle (left, top, width, height). Chosen this rectangle format as it completely defines the ROI without reference to the sensor geometry.""" roi = self._get_roi() if self._transform[2]: # 90 degree rotation roi = microscope.ROI(roi[1], roi[0], roi[3], roi[2]) return roi
def initialize(self) -> None: """Initialise the camera. Open the connection, connect properties and populate settings dict. """ n_cameras = self._handle.get_number_devices() if self._serial_number is None: if n_cameras > 1: raise TypeError("more than one Ximea camera found but the" " serial_number argument was not specified") _logger.info("serial_number is not specified but there is only one" " camera on the system") self._handle.open_device() else: _logger.info("opening camera with serial number '%s'", self._serial_number) self._handle.open_device_by_SN(self._serial_number) self._sensor_shape = ( self._handle.get_width_maximum() + self._handle.get_offsetX_maximum(), self._handle.get_height_maximum() + self._handle.get_offsetY_maximum(), ) self._roi = microscope.ROI( left=0, top=0, width=self._sensor_shape[0], height=self._sensor_shape[1], ) self.set_roi(self._roi) self.set_trigger(microscope.TriggerType.SOFTWARE, microscope.TriggerMode.ONCE) # Add settings for the different temperature sensors. for temp_param_name in [ "chip_temp", "hous_temp", "hous_back_side_temp", "sensor_board_temp", ]: get_temp_method = getattr(self._handle, "get_" + temp_param_name) # Not all cameras have temperature sensors in all # locations. We can't query if the sensor is there, we # can only try to read the temperature and skip that # temperature sensor if we get an exception. try: get_temp_method() except xiapi.Xi_error as err: if err.status != _XI_NOT_SUPPORTED: raise else: self.add_setting( temp_param_name, "float", get_temp_method, None, values=tuple(), )
def _get_roi(self): """Return the current ROI (left, top, width, height).""" return microscope.ROI(0, 0, 512, 512)
def initialize(self) -> None: """Initialise the camera. Open the connection, connect properties and populate settings dict. """ n_cameras = self._handle.get_number_devices() if self._serial_number is None: if n_cameras > 1: raise TypeError("more than one Ximea camera found but the" " serial_number argument was not specified") _logger.info("serial_number is not specified but there is only one" " camera on the system") self._handle.open_device() else: _logger.info("opening camera with serial number '%s'", self._serial_number) self._handle.open_device_by_SN(self._serial_number) self._sensor_shape = ( self._handle.get_width_maximum() + self._handle.get_offsetX_maximum(), self._handle.get_height_maximum() + self._handle.get_offsetY_maximum(), ) self._roi = microscope.ROI( left=0, top=0, width=self._sensor_shape[0], height=self._sensor_shape[1], ) self.set_roi(self._roi) self.set_trigger(microscope.TriggerType.SOFTWARE, microscope.TriggerMode.ONCE) # When we return the sensor temperature we want to return the # temperature that's closest to the chip since that's the one # that has the biggest impact on image noise. We don't know # what temperature sensors each camera has so we try one at a # time, by order of preference, until it works. for temperature_selector in ( "XI_TEMP_IMAGE_SENSOR_DIE", "XI_TEMP_IMAGE_SENSOR_DIE_RAW", "XI_TEMP_SENSOR_BOARD", "XI_TEMP_INTERFACE_BOARD", "XI_TEMP_FRONT_HOUSING", "XI_TEMP_REAR_HOUSING", "XI_TEMP_TEC1_COLD", "XI_TEMP_TEC1_HOT", ): try: self._handle.set_temp_selector(temperature_selector) except xiapi.Xi_error as err: # We need to catch both "not supported" and "unknown # parameter" but we don't understand their difference. # We can definitely get both (see issue #169). status = getattr(err, "status", None) if status in [_XI_NOT_SUPPORTED, _XI_UNKNOWN_PARAM]: _logger.info( "no hardware support for %s temperature" " readings", temperature_selector, ) else: raise else: _logger.info("temperature reading set to %s", temperature_selector) break