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()
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")), )
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")
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" )
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)
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))
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")
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)
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())
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")
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
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)