예제 #1
0
 def load(self):
     self.clib = CLibrary(self.library_file,
                          self.parser,
                          prefix='Lib_',
                          lock_calls=False,
                          convention='cdll',
                          backend='ctypes')
예제 #2
0
	def init_drv(self):
		QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
		self.sigStatusMessage.emit('Loading driver...')
		try:
			drv_path = os.environ['ANDORSDK']
		except KeyError:
			raise Exception('Camera driver not found. Check if envionment variable ANDORSDK exist')

		ANDOR_HEADER = os.path.join(drv_path, 'ATMCD32D.H')
		ANDOR_LIB = os.path.join(drv_path, 'atmcd32d.dll')
		ANDOR_CACHE = os.path.join(drv_path, 'ATMCD32D.cache')
		self.header = CParser([ANDOR_HEADER], cache=ANDOR_CACHE, macros={'WINAPI':''})
		self.camera = CLibrary(ANDOR_LIB, self.header, convention='windll')
		self.DRV_SUCCESS = self.camera.DRV_SUCCESS
		self.values = dict((v, k) for k, v in self.header.defs['values'].items())
		
		QApplication.restoreOverrideCursor()
class CasDll(object):
    def __init__(self, cache_path="cache", lib_path=None, header_path=None):
        if not header_path:
            header_path = r"C:\Program Files\Instrument Systems\CAS4x64-SDK\VC2013\CAS4.h"
        if not lib_path:
            lib_path = r"C:\Windows\System32\CAS4x64.dll"
        lib_name = Path(lib_path).name
        if cache_path:
            cache_name = lib_name + ".cache"
            cache_path_ = Path(cache_path)
            cache_path_.mkdir(parents=True, exist_ok=True)
            cache_file_path = str(cache_path_ / cache_name)
        else:
            cache_file_path = None
        self.parser = CParser(
            header_path,
            cache=cache_file_path,
            replace={"#define __callconv __stdcall": "#define __callconv"})

        self.clib = CLibrary(lib_path, self.parser)

    def new_struct(self, name):
        class_ = getattr(self.clib, name)
        return class_()

    def has_function(self, name):
        try:
            self.clib._get_function(name)
            return True
        except KeyError:
            return False

    def check_cas4_error_code(self, code):
        if (code < self.clib.ErrorNoError):
            p = create_string_buffer(255)
            self.clib.casGetErrorMessageA(code, p, 255)
            raise Exception("CAS Spectrometer Error: {}, {}".format(
                str(code), p.value.decode()))

    def check_cas4_device_error(self, casid):
        self.check_cas4_error_code(self.clib.casGetError(casid).rval)

    def __getattr__(self, name):
        return getattr(self.clib, name)
    def __init__(self, cache_path="cache", lib_path=None, header_path=None):
        if not header_path:
            header_path = r"C:\Program Files\Instrument Systems\CAS4x64-SDK\VC2013\CAS4.h"
        if not lib_path:
            lib_path = r"C:\Windows\System32\CAS4x64.dll"
        lib_name = Path(lib_path).name
        if cache_path:
            cache_name = lib_name + ".cache"
            cache_path_ = Path(cache_path)
            cache_path_.mkdir(parents=True, exist_ok=True)
            cache_file_path = str(cache_path_ / cache_name)
        else:
            cache_file_path = None
        self.parser = CParser(
            header_path,
            cache=cache_file_path,
            replace={"#define __callconv __stdcall": "#define __callconv"})

        self.clib = CLibrary(lib_path, self.parser)
예제 #5
0
    def _setup_library(self):
        """Load and initialize the dll.

        """
        cache_path = str(
            os.path.join(os.path.dirname(__file__), 'adq14.pycctypes.libc'))
        library_dir = os.path.join(self._infos.get('lib_dir', ''),
                                   'ADQAPI.dll')
        header_dir = os.path.join(self._infos.get('header_dir', ''),
                                  'ADQAPI.h')

        self._dll = CLibrary(library_dir, [header_dir],
                             cache=cache_path,
                             prefix=['ADQ', 'ADQ_'],
                             convention='cdll')
