24Changing settings flushes the buffer
25------------------------------------
27It is not possible to set some parameters during image acquisition.
28In such cases, acquisition is stopped (camera is disabled) and the
29restarted (camera is enabled). However, stopping acquisition discards
30any image in the camera memory that have
not yet been read.
32Modifying the following settings require acquisition to be stopped:
36- trigger type (trigger source)
38For more details, see the [XiAPI manual](https://www.ximea.com/support/wiki/apis/XiAPI_Manual
43Ximea cameras
in the MQ family accept software triggers even
if set
44for hardware triggers (see `vendor issues
46However, `XimeaCamera.trigger()` checks the trigger type
and will
47raise an exception unless the camera
is set
for software triggers.
52Support
for Ximea cameras requires Ximea
's API Python (xiApiPython).
53This is only available via Ximea
's website and is not available on
54PyPI. See Ximea's website for `install instructions
55<https://www.ximea.com/support/wiki/apis/Python>`__.
65from ximea import xiapi
71_logger = logging.getLogger(__name__)
74# The ximea package does not provide an enum for the error codes.
75# There is ximea.xidefs.ERROR_CODES which maps the error code to an
76# error message but what we need is a symbol that maps to the error
77# code so we can use while handling exceptions.
80_XI_NOT_IMPLEMENTED = 26
81_XI_ACQUISITION_STOPED = 45
82_XI_UNKNOWN_PARAM = 100
85# During acquisition, we rely on catching timeout errors which then
86# get discarded. However, with debug level set to warning (XiApi
91xiapi.Camera().set_debug_level(
"XI_DL_ERROR")
94@contextlib.contextmanager
95def _disabled_camera(camera):
96 """Context manager to temporarily disable camera."""
107@contextlib.contextmanager
108def _enabled_camera(camera):
109 """Context manager to temporarily enable camera."""
110 if not camera.enabled:
125 XI_TRG_SOFTWARE = microscope.TriggerType.SOFTWARE
126 XI_TRG_EDGE_RISING = microscope.TriggerType.RISING_EDGE
127 XI_TRG_EDGE_FALLING = microscope.TriggerType.FALLING_EDGE
147 XI_TRG_SEL_FRAME_START = microscope.TriggerMode.ONCE
180 serial_number: the serial number of the camera to connect to.
181 It can be set to `None`
if there
is only camera on the
187 self, serial_number: typing.Optional[str] =
None, **kwargs
192 self.
_img = xiapi.Image()
203 trg_source_names = [x.name
for x
in TrgSourceMap]
205 def _trigger_source_setter(index: int) ->
None:
206 trigger_mode = TrgSourceMap[trg_source_names[index]].value
213 _trigger_source_setter,
219 def _fetch_data(self) -> typing.Optional[np.ndarray]:
225 except xiapi.Xi_error
as err:
228 if getattr(err,
"status",
None) == _XI_TIMEOUT:
231 getattr(err,
"status",
None) == _XI_ACQUISITION_STOPED
240 data: np.ndarray = self.
_img.get_image_data_numpy()
242 "Fetched imaged with dims %s and size %s.", data.shape, data.size
247 _logger.info(
"Disabling acquisition.")
254 self.
_handle.stop_acquisition()
259 def initialize(self) -> None:
260 """Initialise the camera.
262 Open the connection, connect properties and populate settings dict.
264 n_cameras = self._handle.get_number_devices()
269 "more than one Ximea camera found but the"
270 " serial_number argument was not specified"
273 "serial_number is not specified but there is only one"
274 " camera on the system"
284 self.
_handle.get_width_maximum()
285 + self.
_handle.get_offsetX_maximum(),
286 self.
_handle.get_height_maximum()
287 + self.
_handle.get_offsetY_maximum(),
298 microscope.TriggerType.SOFTWARE, microscope.TriggerMode.ONCE
302 for temp_param_name
in [
305 "hous_back_side_temp",
308 get_temp_method = getattr(self.
_handle,
"get_" + temp_param_name)
315 except xiapi.Xi_error
as err:
320 if err.status
not in [
335 def _do_disable(self):
338 def _do_enable(self):
339 _logger.info(
"Preparing for acquisition.")
343 self.
_handle.start_acquisition()
345 _logger.info(
"Acquisition enabled.")
351 self.
_handle.set_exposure_direct(int(value * 1000000))
352 except Exception
as err:
353 _logger.debug(
"set_exposure_time exception: %s", err)
357 return self.
_handle.get_exposure() * 1.0e-6
360 return 1.0 / self.
_handle.get_framerate()
362 def _get_sensor_shape(self) -> typing.Tuple[int, int]:
365 def soft_trigger(self) -> None:
368 def _do_trigger(self) -> None:
371 self.
_handle.set_trigger_software(1)
373 def _get_binning(self) -> microscope.Binning:
376 def _set_binning(self, binning: microscope.Binning) -> bool:
383 raise NotImplementedError()
385 def _get_roi(self) -> microscope.ROI:
391 ),
"ROI attribute is out of sync with internal camera setting"
394 def _set_roi(self, roi: microscope.ROI) -> bool:
400 "ROI %s does not fit in sensor shape %s"
410 with _disabled_camera(self):
413 self.
_handle.set_width(roi.width)
414 self.
_handle.set_height(roi.height)
415 self.
_handle.set_offsetX(roi.left)
416 self.
_handle.set_offsetY(roi.top)
423 def _do_shutdown(self) -> None:
425 self.
_handle.stop_acquisition()
434 def trigger_mode(self) -> microscope.TriggerMode:
435 trg_selector = self.
_handle.get_trigger_selector()
437 tmode = TrgSelectorMap[trg_selector]
440 "somehow set to unsupported trigger mode %s" % trg_selector
445 def trigger_type(self) -> microscope.TriggerType:
446 trg_source = self.
_handle.get_trigger_source()
448 ttype = TrgSourceMap[trg_source]
451 "somehow set to unsupported trigger type %s" % trg_source
458 if tmode
is not microscope.TriggerMode.ONCE:
460 "%s not supported (only TriggerMode.ONCE)" % tmode
467 "no support for trigger type %s" % ttype
470 if trg_source.name != self.
_handle.get_trigger_source():
472 with _disabled_camera(self):
473 self.
_handle.set_trigger_source(trg_source.name)
def _set_roi(self, microscope.ROI roi)
None set_roi(self, microscope.ROI roi)
None add_setting(self, name, dtype, get_func, set_func, values, typing.Optional[typing.Callable[[], bool]] readonly=None)
microscope.TriggerType trigger_type(self)
None set_trigger(self, microscope.TriggerType ttype, microscope.TriggerMode tmode)
microscope.TriggerMode trigger_mode(self)
float get_exposure_time(self)
None __init__(self, typing.Optional[str] serial_number=None, **kwargs)
microscope.TriggerType trigger_type(self)
None set_exposure_time(self, float value)
microscope.TriggerMode trigger_mode(self)
None set_trigger(self, microscope.TriggerType ttype, microscope.TriggerMode tmode)
bool _set_roi(self, microscope.ROI roi)