diff --git a/src/pymodaq_plugins_andor/daq_move_plugins/daq_move_Shamrock.py b/src/pymodaq_plugins_andor/daq_move_plugins/daq_move_Shamrock.py index aa45896..190a202 100644 --- a/src/pymodaq_plugins_andor/daq_move_plugins/daq_move_Shamrock.py +++ b/src/pymodaq_plugins_andor/daq_move_plugins/daq_move_Shamrock.py @@ -195,7 +195,7 @@ def ini_spectro(self): self.grating_list = [] for ind_grating in range(1, Ngratings + 1): (err, lines, blaze, home, offset) = self.shamrock_controller.GetGratingInfoSR(0, ind_grating) - self.grating_list.append(str(int(lines))) + self.grating_list.append(f'G{ind_grating}_'+str(int(lines))) self.settings.child('spectro_settings', 'grating_settings', 'grating').setLimits(self.grating_list) err, ind_grating = self.shamrock_controller.GetGratingSR(0) diff --git a/src/pymodaq_plugins_andor/daq_viewer_plugins/plugins_2D/daq_2Dviewer_AndorCCD.py b/src/pymodaq_plugins_andor/daq_viewer_plugins/plugins_2D/daq_2Dviewer_AndorCCD.py index d35074f..5ce6abd 100644 --- a/src/pymodaq_plugins_andor/daq_viewer_plugins/plugins_2D/daq_2Dviewer_AndorCCD.py +++ b/src/pymodaq_plugins_andor/daq_viewer_plugins/plugins_2D/daq_2Dviewer_AndorCCD.py @@ -13,6 +13,8 @@ from pymodaq.utils.data import DataFromPlugins, Axis, DataToExport from pymodaq_plugins_andor.hardware.andor_sdk2 import sdk2 +from pymodaq.utils.parameter import Parameter +import re libpath = sdk2.dllpath camera_list = sdk2.AndorSDK.GetCamerasInfo() @@ -106,9 +108,11 @@ class DAQ_2DViewer_AndorCCD(DAQ_Viewer_base): {'title': 'End x:', 'name': 'im_endx', 'type': 'int', 'value': 1024 , 'default':1024, 'min':0}, {'title': 'Start y:', 'name': 'im_starty', 'type': 'int', 'value': 1 , 'default':1, 'min':1}, {'title': 'End y:', 'name': 'im_endy', 'type': 'int', 'value': 256, 'default':256, 'min':1,}, - ]}, + ]}, ]}, {'title': 'Exposure (ms):', 'name': 'exposure', 'type': 'float', 'value': 0.01 , 'default':0.01, 'min': 0}, + {'title' : 'EMCCD Gain', 'name' : 'emccd_gain', 'type' : 'int'}, + {'title' : 'AD channels', 'name' : 'ad_channels', 'type' : 'group', 'children' : []}, {'title': 'Image size:', 'name': 'image_size', 'type': 'group', 'children':[ {'title': 'Nx:', 'name': 'Nx', 'type': 'int', 'value': 0, 'default':0 , 'readonly': True}, @@ -179,9 +183,15 @@ def commit_settings(self, param): QtWidgets.QApplication.processEvents() #self.get_exposure_ms() + elif param.name() == 'emccd_gain' : + self.camera_controller.SetEMCCDGain(param.value()) + elif param.name() in iter_children(self.settings.child('camera_settings', 'shutter'), []): self.set_shutter() + elif param.name() in iter_children(self.settings.child('camera_settings', 'ad_channels'), []): + self.set_readout_speed(param.name()) + elif param.name() in iter_children(self.settings.child('camera_settings', 'readout_settings', 'image_settings')): if self.settings.child('camera_settings', 'readout').value() == 'Image': self.set_image_area() @@ -355,6 +365,7 @@ def ini_camera(self): model_param = self.settings.child('camera_settings', 'camera_model') cam_index = model_param.opts['limits'].index(model_param.value()) self.camera_controller.SetCurrentCamera(camera_list[cam_index]['handle']) + self.camera_controller.init_AD_channels() self.CCDSIZEX, self.CCDSIZEY = self.camera_controller.GetDetector() self.settings.child('camera_settings', 'readout_settings', @@ -373,6 +384,25 @@ def ini_camera(self): if err == 'DRV_SUCCESS': self.settings.child('camera_settings', 'exposure').setLimits((0, maxexpo * 1000)) + self.settings.child('camera_settings','emccd_gain').setLimits(self.camera_controller.GetEMGainRange()) + + self.speed_dict = {} + for channel in range(self.camera_controller.channels) : + self.speed_dict[channel] = {str(speed) : self.camera_controller.GetHSSpeed(channel, + self.camera_controller.amp_type, + speed).value for speed in range(self.camera_controller.GetNumberHSSpeeds(channel, + self.camera_controller.amp_type))} + children = [] + for channel_key in self.speed_dict.keys() : + + children.append(Parameter.create(type = 'list', + title = f'AD channel {channel_key}', + name = f'ad_channel_{channel}', + value = self.speed_dict[channel_key]['0'], + limits = self.speed_dict[channel_key].values())) + self.settings.child('camera_settings', 'ad_channels').addChildren(children) + + # set default read mode (full vertical binning) self.update_read_mode() @@ -416,6 +446,15 @@ def set_shutter(self): self.camera_controller.SetShutter(typ, mode, self.settings.child('camera_settings', 'shutter', 'shutter_closing_time').value(), self.settings.child('camera_settings', 'shutter', 'shutter_opening_time').value()) + + def set_readout_speed(self,param_name) : + m = re.search(r"\d+$",param_name) + if m : + adc = int(m.group()) + self.camera_controller.SetADChannel(adc) + freq = self.settings.child('camera_settings','ad_channels', param_name).value() + ind = int([ind for ind, speed in self.speed_dict[adc].items() if speed == freq][0]) + self.camera_controller.SetHSSpeed(self.camera_controller.amp_type, ind ) def updated_timer(self): """ diff --git a/src/pymodaq_plugins_andor/hardware/andor_sdk2/sdk2.py b/src/pymodaq_plugins_andor/hardware/andor_sdk2/sdk2.py index 4e4fc1b..7c666d3 100644 --- a/src/pymodaq_plugins_andor/hardware/andor_sdk2/sdk2.py +++ b/src/pymodaq_plugins_andor/hardware/andor_sdk2/sdk2.py @@ -76,6 +76,7 @@ class AndorSDK: def __init__(self): """ """ + @classmethod def init_camera(cls): # Initialize the device @@ -85,7 +86,6 @@ def init_camera(cls): if error != 20002: raise IOError(ERROR_CODE[error]) - def __del__(self): _dll.ShutDown() @@ -135,7 +135,8 @@ def GetCamerasInfo(cls): cls.init_camera() cameralist.append(dict(handle=handle, serial=cls.GetCameraSerialNumber(), - model=cls.GetHeadModel())) + model=cls.GetHeadModel()), + ) return cameralist # Get Camera properties @@ -172,6 +173,13 @@ def GetHeadModel(cls): if error != 20002: raise IOError(ERROR_CODE[error]) return model.value.decode() + + def init_AD_channels(self) : + self.channels = self.GetNumberADChannels() + try : + self.amp_type = self.SetOutputAmplifier(0) + except IOError : + self.amp_type = self.SetOutputAmplifier(1) def GetDetector(self): ''' @@ -208,7 +216,7 @@ def GetMaximumBinning(self, readmode=0, horver=1): raise IOError(ERROR_CODE[error]) return (ERROR_CODE[error], maxbinning.value) - def GetNumberHSSpeeds(self): + def GetNumberHSSpeeds(self, channel, amp_type): ''' Returns the number of HS speeds @@ -219,7 +227,7 @@ def GetNumberHSSpeeds(self): (int) : the number of HS speeds ''' noHSSpeeds = c_int() - error = _dll.GetNumberHSSpeeds(self._channel, self._outamp, + error = _dll.GetNumberHSSpeeds(channel, amp_type, byref(noHSSpeeds)) if error != 20002: raise IOError(ERROR_CODE[error]) @@ -888,7 +896,7 @@ def SetEMCCDGain(self, gain): if error != 20002: raise IOError(ERROR_CODE[error]) - def GetHSSpeed(self): + def GetHSSpeeds(self, channel, amp_type): ''' Returns the available HS speeds of the selected channel @@ -901,13 +909,29 @@ def GetHSSpeed(self): HSSpeed = c_float() HSSpeeds = [] for i in range(self.GetNumberHSSpeeds()): - error = _dll.GetHSSpeed(self._channel, self._outamp, i, byref(HSSpeed)) + error = _dll.GetHSSpeed(channel, amp_type, i, byref(HSSpeed)) if error != 20002: raise IOError(ERROR_CODE[error]) HSSpeeds.append(HSSpeed.value) return HSSpeeds + + def GetHSSpeed(self, channel, amp_type, speed_index): + ''' + Returns the available HS speeds of the selected channel + + Input: + None + + Output: + (float[]) : The speeds of the selected channel + ''' + HSSpeed = c_float() + error = _dll.GetHSSpeed(channel, amp_type, speed_index, byref(HSSpeed)) + if error != 20002: + raise IOError(ERROR_CODE[error]) + return HSSpeed - def SetHSSpeed(self, index): + def SetHSSpeed(self, amp_type, index): ''' Set the HS speed to the mode corresponding to the index @@ -917,7 +941,7 @@ def SetHSSpeed(self, index): Output: None ''' - error = _dll.SetHSSpeed(index) + error = _dll.SetHSSpeed(amp_type,index) if error != 20002: raise IOError(ERROR_CODE[error])