Example #1
0
 def exposure(self, exposure: Q_):
     self.logger.info(f'Setting exposure to {exposure}')
     try:
         if not isinstance(exposure, Q_):
             exposure = Q_(exposure)
         self._driver.ExposureTime.SetValue(exposure.m_as('us'))
         exposure = float(self._driver.ExposureTime.ToString()) * Q_('us')
         self.config.upgrade({'exposure': exposure})
     except _genicam.TimeoutException:
         self.logger.error(f'Timed out setting the exposure to {exposure}')
Example #2
0
    def do_scan(self):
        """ Does the scan considering that everything else was already set up.
        """

        scan = self.scan
        laser = self.devices[scan['laser']['name']]
        axis = scan['axis']
        approx_time_to_scan = (laser.params['stop_wavelength']-laser.params['start_wavelength'])/laser.params['wavelength_speed']
        self.logger.info('Total number of devices to scan: {}'.format(len(axis)))
        self.logger.info('Approximate time to do a laser scan: {}'.format(approx_time_to_scan))

        if len(axis) != 1:
            self.logger.warning('Trying to do a scan of {} dimensions. The program only supports 1 dimenstion'.format(len(axis)))
            raise Warning('Wrong number of axis')

        dev_to_scan = list(axis.keys())[-1] # Get the name of the device
        self.logger.info('Device to scan: {}'.format(dev_to_scan))
        actuator_to_scan = list(axis[dev_to_scan].keys())[-1]
        self.logger.info('Actuator to scan: {}'.format(actuator_to_scan))
        range = axis[dev_to_scan][actuator_to_scan]['rage']
        self.logger.debug('Range to scan: {}'.format(range))
        # Scan the laser and the values of the given device
        if dev_to_scan != 'time':
            start = Q_(range[0])
            stop = Q_(range[1])
            step = Q_(range[2])
            units = start.u
            num_points_dev = ((stop-start)/step).to('') + 1  # This is to include also the last point
        else:
            start = 1
            stop = range[1]
            num_points_dev = stop

        for value in np.linspace(start, stop, num_points_dev):
            if dev_to_scan != 'time':
                self.devices[dev_to_scan]['actuators'][actuator_to_scan].value = value * units
                self.logger.debug('Set {} to {}'.format(actuator_to_scan, value))

            laser.driver.execute_sweep()
            self.logger.info('Executing laser sweep')
            sleep(0.1)
            while laser.driver.sweep_condition != 'Stop':
                sleep(approx_time_to_scan.m/Config.Laser.number_checks_per_scan)

        for device in self.scan['detectors']:
            dev = self.devices[device]['dev']
            daq_driver = dev.driver
            daq_driver.stop_task()
            daq_driver.clear_task()
Example #3
0
    def apply_value(self, actuator, value):
        """ Sets the output of the NI card. For the time being it sets a DC constant value; this has to be expanded to
        other types of actuators, for example a digital output.

        .. todo:: Make this method work with actuators of different types than analog

        .. warning:: This method is not intended for making ramps or generating a continuous output; it is just a handy
        way of changing the value of a particular port.

        :param actuator: specifies the actuator on which to act.
        :param value: The value to be set
        """


        port = actuator.properties['port']

        # First let's check that the actuator is an analog channel
        if actuator.properties['type'] == 'analog':
            port = "Dev%s/ao%s" % (self.daq_num, port)
            calibration = actuator.calibration
            # Convert value to volts:
            output_volts = from_units_to_volts(value, calibration)

            min_value = Q_(actuator.properties['limits']['min'])
            max_value = Q_(actuator.properties['limits']['max'])
            # Convert values to volts:
            # The NI card needs to specify min and max voltages; the actuator itself should check that the voltages
            # are within limits before even arriving here. In any case, as a safe, the NI card will never output a value
            # beyond the limits.

            min_V = from_units_to_volts(min_value, calibration)
            max_V = from_units_to_volts(max_value, calibration)

            autostart = nidaq.bool32(True)
            timeout = Config.NI.Output.Analog.timeout
            self.logger.debug('Actuator: {}, MIN: {}, MAX: {}, Value: {}'.format(actuator.name, min_V, max_V, output_volts))
            t = nidaq.Task()
            t.CreateAOVoltageChan(port, None, min_V, max_V, nidaq.DAQmx_Val_Volts, None)
            t.WriteAnalogScalarF64(autostart, timeout, output_volts, None)
            t.StopTask()
            t.ClearTask()

        self.logger.info('Changed the value of {} to {}'.format(actuator.name, value))