예제 #6
0
class AndorCamera(QObject):
	sigStatusMessage = pyqtSignal(str)
	sigAcquiredData = pyqtSignal(list)
	SETTING_SAVE = ['frameNumberSpinBox', 'frameTransferCheckBox', 'exposureTimeSpinBox',
			'shutterComboBox', 'triggerComboBox', 'hbinSpinBox', 'vbinSpinBox', 
			'preAmplifySlider', 'temperatureSpinBox', 'EMGainCheckBox', 'EMGainSpinBox',
			'verticalVoltageSpinBox', 'verticalSpeedSpinBox', 'horizontalVoltageSpinBox']
	
	def __init__(self):
		super().__init__()

		self.lastTemp = None
		self.shot_mode = None
		self.frames_to_shot = 0
		self.frame_number = 0

		self.frames = []
		
		self.progressBar = QProgressBar()
		self.progressBar.setEnabled(False)

		self.tempLabel = QLabel('OFF')

		self.toolbar = QToolBar('Camera')
		self.connectAction = QAction('Connect', self.toolbar, triggered=self.onConnect)
		self.toolbar.addAction(self.connectAction)
		self.settingsAction = QAction('Settings', self.toolbar, triggered=self.onSettings)
		self.settingsAction.setEnabled(False)
		self.toolbar.addAction(self.settingsAction)
		self.startAction = QAction('Start', self.toolbar, triggered=self.onStart)
		self.startAction.setEnabled(False)
		self.toolbar.addAction(self.startAction)

		self.camera = None
		self.flowchart = None
		
		self.settingDialog = CameraSettingDialog()
		self.settingDialog.setModal(True)
		self.settingDialog.accepted.connect(self.setCamera)

		self.settingDialog.verticalSpeedSpinBox.valueChanged.connect(self.onVerticalSpeedChanged)
		self.settingDialog.horizontalVoltageSpinBox.valueChanged.connect(self.onHorizontalSpeedChanged)
		self.settingDialog.EMGainCheckBox.toggled.connect(self.onEMGainChecked)

		self.acqTimer = QTimer()
		self.acqTimer.setSingleShot(False)
		self.acqTimer.setInterval(200)
		self.acqTimer.timeout.connect(self.updateProgress)

		self.tempTimer = QTimer()
		self.tempTimer.setSingleShot(False)
		self.tempTimer.setInterval(3000)
		self.tempTimer.timeout.connect(self.updateTemperature)

	def init_drv(self):
		QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
		self.sigStatusMessage.emit('Loading driver...')
		try:
			drv_path = os.environ['ANDORSDK']
		except KeyError:
			raise Exception('Camera driver not found. Check if envionment variable ANDORSDK exist')

		ANDOR_HEADER = os.path.join(drv_path, 'ATMCD32D.H')
		ANDOR_LIB = os.path.join(drv_path, 'atmcd32d.dll')
		ANDOR_CACHE = os.path.join(drv_path, 'ATMCD32D.cache')
		self.header = CParser([ANDOR_HEADER], cache=ANDOR_CACHE, macros={'WINAPI':''})
		self.camera = CLibrary(ANDOR_LIB, self.header, convention='windll')
		self.DRV_SUCCESS = self.camera.DRV_SUCCESS
		self.values = dict((v, k) for k, v in self.header.defs['values'].items())
		
		QApplication.restoreOverrideCursor()

	def close_drv(self):
		if self.camera is not None:
			result = self.camera.ShutDown().rval

	def onConnect(self):
		if self.connectAction.text() == 'Connect':
			if self.camera is None:
				self.init_drv()

			QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
			self.sigStatusMessage.emit('Connecting camera...')
			result = self.camera.Initialize('.').rval
			QApplication.restoreOverrideCursor()

			if result == self.DRV_SUCCESS:
				self.connectAction.setText('Disconnect')
				self.sigStatusMessage.emit('Connected')
				if self.settingDialog.EMGainCheckBox.isChecked():
					self.ampl_type = 0
				else:
					self.ampl_type = 1
				result = self.camera.GetTemperatureRange()
				self.settingDialog.temperatureSpinBox.setRange(result['mintemp'], result['maxtemp'])
				self.settingDialog.temperatureSpinBox.setValue(result['maxtemp'])
				self.settingDialog.coolerCheckBox.setChecked(False)
				result = self.camera.GetEMGainRange()
				self.settingDialog.EMGainSpinBox.setRange(result['low'], result['high'])
				result = self.camera.GetNumberVSAmplitudes()
				self.settingDialog.verticalVoltageSpinBox.setRange(0, result['number']-1)
				result = self.camera.GetNumberVSSpeeds()
				self.settingDialog.verticalSpeedSpinBox.setRange(0, result['speeds']-1)
				value = self.settingDialog.verticalSpeedSpinBox.value()
				self.onVerticalSpeedChanged(value)
				result = self.camera.GetNumberHSSpeeds(0, self.ampl_type)
				value = self.settingDialog.horizontalVoltageSpinBox.value()
				self.onHorizontalSpeedChanged(value)
				self.settingDialog.horizontalVoltageSpinBox.setRange(0, result['speeds']-1)
				self.settingsAction.setEnabled(True)
				self.startAction.setEnabled(True)
				self.tempTimer.start()
				self.setCamera()
			else:
				self.sigStatusMessage.emit('Connection Error: %s(%d)' % (self.values[result], result))

		
		elif self.connectAction.text() == 'Disconnect':
			self.tempTimer.stop()
			self.close_drv()
			self.connectAction.setText('Connect')
			self.settingsAction.setEnabled(False)
			self.startAction.setEnabled(False)
			self.sigStatusMessage.emit('Disconnected')

	def onEMGainChecked(self, checked):
		if checked:
			self.ampl_type = 0
			self.settingDialog.EMGainSpinBox.setEnabled(True)
		else:
			self.ampl_type = 1
			self.settingDialog.EMGainSpinBox.setEnabled(False)
		result = self.camera.GetNumberHSSpeeds(0, self.ampl_type)
		self.settingDialog.horizontalVoltageSpinBox.setRange(0, result['speeds']-1)
		value = self.settingDialog.horizontalVoltageSpinBox.value()
		self.onHorizontalSpeedChanged(value)

	def onVerticalSpeedChanged(self, value):
		result = self.camera.GetVSSpeed(value)
		self.settingDialog.verticalSpeedLabel.setText('%fMHz' % result['speed'])

	def onHorizontalSpeedChanged(self, value):
		result = self.camera.GetHSSpeed(0, self.ampl_type, value)
		self.settingDialog.horizontalSpeedLabel.setText('%fMHz' % result['speed'])

	def onSettings(self):
		self.settingDialog.show()

	def onStart(self):
		if self.startAction.text() == 'Start':
			self.connectAction.setEnabled(False)
			self.settingsAction.setEnabled(False)
			self.camera.FreeInternalMemory()
			self.startAction.setText('Stop')
			self.progressBar.setRange(0, self.settingDialog.frameNumberSpinBox.value())
			self.progressBar.setValue(0)
			self.progressBar.setEnabled(True)
			self.camera.PrepareAcquisition()
			self.camera.StartAcquisition()
			self.frames_to_shot = self.frame_number
			self.frames = []
			self.acqTimer.start()
		elif self.startAction.text() == 'Stop':
			self.connectAction.setEnabled(True)
			self.settingsAction.setEnabled(True)
			self.acqTimer.stop()
			self.camera.AbortAcquisition()
			self.progressBar.setEnabled(False)
			self.startAction.setText('Start')

	def updateProgress(self):
		status = self.camera.GetStatus()['status']
		if self.shot_mode == 'Kinetics':
			if status == self.camera.DRV_IDLE:
				self.acquire(self.frame_number)
				self.sigAcquiredData.emit(list(self.frames))
				self.frames = []
				self.camera.StartAcquisition()
			elif status == self.camera.DRV_ACQUIRING:
				result = self.camera.GetAcquisitionProgress()
				self.progressBar.setValue(result['series'])
			else:
				self.sigStatusMessage.emit('Status Error: %s(%d)' % (self.values[status], status))
		elif self.shot_mode == 'FastKinetics':
			if status == self.camera.DRV_IDLE:
				self.frames_to_shot -= 2
				self.acquire(2)
				if self.frames_to_shot == 0:
					self.sigAcquiredData.emit(list(self.frames))
					self.frames_to_shot = self.frame_number
					self.frames = []
				self.camera.StartAcquisition()
				self.progressBar.setValue(self.frame_number - self.frames_to_shot)

	def updateTemperature(self):
		temp = self.camera.GetTemperature()['temperature']
		self.tempLabel.setText('%d ℃' % temp)

		if self.lastTemp is not None:
			if temp > self.lastTemp:
				self.tempLabel.setStyleSheet("QLabel { background-color : red;}")
			elif temp < self.lastTemp:
				self.tempLabel.setStyleSheet("QLabel { background-color : blue;}")
			else:
				self.tempLabel.setStyleSheet("QLabel { background-color : green;}")

		self.lastTemp = temp

	def acquire(self, frame_number):
		result = self.camera.GetNumberAvailableImages()
		if result['first'] == 0 and result['last'] == 0:
			return
		hbin = self.settingDialog.hbinSpinBox.value()
		vbin = self.settingDialog.vbinSpinBox.value()
		height = int(512/vbin)
		width = int(512/hbin)
		# frame_number = self.frame_number
		size = height * width * frame_number
		data = np.empty(size, dtype=np.intc)
		self.camera.GetImages(result['first'], result['last'], data.ctypes.data_as(POINTER(c_long)), size)
		self.frames.extend([arr.reshape(width, height) for arr in np.split(data, frame_number)])
			

	# def init_settingsui(self):
	# 	QML_FILENAME = os.path.join(os.path.dirname(__file__), 'CameraSettings.qml')
	# 	self.settingDialog = QQuickView()
	# 	self.settingDialog.setSource(QUrl.fromLocalFile(QML_FILENAME))
	# 	self.settingDialog.setResizeMode(QQuickView.SizeRootObjectToView)

	# 	self.settings = self.settingDialog.rootObject()
	# 	# self.settings.okayClicked.connect(self.output)
	# 	okaybutton = self.settings.findChild(QQuickItem, 'Button')
	# 	okaybutton.onClicked.connect(self.output)

	def setCamera(self):
		hbin = self.settingDialog.hbinSpinBox.value()
		vbin = self.settingDialog.vbinSpinBox.value()
		exposureTime = ctypes.c_float(self.settingDialog.exposureTimeSpinBox.value()/1000.0)
		framenumber = self.settingDialog.frameNumberSpinBox.value()
		self.frame_number = framenumber

		if self.settingDialog.frameTransferCheckBox.isChecked():
			self.shot_mode = 'FastKinetics'
			self.camera.SetAcquisitionMode(4)
			self.camera.SetFastKinetics(512, 2, exposureTime, 4, hbin, vbin)
		else:
			self.shot_mode = 'Kinetics'
			self.camera.SetAcquisitionMode(3)
			self.camera.SetImage(hbin, vbin, 1, 512, 1, 512)
			self.camera.SetExposureTime(exposureTime)
			self.camera.SetNumberKinetics(framenumber)

		trigger = self.settingDialog.triggerComboBox.currentText()
		trigger_dict = {
			'Internal': 0,
			'External': 1
		}
		self.camera.SetTriggerMode(trigger_dict[trigger])

		shutter = self.settingDialog.shutterComboBox.currentText()
		shutter_dict = {
			'Auto': 0,
			'Open': 1,
			'Close': 2
		}
		self.camera.SetShutter(1, shutter_dict[shutter], 27, 27)

		preamp = self.settingDialog.preAmplifySlider.value()
		self.camera.SetPreAmpGain(preamp)

		if self.settingDialog.coolerCheckBox.isChecked():
			self.camera.CoolerON()
			self.camera.SetTemperature(self.settingDialog.temperatureSpinBox.value())
		else:
			self.camera.CoolerOFF()
		if self.settingDialog.EMGainCheckBox.isChecked():
			self.camera.SetEMCCDGain(self.settingDialog.EMGainSpinBox.value())
		else:
			self.camera.SetEMCCDGain(0)

		vvoltage = self.settingDialog.verticalVoltageSpinBox.value()
		self.camera.SetVSAmplitude(vvoltage)

		vspeed = self.settingDialog.verticalSpeedSpinBox.value()
		self.camera.SetVSSpeed(vspeed)

		hspeed = self.settingDialog.horizontalVoltageSpinBox.value()
		self.camera.SetHSSpeed(self.ampl_type, hspeed)

	def close(self):
		self.close_drv()

	def saveState(self):
		state = {}
		for settingName in self.SETTING_SAVE:
			for k in stateFunc:
				if settingName.endswith(k):
					break
			else:
				raise Exception('Unknown setting type %s' % settingName)

			setting = getattr(self.settingDialog, settingName)
			state[settingName] = getattr(setting, stateFunc[k][0])()
		return state

	def restoreState(self, state):
		for settingName, settingState in state.items():
			for k in stateFunc:
				if settingName.endswith(k):
					break
			else:
				raise Exception('Unknown setting type %s' % settingName)

			setting = getattr(self.settingDialog, settingName)
			getattr(setting, stateFunc[k][1])(settingState)
