示例#1
0
    def __init__(
        self, conn: _ZaberConnection, device_address: int, **kwargs
    ) -> None:
        self._dev_conn = _ZaberDeviceConnection(conn, device_address)

        if self._dev_conn.get_number_axes() != 1:
            raise microscope.InitialiseError(
                "Device with address %d is not a filter wheel" % device_address
            )

        rotation_length = self._dev_conn.get_rotation_length(1)
        if rotation_length <= 0:
            raise microscope.InitialiseError(
                "Device with address %d is not a filter wheel" % device_address
            )
        positions = int(rotation_length / self._dev_conn.get_index_distance(1))

        super().__init__(positions, **kwargs)

        # Before a device can moved, it first needs to establish a
        # reference to the home position.  We won't be able to move
        # unless we home it first.  On a stage this happens during
        # enable because the stage movemenet can be dangerous but on a
        # filter wheel this is fine.
        if not self._dev_conn.been_homed():
            self._dev_conn.home()
示例#2
0
    def __init__(
        self,
        image: np.ndarray,
        stage: microscope.abc.Stage,
        filterwheel: microscope.abc.FilterWheel,
        **kwargs,
    ) -> None:
        super().__init__(**kwargs)
        self._image = image
        self._stage = stage
        self._filterwheel = filterwheel
        self._pixel_size = 1.0

        if not all([name in stage.axes.keys() for name in ["x", "y", "z"]]):
            raise microscope.InitialiseError(
                "stage for StageAwareCamera requires x, y, and z axis")
        if image.shape[2] != self._filterwheel.n_positions:
            raise ValueError(
                "image has %d channels but filterwheel has %d positions")

        # Empty the settings dict, most of them are for testing
        # settings, and the rest is specific to the image generator
        # which we don't need.  We probably should have a simpler
        # SimulatedCamera that we could subclass.
        self._settings = {}

        self.add_setting(
            "pixel size",
            "float",
            lambda: self._pixel_size,
            lambda pxsz: setattr(self, "_pixel_size", pxsz),
            # technically should be: (nextafter(0.0, inf), nextafter(inf, 0.0))
            values=(0.0, float("inf")),
        )
示例#3
0
 def __init__(self, serial: _SyncSerial) -> None:
     self._serial = serial
     # We use command() and readline() instead of get_command() in
     # case this is not a Lumencor and won't even give a standard
     # answer and raises an exception during the answer validation.
     self._serial.write(b"GET MODEL\n")
     answer = self._serial.readline()
     if not answer.startswith(b"A MODEL Spectra III"):
         raise microscope.InitialiseError(
             "Not a Lumencor Spectra III Light Engine")
示例#4
0
 def __init__(self, *args, **kwargs):
     warnings.warn(
         "Use ThorlabsFilterWheel instead of ThorlabsFW212C",
         DeprecationWarning,
         stacklevel=2,
     )
     super().__init__(*args, **kwargs)
     if self.n_positions != 12:
         raise microscope.InitialiseError(
             "Does not look like a FW212C, it has %d positions instead of 12"
         )
示例#5
0
 def __init__(self, **kwargs) -> None:
     super().__init__(**kwargs)
     # Status is not the return code of the function calls.
     # Status is where we can find the error code in case a
     # function call returns false.  This _status variable will be
     # an argument in all function calls.
     self._status = ctypes.pointer(ctypes.c_int(mro.OK))
     if not mro.open(self._status):
         raise microscope.InitialiseError(
             "failed to open mirao mirror (error code %d)" %
             self._status.contents.value)
示例#6
0
    def __init__(self, serial_number: str, **kwargs) -> None:
        super().__init__(**kwargs)
        self._dm = BMC.DM()

        if __debug__:
            BMC.ConfigureLog(os.devnull.encode(), BMC.LOG_ALL)
        else:
            BMC.ConfigureLog(os.devnull.encode(), BMC.LOG_OFF)

        status = BMC.Open(self._dm, serial_number.encode())
        if status:
            raise microscope.InitialiseError(BMC.ErrorString(status))
示例#7
0
    def __init__(self, serial: microscope._utils.SharedSerial) -> None:
        self._serial = serial

        # When we connect for the first time, we will get back a
        # greeting message like 'CoolLED precisExcite, Hello, pleased
        # to meet you'.  Discard it by reading until timeout.
        self._serial.readlines()

        # Check that this behaves like a CoolLED device.
        try:
            self.get_css()
        except Exception:
            raise microscope.InitialiseError(
                "Not a CoolLED device, unable to get CSS")
示例#8
0
    def __init__(self, serial_number: str, **kwargs) -> None:
        super().__init__(**kwargs)

        self.serial_number = c_char_p(bytes(str(serial_number), "utf-8"))
        status = TMC.SBC_Open(self.serial_number)

        if status:
            raise microscope.InitialiseError(status)
        # populate axes dict
        self.n_axes = 3  # can be updated later
        axes_names = ["x", "y", "z"]
        self._axes = {}
        for j in range(self.n_axes):
            axn = axes_names[j]
            self._axes[axn] = ThorlabsNanoMaxAxis(self.serial_number, j + 1)