Example #4
0
 def exposure(self) -> Q_:
     """ The exposure of the camera, defined in units of time """
     if self.config['exposure'] is not None:
         return self.config['exposure']
     try:
         exposure = float(self._driver.ExposureTime.ToString()) * Q_('us')
         return exposure
     except _genicam.TimeoutException:
         self.logger.error('Timeout getting the exposure')
         return self.config['exposure']
    def __set__(self, instance, value):
        if self.units:
            if isinstance(value, Q_):
                value = value.to(self.units)
            elif isinstance(value, str):
                value = Q_(value).to(self.units)
            elif isinstance(value, Number):
                value = value * self.units
            else:
                raise Exception(f'Cant set {self.name} to {value}')

        self._value = value
Example #6
0
    def analog_output_dc(self, conditions):
        """ Sets the analog output of the NI card. For the time being is thought as a DC constant value.

        :param dict conditions: specifies DEV and Value
        :return:
        """
        dev = conditions['dev']
        port = "Dev%s/ao%s" % (self.daq_num, dev.properties['port'])
        units = Q_(dev.properties['calibration']['units'])
        min_value = Q_(dev.properties['limits']['min']).to(units)
        max_value = Q_(dev.properties['limits']['max']).to(units)
        # Convert values to volts:
        value = conditions['value'].to(units)
        V = self.from_units_to_volts(value, dev)
        min_V = self.from_units_to_volts(min_value, dev)
        max_V = self.from_units_to_volts(max_value, dev)
        t = nidaq.Task()
        t.CreateAOVoltageChan(port, None, min_V, max_V, nidaq.DAQmx_Val_Volts, None)
        t.WriteAnalogScalarF64(nidaq.bool32(True), 0, V, None)
        t.StopTask()
        t.ClearTask()
Example #7
0
    def read_value(self, sensor):
        """ Reads the value of a sensor.

        .. todo:: Make this method work with sensors other than analog inputs.

        :param sensor: the sensor to read.
        :return: The value read, with units if appropriate.
        """
        port = sensor.properties['port']

        if sensor.properties['type'] == 'analog':
            port = "Dev%s/ai%s" % (self.daq_num, port)
            calibration = sensor.properties['calibration']
            min_value = Q_(sensor.properties['limits']['min'])
            max_value = Q_(sensor.properties['limits']['max'])
            min_V = from_units_to_volts(min_value, calibration)
            max_V = from_units_to_volts(max_value, calibration)

            freq = Config.NI.Input.Analog.freq
            trigger = Config.NI.Input.Analog.trigger
            trigger_edge = Config.NI.Input.Analog.trigger_edge
            measure_mode = Config.NI.Input.Analog.measure_mode
            num_points = Config.NI.Input.Analog.num_points
            cont_finite = Config.NI.Input.Analog.cont_finite

            t = nidaq.Task()
            t.CreateAIVoltageChan(port, None, measure_mode, min_V,
                                  max_V, nidaq.DAQmx_Val_Volts, None)
            t.CfgSampClkTiming(trigger, freq, trigger_edge, cont_finite, num_points)
            t.StartTask()
            time.sleep(num_points*freq)
            timeout = Config.NI.Input.Analog.read_timeout
            read = nidaq.int32()
            data = np.zeros((num_points,), dtype=np.float64)

            t.ReadAnalogF64(num_points, timeout, nidaq.DAQmx_Val_GroupByChannel,
                            data, num_points, nidaq.byref(read), None)

            value = np.mean(data)
            return from_volts_to_units(value, calibration)
    def __init__(self, units=None, ui_class=None):
        self._value = None

        self.units = None
        if units:
            if isinstance(units, Q_):
                self.units = units
            else:
                try:
                    self.units = Q_(units)
                except UndefinedUnitError:
                    self.units = None

        self.ui_class = ui_class
Example #9
0
 def value(self, value):
     if self._device is None:
         err_str = "Trying to update a value of {} before connecting it to a device".format(
             self.name)
         logger.error(err_str)
         raise Exception(err_str)
     if 'limits' in self.properties:
         if value > Q_(self.properties['limits']['max']) or value < Q_(
                 self.properties['limits']['min']):
             wrn_msg = 'Trying to set {} to {}, while limits are ({}, {})'.format(
                 self.name, value, self.properties['limits']['min'],
                 self.properties['limits']['max'])
             logger.warning(wrn_msg)
             raise Warning(wrn_msg)
             return
     try:
         self._device.apply_value(
             self, value
         )  # self has to be passed as an explicit argument since the method is
         # expecting an actuator as argument.
     except Exception as e:
         logger.error("Failed to apply {} to {}: {}".format(
             value, self.name, e))
         raise e
Example #10
0
    def from_units_to_volts(self, value, dev):
        """ Converts a value from specific actuator units into volts to pass to a DAQ.

        :param value: The output value
        :param dev: The calibration of the device, including units.
        :type value: Quantity
        :type dev: dict.
        """
        units = Q_(dev.properties['calibration']['units'])
        slope = dev.properties['calibration']['slope'] * units
        offset = dev.properties['calibration']['offset'] * units
        value = value.to(units)
        value = value.m
        slope = slope.m
        offset = offset.m
        return (value - offset) / slope
