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#Flushing-the-queue).
43Ximea cameras in the MQ family accept software triggers even if set
44for hardware triggers (see `vendor issues
45#3`<https://github.com/python-microscope/vendor-issues/issues/3>).
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__)
80_XI_NOT_IMPLEMENTED = 26
81_XI_ACQUISITION_STOPED = 45
82_XI_UNKNOWN_PARAM = 100
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,
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 [
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()
365 def soft_trigger(self) -> None:
371 self.
_handle.set_trigger_software(1)
383 raise NotImplementedError()
391 ),
"ROI attribute is out of sync with internal camera setting"
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)
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)
None set_roi(self, microscope.ROI roi)
_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)
microscope.ROI _get_roi(self)
typing.Optional[np.ndarray] _fetch_data(self)
None __init__(self, typing.Optional[str] serial_number=None, **kwargs)
microscope.TriggerType trigger_type(self)
bool _set_binning(self, microscope.Binning binning)
None set_exposure_time(self, float value)
microscope.TriggerMode trigger_mode(self)
microscope.Binning _get_binning(self)
None set_trigger(self, microscope.TriggerType ttype, microscope.TriggerMode tmode)
bool _set_roi(self, microscope.ROI roi)
typing.Tuple[int, int] _get_sensor_shape(self)