diff --git a/concert/devices/cameras/uca.py b/concert/devices/cameras/uca.py index 57ba4565f..d17304f89 100644 --- a/concert/devices/cameras/uca.py +++ b/concert/devices/cameras/uca.py @@ -1,7 +1,10 @@ """ Cameras supported by the libuca library. """ +import time import numpy as np +from concert.coroutines import null +from concert.helpers import async, inject from concert.quantities import q from concert.base import Parameter from concert.devices.cameras import base @@ -137,3 +140,73 @@ def _grab_real(self): return array return None + + +class Dimax(Camera): + + """A PCO.dimax camera implementation based on libuca :py:class:`Camera`.""" + + def __init__(self): + super(Dimax, self).__init__("pco") + + def readout_blocking(self, condition=lambda: True): + """ + Readout the frames and don't allow recording in the meantime. + *condition* is the same as in :py:meth:`Camera.readout`. + """ + try: + self.uca.start_readout() + super(Dimax, self).readout(condition) + finally: + self.uca.stop_readout() + + def acquire_auto(self, num_frames): + """ + Acquire approximately *num_frames* frames. Camera is set to a mode when + it is triggered automatically and live images streaming is enabled. + Live frames are yielded as they are grabbed. + + **Note** the number of actually recorded images may differ. + """ + @async + def async_wait(): + try: + sleep_time = (num_frames / + self.frame_rate).to_base_units().magnitude + time.sleep(sleep_time) + finally: + self.stop_recording() + + self.uca.props.trigger_mode = self.uca.props.trigger_mode.AUTO + self.uca.props.storage_mode = 0 + self.uca.props.record_mode = 1 + + # We need to make sure that the camera is in recording mode when we + # start grabbing live frames, thus we start it synchronously. + self.start_recording() + + # The sleeping and camera stopping can be handled asynchronously + acq_future = async_wait() + + # Yield live frames + for frame in self.readout(self.uca.props.is_recording): + yield frame + + # Wait for the acquisition to end + acq_future.result() + + @async + def take_frames_auto(self, num_frames, consumer=None): + """ + Acquire and readout *num_frames*. Frames are first recorded to the + internal camera memory and then read out. The camera is triggered + automatically. *consumer* is a coroutine which is fed with live + frames. After the recording is done the frames are yielded as they are + being grabbed from the camera. + """ + # We need to provide a consumer, otherwise the generator method + # wouldn't start + consumer = null() if consumer is None else consumer + inject(self.acquire_auto(num_frames), consumer) + + return (frame for frame in self.readout())