示例#9
0
    def __init__(self, port: str):
        # From the Toptica iBeam SMART manual:
        # Direct connection via COMx with 115200,8,N,1 and serial
        # interface handshake "none". That means that no hardware
        # handshake (DTR, RTS) and no software handshake (XON,XOFF) of
        # the underlying operating system is supported.
        serial_conn = serial.Serial(
            port=port,
            baudrate=115200,
            timeout=1.0,
            bytesize=serial.EIGHTBITS,
            stopbits=serial.STOPBITS_ONE,
            parity=serial.PARITY_NONE,
            xonxoff=False,
            rtscts=False,
            dsrdtr=False,
        )
        self._serial = _SharedSerial(serial_conn)

        # We don't know what is the current verbosity state and so we
        # don't know yet what we should be reading back.  So blindly
        # set to the level we want, flush all output, and then check
        # if indeed this is a Toptica iBeam device.
        with self._serial.lock:
            self._serial.write(b"echo off\r\n")
            self._serial.write(b"prompt off\r\n")
            # The talk level we want is 'usual'.  In theory we should
            # be able to use 'quiet' which only answers queries but in
            # practice 'quiet' does not answer some queries like 'show
            # serial'.
            self._serial.write(b"talk usual\r\n")
            self._serial.readlines()  # discard all pending lines

        # Empty command does nothing and returns nothing extra so we
        # use it to ensure this at least behaves like a Toptica iBeam.
        try:
            self.command(b"")
        except microscope.DeviceError as e:
            raise microscope.InitialiseError(
                "Failed to confirm Toptica iBeam on %s" % (port)
            ) from e

        answer = self.command(b"show serial")
        if not answer.startswith(b"SN: "):
            raise microscope.DeviceError(
                "Failed to parse serial from %s" % answer
            )
        _logger.info("got connection to Toptica iBeam %s", answer.decode())
示例#10
0
    def __init__(self, serial: microscope._utils.SharedSerial) -> None:
        self._serial = serial
        # If the Spectra has just been powered up the first command
        # will fail with UNKNOWNCMD.  So just send an empty command
        # and ignore the result.
        self._serial.write(b"\n")
        self._serial.readline()

        # We use command() and readline() instead of get_command() in
        # case this is not a Lumencor and won't even give a standard
        # answer and raises an exception during the answer validation.
        self._serial.write(b"GET MODEL\n")
        answer = self._serial.readline()
        if not answer.startswith(b"A MODEL Spectra III"):
            raise microscope.InitialiseError(
                "Not a Lumencor Spectra III Light Engine")
示例#11
0
    def __init__(self, serial_number: str, **kwargs) -> None:
        super().__init__(**kwargs)
        self._dm = asdk.Init(serial_number.encode())
        if not self._dm:
            raise microscope.InitialiseError(
                "Failed to initialise connection: don't know why")
        # In theory, asdkInit should return a NULL pointer in case of
        # failure and that should be enough to check.  However, at least
        # in the case of a missing configuration file it still returns a
        # DM pointer so we still need to check for errors on the stack.
        self._raise_if_error(asdk.FAILURE)

        value = asdk.Scalar_p(asdk.Scalar())
        status = asdk.Get(self._dm, b"NbOfActuator", value)
        self._raise_if_error(status)
        self._n_actuators = int(value.contents.value)
        self._trigger_type = microscope.TriggerType.SOFTWARE
        self._trigger_mode = microscope.TriggerMode.ONCE
示例#12
0
    def initialize(self):
        """Initialise the camera.

        Open the connection, connect properties and populate settings
        dict.

        """
        try:
            self.handle = SDK3.Open(self._index)
        except Exception as e:
            raise microscope.InitialiseError("Problem opening camera.") from e
        if self.handle == None:
            raise microscope.InitialiseError("No camera opened.")
        for name, var in sorted(self.__dict__.items()):
            if isinstance(var, ATProperty):
                sdk_name = SDK_NAMES[name]
                if not SDK3.IsImplemented(self.handle, sdk_name):
                    delattr(self, name)
                    continue
                var.connect(self.handle, sdk_name)

                if type(var) is ATCommand:
                    continue

                is_readonly_func = var.is_readonly
                if type(var) is ATEnum:
                    set_func = var.set_index
                    get_func = var.get_index
                    vals_func = var.get_available_values
                else:
                    set_func = var.set_value
                    get_func = var.get_value
                    if type(var) is ATString:
                        vals_func = var.max_length
                    elif type(var) in (ATFloat, ATInt):
                        vals_func = lambda v=var: (v.min(), v.max())
                    else:
                        vals_func = None

                if name in INVALIDATES_BUFFERS:
                    set_func = self.invalidate_buffers(set_func)

                self.add_setting(
                    name.lstrip("_"),
                    PROPERTY_TYPES[type(var)],
                    get_func,
                    set_func,
                    vals_func,
                    is_readonly_func,
                )
        # Default setup.
        self.set_cooling(True)
        if not self._camera_model.getValue().startswith("SIMCAM"):
            self._trigger_mode.set_string("Software")
            self._cycle_mode.set_string("Continuous")
        else:
            _logger.warn("No hardware found - using SIMCAM")

        def callback(*args):
            data = self._fetch_data(timeout=500)
            timestamp = time.time()
            if data is not None:
                self._put(data, timestamp)
                return 0
            else:
                return -1

        self._exposure_callback = SDK3.CALLBACKTYPE(callback)