예제 #7
0
def _load_bifrost_lib():
    import os
    import glob

    library_name = "libbifrost.so"
    api_prefix = "bf"
    header_paths = ["/usr/local/include/bifrost",
                    "../src/bifrost"]  # TODO: Remove this one?
    include_env = 'BIFROST_INCLUDE_PATH'
    # PYCLIBRARY ISSUE
    # TODO: Would it make sense to build this into PyCLibrary?
    library_env = 'LD_LIBRARY_PATH'
    home_dir = os.path.expanduser("~")
    parser_cache = os.path.join(home_dir, ".cache/bifrost.parse")

    def _get_env_paths(env):
        paths = os.getenv(env)
        if paths is None:
            return []
        return [p for p in paths.split(':') if len(p.strip())]

    import pyclibrary
    from pyclibrary import CParser, CLibrary

    import ctypes
    # PYCLIBRARY ISSUE Should these be built in? Optional extra?
    # Note: This is needed because pyclibrary starts with only
    #         the fundamental types (short, int, float etc.).
    #extra_types = {}
    #extra_types = {'uint64_t': ctypes.c_uint64}
    extra_types = {
        'uint8_t': ctypes.c_uint8,
        'int8_t': ctypes.c_int8,
        'uint16_t': ctypes.c_uint16,
        'int16_t': ctypes.c_int16,
        'uint32_t': ctypes.c_uint32,
        'int32_t': ctypes.c_int32,
        'uint64_t': ctypes.c_uint64,
        'int64_t': ctypes.c_int64,
        'size_t': ctypes.c_ulong
    }

    try:
        pyclibrary.auto_init(extra_types=extra_types)
    except RuntimeError:
        pass  # WAR for annoying "Can only initialise the parser once"
    header_paths = _get_env_paths(include_env) + header_paths
    valid_header_paths = [p for p in header_paths if os.path.exists(p)]

    # HACK TODO: Decide on what to do here
    valid_header_paths = valid_header_paths[:1]
    if len(valid_header_paths) == 0:
        raise ValueError(
            "No valid Bifrost header paths found. Run make install or set BIFROST_INCLUDE_PATH."
        )
    header_path = valid_header_paths[0]
    headers = glob.glob(os.path.join(header_path, '*.h'))

    pyclibrary.utils.add_header_locations(valid_header_paths)
    try:
        _parser = CParser(headers, cache=unicode(parser_cache, "utf-8"))
    except AttributeError:  # # PYCLIBRARY ISSUE WAR for "'tuple' has no attribute 'endswith'" bug
        raise ValueError("Could not find Bifrost headers.\nSearch paths: " +
                         str(header_paths))
    pyclibrary.utils.add_library_locations(_get_env_paths(library_env))
    lib = CLibrary(library_name, _parser, prefix=api_prefix)
    return lib