Example #11
0
 def buffer_size(self, value):
     value = Q_(value)
     self.logger.info(f'{self} - Setting buffer size to {value}')
     self._buffer_size = value
Example #12
0
 def get_exposure(self) -> Q_:
     self.exposure = float(self.camera.ExposureTime.ToString()) * Q_('us')
     return self.exposure
Example #13
0
    def configure(self, properties: dict):
        """ Configure the camera based on a dictionary of properties.

        .. deprecated:: 0.3.0
            By implementing features, this method is no longer required
        """
        self.logger.info('Updating config')
        update_cam = False
        update_roi = False
        update_exposure = False
        update_binning = False
        update_gain = False
        for k, new_prop in properties.items():
            self.logger.debug('Updating {} to {}'.format(k, new_prop))

            update_cam = False
            if k in self.config:
                old_prop = self.config[k]
                if new_prop != old_prop:
                    update_cam = True
            else:
                update_cam = True

            if update_cam:
                if k in ['roi_x1', 'roi_x2', 'roi_y1', 'roi_y2']:
                    update_roi = True
                elif k == 'exposure_time':
                    update_exposure = True
                elif k in ['binning_x', 'binning_y']:
                    update_binning = True
                elif k == 'gain':
                    update_gain = True

        if update_cam:
            self.logger.info('There are things to update in the new config')
            if update_roi:
                X = sorted([properties['roi_x1'], properties['roi_x2']])
                Y = sorted([properties['roi_y1'], properties['roi_y2']])
                self.logger.info(f'Updating ROI {X}, {Y}')
                self.set_ROI(X, Y)
                self.config.update({
                    'roi_x1': X[0],
                    'roi_x2': X[1],
                    'roi_y1': Y[0],
                    'roi_y2': Y[1]
                })

            if update_exposure:
                exposure = properties['exposure_time']
                self.logger.info(f'Updating exposure to {exposure}')
                if isinstance(exposure, str):
                    exposure = Q_(exposure)

                new_exp = self.set_exposure(exposure)
                self.config['exposure_time'] = new_exp

            if update_binning:
                self.logger.info('Updating binning')
                self.set_binning(properties['binning_x'],
                                 properties['binning_y'])
                self.config.update({
                    'binning_x': properties['binning_x'],
                    'binning_y': properties['binning_y']
                })

            if update_gain:
                self.logger.info(f'Updating gain to {properties["gain"]}')
                self.set_gain(properties['gain'])
Example #14
0
        self.camera.Close()

    def __str__(self):
        if self.friendly_name:
            return self.friendly_name
        return "Basler Camera"


if __name__ == '__main__':
    from time import sleep

    logger.setLevel(logging.DEBUG)
    ch = logging.StreamHandler()
    ch.setLevel(logging.DEBUG)
    formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    ch.setFormatter(formatter)
    logger.addHandler(ch)
    logger.info('Starting Basler')
    basler = Camera(0)
    basler.initialize()
    basler.set_acquisition_mode(basler.MODE_SINGLE_SHOT)
    basler.set_exposure(Q_('.02s'))
    basler.trigger_camera()
    print(len(basler.read_camera()))
    basler.set_acquisition_mode(basler.MODE_CONTINUOUS)
    basler.trigger_camera()
    sleep(1)
    imgs = basler.read_camera()
    print(len(imgs))
from time import sleep

from experimentor import Q_
from experimentor.config import settings
from experimentor.core.publisher import Publisher, Listener
from experimentor.core.subscriber import Subscriber
from experimentor.models.cameras.basler import BaslerCamera

cam = BaslerCamera('da')
cam.initialize()
cam.clear_ROI()
cam.set_acquisition_mode(cam.MODE_CONTINUOUS)
cam.set_ROI((1, 100), (1, 100))
cam.set_exposure(Q_('10ms'))

publisher = Publisher(settings.GENERAL_STOP_EVENT)
publisher.start()

listener = Listener()


def func(frame):
    print(len(frame))


subscriber = Subscriber(func, 'frame')
subscriber.start()

sleep(2)

cam.trigger_camera()
Example #16
0
from time import time

from experimentor import Q_
from experimentor.models.devices.cameras.basler.basler import BaslerCamera


cam = BaslerCamera('p')
cam.initialize()

cam.exposure = Q_('10ms')

t0 = time()
i = 0
while True:
    try:
        cam.trigger_camera()
        ans = cam.read_camera()[0]
        print(f'Acquired {i} frames, {i/(time()-t0)} fps', end='\r')
    except KeyboardInterrupt:
        break

cam.finalize()
Example #17
0
 def set_exposure(self, exposure: Q_) -> Q_:
     self.camera.ExposureTime.SetValue(exposure.m_as('us'))
     self.exposure = exposure
     return self.get_exposure()