class ThorPM100(ThorlabsPM100, Instrument): num_averages = DumbNotifiedProperty() def __init__(self, address='USB0::0x1313::0x8072::P2004571::0::INSTR', num_averages=100, calibration=None): """A quick wrapper to create a gui and bring in nplab features to the pm100 thorlabs power meter """ rm = visa.ResourceManager() instr = rm.open_resource(address) super(ThorPM100, self).__init__(instr) self.num_averages = 100 self.ui = None if calibration == None: self.calibration = 1.0 else: self.calibration = calibration def read_average(self, num_averages=None): """a quick averaging tool for the pm100 power meter """ if num_averages == None: num_averages = self.num_averages values = [] for i in range(num_averages): values.append(self.read) return np.average(values) def read_average_power(self): """Return the average power including a calibration """ return self.read_average() * self.calibration average_power = NotifiedProperty(read_average_power) def update_power(self): """Update the power in the gui """ self.ui.controls['Power'].setText(str(self.average_power)) def get_qt_ui(self): if self.ui == None: self.ui = ThorlabsPM100_widget(self) return self.ui def set_wavelength(self, wavelength): self.power_meter.sense.correction.wavelength = wavelength def get_wavelength(self): return self.sense.correction.wavelength wavelength = NotifiedProperty(get_wavelength, set_wavelength)
class inspire_OPO(SerialInstrument): port_settings = dict( baudrate=9600, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, timeout=1, #wait at most one second for a response writeTimeout=1, #similarly, fail if writing takes >1s xonxoff=False, rtscts=False, dsrdtr=False, ) def __init__(self, port): self.mode = 'power' self.initialise() def initialise(self): self.write('00 550.0') def set_wavelength(self, wavelength): wavelength = str(int(wavelength)) + '.0' self.write(self.mode_dict[self.mode] + wavelength) def get_wavelength(self): wavelength = self.query('50 550.0') return wavelength wavelength = NotifiedProperty(get_wavelength, set_wavelength) def enable_power_mode(self): self.query(mode_dict['power'] + ' ' + self.wavelength) mode_dict = {'tune': '03', 'power': '04'} def SHG_on(self): self.query('08 000.0') def SHG_off(self): self.query('09 000.0') def SHG_find(self): self.query('10 000.0') def SHG_optimise(self): self.query('11 000.0') def auto_cavity(self): self.query('07 ' + self.wavelength)
class Maitai(SerialInstrument): port_settings = dict( baudrate=38400, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, timeout=1, #wait at most one second for a response writeTimeout=1, #similarly, fail if writing takes >1s xonxoff=True, rtscts=False, dsrdtr=False, ) termination_character = "\n" def __init__(self, port): '''Maitai Ti:saphire laser: just requires port number to inialise ''' super(Maitai, self).__init__(port) self.set_watchdog(0) def on(self): '''Turn the Maitai on''' self.write('ON') def off(self): '''Turn the Maitai off''' self.write('OFF') def open_shutter(self): '''Opens the shutter using the shutter state property''' self.shutter_state = True def close_shutter(self): '''Close the shutter using the shutter state property ''' self.shutter_state = False def get_shutter_state(self): '''Get shutter state and convert it to a bool returns: bool: True == open and False == close''' return bool(int(self.query('SHUTTER?'))) def set_shutter_state(self, state): ''' Sets the shutter from a bool Args: bool True == Open, false == closed ''' self.write('SHUTTER ' + str(int(state))) shutter_state = NotifiedProperty(get_shutter_state, set_shutter_state) def get_humidity(self): '''Returns the humidity ''' return self.query('READ:HUM?') def get_power(self): '''Returns the IR power ''' return self.query('READ:PLASER:POWER?') def get_current_wavelength(self): ''' The current real time wavelength - allowing you to check if the maitai ahs moved to the set wavelength yet ''' return self.query('READ:WAVELENGTH?') current_wavelength = property(get_current_wavelength) def save(self): '''Save tje current maitai settings for restart ''' self.write('SAVE') def get_set_wavelength(self): ''' wavelength(float): The current set wavelength of the Maitai (in nm) must between 690 and 1020 ''' return float(self.query('WAVELENGTH?')[:-2]) def set_wavelength(self, wavelength): if wavelength > 690 and wavelength < 1020: return self.write('WAVELENGTH ') else: self.log('Wavelength out of range (' + wavelength + ')') wavelength = NotifiedProperty(get_set_wavelength, set_wavelength) def set_watchdog(self, n): '''Sets the watchdog timer i.e. the ammount of time the laser will keep itself on without stay alive command. If set to zero this is disabled ''' self.write('TIMER:WATCHDOG ' + str(n)) def get_qt_ui(self): return MaitaiControlUI(self)
class Image_Filter_box(Instrument): threshold = DumbNotifiedProperty() bin_fac = DumbNotifiedProperty() min_size = DumbNotifiedProperty() max_size = DumbNotifiedProperty() bilat_height = DumbNotifiedProperty() bilat_size = DumbNotifiedProperty() morph_kernel_size = DumbNotifiedProperty() show_particles = DumbNotifiedProperty() return_original_with_particles = DumbNotifiedProperty() def __init__(self, threshold=40, bin_fac=4, min_size=2, max_size=6, bilat_size=3, bilat_height=40, morph_kernel_size=3): self.threshold = threshold self.bin_fac = bin_fac self.min_size = min_size self.max_size = max_size self.bilat_size = bilat_size self.bilat_height = bilat_height self.morph_kernel_size = morph_kernel_size self.filter_options = [ 'None', 'STBOC_with_size_filter', 'strided_rescale', 'StrBiThresOpen' ] self.show_particles = False self.return_original_with_particles = False self.current_filter_index = 0 self.update_functions = [] def current_filter(self, image): if self.current_filter_proxy == None: return image else: return self.current_filter_proxy(image) def set_current_filter_index(self, filter_index): filter_name = self.filter_options[filter_index] self._filter_index = filter_index if filter_name == 'None': self.current_filter_proxy = None else: self.current_filter_proxy = getattr(self, filter_name) self._current_filter_str = filter_name def get_current_filter_index(self): return self._filter_index current_filter_index = NotifiedProperty(fget=get_current_filter_index, fset=set_current_filter_index) def STBOC_with_size_filter(self, g, return_centers=False): try: return STBOC_with_size_filter( g, bin_fac=self.bin_fac, bilat_size=self.bilat_size, bilat_height=self.bilat_height, threshold=self.threshold, min_size=self.min_size, max_size=self.max_size, morph_kernel_size=self.morph_kernel_size, show_particles=self.show_particles, return_original_with_particles=self. return_original_with_particles, return_centers=return_centers) except Exception as e: self.log('Image processing has failed due to: ' + str(e), level='WARN') def strided_rescale(self, g): try: return strided_rescale(g, bin_fac=self.bin_fac) except Exception as e: self.log('Image processing has failed due to: ' + str(e), level='WARN') def StrBiThresOpen(self, g): try: return StrBiThresOpen(g, bin_fac=self.bin_fac, bilat_size=self.bilat_size, bilat_height=self.bilat_height, threshold=self.threshold, morph_kernel_size=self.morph_kernel_size) except Exception as e: self.log('Image processing has failed due to: ' + str(e), level='WARN') def connect_function_to_property_changes(self, function): # print function for variable_name in vars(self.__class__): self.update_functions.append(function) if (type(getattr(self.__class__, variable_name)) == DumbNotifiedProperty or type(getattr(self.__class__, variable_name)) == NotifiedProperty): register_for_property_changes(self, variable_name, self.update_functions[-1]) def get_qt_ui(self): return Camera_filter_Control_ui(self)
class ThreadBox3000(QuickControlBox): '''A gui/threading utility for running a function in a thread with a simple control window ''' def __init__(self, function=None): super(ThreadBox3000, self).__init__('ThreadBox3000') self.function = function def add_controls(self, function): '''Inspect the inputted function and automatically generate controls by looking the defaults ''' full_args = inspect.getargspec(function) self.add_checkbox('save_returned') self.add_lineedit('function name') self.controls['function name'].setText(str(function)) self.controls['function name'].setReadOnly(True) if 'self' in full_args.args: full_args.args.remove('self') if (full_args.defaults != None and len(full_args.args) == len(full_args.defaults)): for arg, default in zip(full_args.args, full_args.defaults): if type(default) == int: self.add_spinbox(arg) self.controls[arg].setValue(default) elif type(default) == float: self.add_doublespinbox(arg) self.controls[arg].setValue(default) elif type(default) == bool: self.add_checkbox(arg) self.controls[arg].setChecked(default) elif hasattr(default, '__call__'): self.add_lineedit(arg) try: self.controls[arg].setText(default.func_name) except Exception as e: print e self.controls[arg].setText(default.__name__) self.controls[arg].setReadOnly(True) else: self.add_lineedit(arg) if type(default) == np.ndarray: temp_txt = np.array2string(default).replace( ' ', ',') # danger - might need to check formatter temp_txt = temp_txt.replace(' ', ',') temp_txt = temp_txt.replace(' ', ',') temp_txt = temp_txt.replace('[,', '[') temp_txt = temp_txt.replace(',]', ']') txt = 'np.array(' + temp_txt + ')' elif type(default) == str: txt = "'" + default + "'" else: txt = str(default) self.controls[arg].setText(txt) self.add_button('start') self.controls['start'].pressed.connect(self.start) def construct_payload(self): '''Construct the function with the arguments set in the control window ''' def payload(save_group=df._current_group): import numpy as np input_variables = {} for variable in self.controls.keys(): if variable == 'save_returned' or variable == 'start' or variable == 'function name': continue variable_control = self.controls[variable] if type(variable_control) == type(QtWidgets.QLineEdit( )) and variable_control.isReadOnly() == True: fullargs = inspect.getargspec(self.function) args = fullargs.args try: args.remove('self') except ValueError: pass args = np.array(args) defaults = np.array(fullargs.defaults) default_value = defaults[args == variable] input_variables[variable] = default_value[0] print variable, default_value elif (type(variable_control) == QtWidgets.QSpinBox or type(variable_control) == QtWidgets.QDoubleSpinBox): input_variables[variable] = variable_control.value() elif type(variable_control) == QtWidgets.QLineEdit: try: exec 'temp_var = ' + variable_control.text() in locals( ) input_variables[variable] = temp_var except Exception as e: print e print 'Qlineedit input error for ', variable elif type(variable_control) == QtWidgets.QCheckBox: input_variables[variable] = variable_control.isChecked() try: function_returns = self.function(**input_variables) except TypeError: print input_variables print 'function: ', task print 'Did not recieve the correct inputs!' print 'did you make an error in your lineedit inputs?' if self.controls['save_returned'].isChecked() == True: save_group.create_dataset(task, data=function_returns, attrs=input_variables) return payload def clean_box(self): '''Remove all of the controls from the box ''' if len(self.children()) > 1: #check if the box contains any controls for child in self.children()[1:]: child.deleteLater() self.controls = dict() def set_function(self, function): '''Sets the function, by clearing the old function with 'clean_box' and adding the controls for he new function ''' self._function = function self.clean_box() if function is not None: self.add_controls(function) def get_function(self): '''The getter for the current function ''' return self._function function = NotifiedProperty(fget=get_function, fset=set_function) @background_action @locked_action def start(self): '''Construct and start the function ''' self.construct_payload()() def get_qt_ui(self): return self
class Frequency_counter_F390(SerialInstrument): port_settings = dict(baudrate=115200, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, xonxoff=True, timeout=1.0) termination_character = "\n" update_data_signal = QtCore.Signal(np.ndarray) def __init__(self, port=None, integration_time=1): SerialInstrument.__init__(self, port=port) self.live_window = 100 self._live_view = False self.int_time = integration_time self.write('FO') #do not apply low pass filter self.write('Z5') #for 50 Ohms impedance function_dict = { '0': 'B Input Period', '1': 'A Input Period', '2': 'A Input Frequency', '3': 'B Input Frequency', '4': 'Frequency Ratio B:A', '5': 'A Input Width High', '6': 'A Input Width Low', '7': 'A Input Count', '8': 'A Input Ratio H:L', '9': 'A Input Duty Cycle', 'C': 'C Input Frequency', 'D': 'C Input Period' } def get_function(self): '''A property to set the required function of the frequency counter Args: f: the a string value of the function shown in the table below and in self.function_dict 0 B Input Period 1 A Input Period 2 A Input Frequency 3 B Input Frequency 4 Frequency Ratio B:A 5 A Input Width High 6 A Input Width Low 7 A Input Count 8 A Input Ratio H:L 9 A Input Duty Cycle C C Input Frequency D C Input Period returns: the current function ''' return self.function_dict(self._function) def set_function(self, f): self._function = str(f) self.write('F' + str(f)) function = property(fget=get_function, fset=set_function) def get_identity(self): '''Returns the device id (good for testing comms) ''' return self.query('*IDN?') def test_communications(self): '''A command to allow autodetection to work ''' if self.get_identity().split(',')[0] == 'Thurlby-Thandar': return True def measure_next(self): '''Return the next valid measurement''' try: return float(self.query('N?')[:-2]) except: print(self.query('N?')[:-2]) def measure_next_fast(self): '''Return the invalid measurement (i.e. refereshs at LCD refresh rate, not the measreument rate)''' try: return float(self.query('?')[:-2]) except: print(self.query('?')[:-2]) # def start_countinous_fast(self): # '''Starts fast streaming of values at the LCD refresh rate ''' # self.write('C?') # def start_countinous_single(self): # '''Starts continuous streaming of values at the rate of the measurement time''' # self.write('E?') # def stop_countinous(self): # self.write('STOP') def get_live_view_window(self): return self._live_window def set_live_view_window(self, window_length): self._live_window = window_length '''Set the number of the stored values in the deque ''' self.live_deque = deque(maxlen=window_length) live_window = NotifiedProperty(get_live_view_window, set_live_view_window) int_times = {0.3: '1', 1: '2', 10: '3', 100: '4'} impedances = {'50': 'Z5', '1M': 'Z1'} def get_int_time(self): '''A property for the integration time possible values are: 0.3 s, 1s, 10s,100s ''' return self._int_time def set_int_time(self, integration_time): self._int_time = integration_time try: self.write('M' + self.int_times[integration_time]) except KeyError: self.log('Invalid integration time', level='WARN') int_time = NotifiedProperty(get_int_time, set_int_time) def get_qt_ui(self): self.ui = CounterUI(self) self.display_ui = self.ui.preview_widget self.control_ui = self.ui.control_widget return self.ui def get_preview_widget(self): self.display_ui = CounterPreviewWidget(self) return self.display_ui def get_control_widget(self): self.control_ui = CounterControlUI(self) return self.control_ui def _live_view_function(self): '''The function that is run within the live preview thread ''' while self._live_view: data = None data = self.measure_next_fast() # while data == None: time.sleep(self.int_time) self.live_deque.append([data, time.time()]) self.display_ui.update_data_signal.emit(np.array(self.live_deque)) def get_live_view(self): '''Setting up the notificed property live view to allow live view to be switch on and off ''' return self._live_view def set_live_view(self, enabled): if enabled == True: try: self._live_view = True self._live_view_stop_event = threading.Event() self._live_view_thread = threading.Thread( target=self._live_view_function) self._live_view_thread.start() except AttributeError as e: #if any of the attributes aren't there print("Error:", e) else: if not self._live_view: return # do nothing if it's not running. print("stopping live view thread") try: self._live_view = False self._live_view_stop_event.set() self._live_view_thread.join() del (self._live_view_stop_event, self._live_view_thread) except AttributeError: raise Exception( "Tried to stop live view but it doesn't appear to be running!" ) live_view = NotifiedProperty(get_live_view, set_live_view)
class Digikrom(SerialInstrument): port_settings = dict( baudrate=9600, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, timeout=1, #wait at most one second for a response writeTimeout=1, #similarly, fail if writing takes >1s xonxoff=False, rtscts=False, dsrdtr=False, ) def __init__(self, port=None, serial_number=[50, 52, 51, 49, 55]): self.termination_character = '' self.serial_number = serial_number super(Digikrom, self).__init__(port=port) def query(self, message, convert_to_hex=True, return_as_dec=True, max_len_returned=10, block=True): """The digikrom uses fixed length commands and has no termination character therefore the query function from serialinstrument needs to be overwritten. As the digikrom requires input in hex commands must be changed from decimal (as listed in the manual) to hex. The returned messages also need the same treatment The maximum length of the returned str can also be specified to maximise speed as currently it just waits for timeout""" if convert_to_hex == True: message_hex = self.encode_bytes(message) else: message_hex = message self.write(message_hex) returned_message = self.ser.read(max_len_returned) if return_as_dec == True: returned_message = self.decode_bytes(returned_message) if returned_message[-1] == 24: block = False self.set_status_byte(returned_message[-2]) elif (returned_message != [message]): self.set_status_byte(returned_message[-1]) while block == True: block_message = self.decode_bytes(self.ser.read_all()) if len(block_message) == 1: if block_message[0] == 24: block = False return returned_message @staticmethod def decode_bytes(byte_str): """The digikrom uses decimal charcters therefore it is helpful to translate hex (returned from the digikrom) into a list of decimal values to prevent asci mishaps """ decimal_list = [] for byte in byte_str: decimal_list.append(ord(byte)) return decimal_list @staticmethod def encode_bytes(decimal_list): """The digikrom uses decimal charcters but recieves hex therefore it is helpful to translate decimal values into hex to send to the digikrom """ if type(decimal_list) != list: decimal_list = [decimal_list] byte_str = '' for decimal in decimal_list: byte = chr(decimal) byte_str += byte return byte_str def set_status_byte(self, status_byte): """Extract the status from the status byte """ binary_byte = bin(status_byte)[2:] if len(binary_byte) != 8: binary_byte = (8 - len(binary_byte)) * '0' + binary_byte if binary_byte[0] == 1: motor_movement_order = 'negative' else: motor_movement_order = 'positive' if binary_byte[4] == 1: scan_direction = 'positive' else: scan_direction = 'negative' if binary_byte[7] == '0': value_accepted = True value_error = None else: value_accepted = False if binary_byte[6] == '1': value_error = 'repeat set' elif binary_byte[5] == '1': value_error = 'value too large' elif binary_byte[5] == '0': value_error = 'value too small' CSR_mode = bool(int(binary_byte[2])) status_dict = { 'value_accepted': value_accepted, 'value_error': value_error, 'motor_movement_order': motor_movement_order, 'scan_direction': scan_direction, 'CSR_mode': CSR_mode } if value_accepted == True: level = 'debug' else: level = 'warn' self.log(status_dict, level=level) self._status_byte = status_dict def get_wavelength(self): """The get wavlength command number is 29 and data is returned as 3 bytes, the high byte, the mid byte and the low bye. These byte correspond to multiples of 65536, 256 and 1. as shown below""" returned_message = self.query(29) wl = returned_message[1] * 65536 wl += 256 * returned_message[2] wl += returned_message[3] self.set_status_byte(returned_message[-2]) return wl / 100.0 def set_wavelength(self, wl): """The set wavlength command number is 16 and data is sent as 3 bytes, the high byte, the mid byte and the low bye. These byte correspond to multiples of 65536, 256 and 1. as shown below""" self.query(16, block=False) wl = wl * 100 high_byte = int(old_div(wl, 65536)) wl = wl - high_byte * 65536 mid_byte = int(old_div(wl, 256)) wl = wl - mid_byte * 256 low_byte = int(wl) self.query([high_byte, mid_byte, low_byte]) centre_wavlength = NotifiedProperty(get_wavelength, set_wavelength) def get_grating_id(self): info = self.query(19) info_dict = { 'number_of_gratings': info[1], 'current_grating': info[2], 'grating_ruling': info[3] * 256 + info[4], 'grating_blaze': info[5] * 256 + info[6] } return info_dict def set_grating(self, grating_number): """This command changes gratings , if additional gratings installed..""" self.query(26) self.query(grating_number) def reset(self): """This command returns the grating to home position """ self.query([255, 255, 255]) def clear(self): """This command restores factory calibration values for the grating and slits. This command also executes a reset, which returns the grating to home position.""" self.query(25) def CSR(self, bandpass_value): """ This command sets monochromator to Constant Spectral Resolution mode. The slit width will vary throughout a scan. This is useful, for example, where measurement of a constant interval of frequency is desired (spectral power distribution measurements).""" self.query(28) high_byte = int(old_div(bandpass_value, 256)) bandpass_value = bandpass_value - high_byte * 256 low_byte = int(bandpass_value) self.query([high_byte, low_byte]) def echo(self): """The ECHO command is used to verify communications with the DK240/480. """ self.log(self.query(27), level='info') def gval(self, repositioning_wl): """This command allows recalibration of the monochromator positioning scale factor and should be used immediately after using the ZERO command (see page 15). The monochromator should be set to the peak of a known spectral line, then the position of that line is input using the CALIBRATE command. """ self.query(18) repositioning_wl = repositioning_wl * 100 high_byte = int(old_div(repositioning_wl, 65536)) repositioning_wl = repositioning_wl - high_byte * 65536 mid_byte = int(old_div(repositioning_wl, 256)) repositioning_wl = repositioning_wl - mid_byte * 256 low_byte = int(repositioning_wl) self.query([high_byte, mid_byte, low_byte]) def get_serial(self): """ Returns the 5 digit serial number of the monochromator.""" return self.query(33)[1:-2] def get_slit_widths(self): """Returns the current four byte (six byte for DK242) slit width. First two bytes are high and low byte of the entrance slit width in microns. Second two bytes are the high and low byte of the exit slit width. For DK242, the last two bytes are for middle slit width.""" slit_info = self.query(30)[1:-2] slit_info = np.array(slit_info) low_byte = slit_info[1::2] high_byte = slit_info[::2] slit_info = 256 * high_byte + low_byte return slit_info def set_all_slits(self, slit_width): """ Adjusts all slits to a given width. """ high_byte = int(old_div(slit_width, 256)) slit_width = slit_width - high_byte * 256 low_byte = int(slit_width) self.query(14) self.query([high_byte, low_byte]) def set_slit_1_width(self, slit_width): """Adjusts entrance slit to a given width.""" high_byte = int(old_div(slit_width, 256)) slit_width = slit_width - high_byte * 256 low_byte = int(slit_width) self.query(31) self.query([high_byte, low_byte]) def set_slit_2_width(self, slit_width): """Adjusts exit slit to a given width.""" """Slit 2 (exit) not installed 05042019""" high_byte = int(old_div(slit_width, 256)) slit_width = slit_width - high_byte * 256 low_byte = int(slit_width) self.query(32) self.query([high_byte, low_byte]) def set_slit_3_width(self, slit_width): """Adjusts middle slit to a given width.""" high_byte = int(old_div(slit_width, 256)) slit_width = slit_width - high_byte * 256 low_byte = int(slit_width) self.query(34) self.query([high_byte, low_byte]) def test_communications(self): """Check there is the correct digikrom at other end of the COM port.""" try: serial_num = self.get_serial() except: return False if serial_num == self.serial_number: return True else: return False
class Shamrock(Instrument): def __init__(self): super(Shamrock, self).__init__() #for Windows self.dll2 = CDLL( "C:\\Program Files\\Andor SOLIS\\Drivers\\Shamrock64\\atshamrock") self.dll = CDLL( "C:\\Program Files\\Andor SOLIS\\Drivers\\Shamrock64\\ShamrockCIF") tekst = c_char() error = self.dll.ShamrockInitialize(byref(tekst)) self.current_shamrock = 0 #for more than one Shamrock this has to be varied, see ShamrockGetNumberDevices self.center_wavelength = 0.0 def verbose(self, error, function=''): self.log("[%s]: %s" % (function, error), level='info') #basic Shamrock features def Initialize(self): error = self.dll.ShamrockInitialize("") self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name) def GetNumberDevices(self): no_shamrocks = c_int() error = self.dll.ShamrockGetNumberDevices(byref(no_shamrocks)) self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name) return no_shamrocks.value num_shamrocks = property(GetNumberDevices) def Close(self): error = self.dll.ShamrockClose() self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name) def GetSerialNumber(self): ShamrockSN = c_char() error = self.dll.ShamrockGetSerialNumber(self.current_shamrock, byref(ShamrockSN)) self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name) return ShamrockSN serial_number = property(GetSerialNumber) def EepromGetOpticalParams(self): self.FocalLength = c_float() self.AngularDeviation = c_float() self.FocalTilt = c_float() error = self.dll.ShamrockEepromGetOpticalParams( self.current_shamrock, byref(self.FocalLength), byref(self.AngularDeviation), byref(self.FocalTilt)) return { 'FocalLength': self.FocalLength, 'AngularDeviation': self.AngularDeviation, 'FocalTilt': self.FocalTilt } #basic Grating features def GratingIsPresent(self): is_present = c_int() error = self.dll.ShamrockGratingIsPresent(self.current_shamrock, is_present) self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name) return is_present.vlaue grating_present = property(GratingIsPresent) def GetTurret(self): Turret = c_int() error = self.dll.ShamrockGetTurret(self.current_shamrock, byref(Turret)) self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name) return Turret.value def SetTurret(self, turret): error = self.dll.ShamrockSetTurret(self.current_shamrock, c_int(turret)) self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name) turret_position = NotifiedProperty(GetTurret, SetTurret) def GetNumberGratings(self): self.noGratings = c_int() error = self.dll.ShamrockGetNumberGratings(self.current_shamrock, byref(self.noGratings)) self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name) return self.noGratings num_gratings = property(GetNumberGratings) def GetGrating(self): grating = c_int() error = self.dll.ShamrockGetGrating(self.current_shamrock, byref(grating)) self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name) return grating current_grating = property(GetGrating) def GetGratingInfo(self): lines = c_float() blaze = c_char() home = c_int() offset = c_int() error = self.dll.ShamrockGetGratingInfo(self.current_shamrock, self.current_grating, byref(lines), byref(blaze), byref(home), byref(offset)) CurrGratingInfo = [lines.value, blaze.value, home.value, offset.value] self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name) return CurrGratingInfo GratingInfo = property(GetGratingInfo) def GetGratingOffset(self): GratingOffset = c_int() #not this is in steps, so int error = self.dll.ShamrockGetGratingOffset(self.current_shamrock, self.current_grating, byref(GratingOffset)) self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name) return GratingOffset def SetGratingOffset(self, offset): error = self.dll.ShamrockSetGratingOffset(self.current_shamrock, self.current_grating, c_int(offset)) self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name) Grating_offset = NotifiedProperty(GetGratingOffset, SetGratingOffset) def GetDetectorOffset(self): DetectorOffset = c_int() #not this is in steps, so int error = self.dll.ShamrockGetDetectorOffset(self.current_shamrock, byref(self.DetectorOffset)) self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name) return DetectorOffset def SetDetectorOffset(self, offset): error = self.dll.ShamrockSetDetectorOffset(self.current_shamrock, self.current_grating, c_int(offset)) self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name) detector_offset = NotifiedProperty(GetDetectorOffset, SetDetectorOffset) #Wavelength features def WavelengthIsPresent(self): ispresent = c_int() error = self.dll.ShamrockWavelengthIsPresent(self.current_shamrock, byref(ispresent)) self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name) return ispresent.value motor_present = property(WavelengthIsPresent) def GetWavelength(self): curr_wave = c_float() error = self.dll.ShamrockGetWavelength(self.current_shamrock, byref(curr_wave)) self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name) return curr_wave.value def SetWavelength(self, centre_wl): error = self.dll.ShamrockSetWavelength(self.current_shamrock, c_float(centre_wl)) self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name) center_wavelength = NotifiedProperty(GetWavelength, SetWavelength) def AtZeroOrder(self): is_at_zero = c_int() error = self.dll.ShamrockAtZeroOrder(self.current_shamrock, byref(is_at_zero)) self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name) return is_at_zero.value wavelength_is_zero = property(AtZeroOrder) def GetWavelengthLimits(self): min_wl = c_float() max_wl = c_float() error = self.dll.ShamrockGetWavelengthLimits(self.current_shamrock, self.current_grating, byref(min_wl), byref(max_wl)) wl_limits = [min_wl.value, max_wl.value] self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name) return wl_limits wavelength_limits = property(GetWavelengthLimits) def GotoZeroOrder(self): error = self.dll.ShamrockGotoZeroOrder(self.current_shamrock) self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name) #Slit functions def AutoSlitIsPresent(self): present = c_int() slits = [] for i in range(1, 5): self.dll.ShamrockAutoSlitIsPresent(self.current_shamrock, i, present) slits.append(present.value) return slits Autoslits = property(AutoSlitIsPresent) #Sets the slit to the default value (10um) def AutoSlitReset(self, slit): error = self.dll.ShamrockAutoSlitReset(self.current_shamrock, self.current_slit) self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name) #finds if input slit is present def SlitIsPresent(self): slit_present = c_int() error = self.dll.ShamrockSlitIsPresent(self.current_shamrock, byref(slit_present)) self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name) return slit_present.value slit_present = property(SlitIsPresent) #Output Slits def GetAutoSlitWidth(self, slit): slitw = c_float() error = self.dll.ShamrockGetAutoSlitWidth(self.current_shamrock, slit, byref(slitw)) self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name) return slitw.value def SetAutoSlitWidth(self, slit, width): slit_w = c_float(width) error = self.dll.ShamrockSetAutoSlitWidth(self.current_shamrock, slit, slit_w) self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name) return width #Input Slits def GetSlit(self): slitw = c_float() error = self.dll.ShamrockGetSlit(self.current_shamrock, byref(slitw)) self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name) return slitw.value def SetSlit(self, width): slit_w = c_float(width) error = self.dll.ShamrockSetSlit(self.current_shamrock, slit_w) self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name) slit_width = NotifiedProperty(GetSlit, SetSlit) def SlitReset(self): error = self.dll.ShamrockSlitReset(self.current_shamrock) self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name) #Calibration functions def SetPixelWidth(self, width): error = self.dll.ShamrockSetPixelWidth(self.current_shamrock, c_float(width)) self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name) def GetPixelWidth(self): pixelw = c_float() error = self.dll.ShamrockGetPixelWidth(self.current_shamrock, byref(pixelw)) self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name) return pixelw.value pixel_width = NotifiedProperty(GetPixelWidth, SetPixelWidth) def GetNumberPixels(self): numpix = c_int() error = self.dll.ShamrockGetNumberPixels(self.current_shamrock, byref(numpix)) self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name) return numpix.value def SetNumberPixels(self, pixels): error = self.dll.ShamrockSetNumberPixels(self.current_shamrock, pixels) self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name) pixel_number = NotifiedProperty(GetNumberPixels, SetNumberPixels) def GetCalibration(self): ccalib = c_float * self.pixel_number ccalib_array = ccalib() error = self.dll.ShamrockGetCalibration(self.current_shamrock, pointer(ccalib_array), self.pixel_number) self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name) calib = [] for i in range(len(ccalib_array)): calib.append(ccalib_array[i]) return calib[:] wl_calibration = property(GetCalibration) def GetPixelCalibrationCoefficients(self): ca = c_float() cb = c_float() cc = c_float() cd = c_float() error = self.dll.ShamrockGetPixelCalibrationCoefficients( self.current_shamrock, byref(ca), byref(cb), byref(cc), byref(cd)) self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name) return [ca, cb, cc, cd] PixelCalibrationCoefficients = property(GetPixelCalibrationCoefficients) def get_qt_ui(self): return ShamrockControlUI(self)
class Arduino_tri_shutter(SerialInstrument): '''Control class for tri shutter ''' def __init__(self, port=None): '''Set up baudrate etc and recenters the stage to the center of it's range (50um) Args: port(int/str): The port the device is connected to in any of the accepted serial formats ''' self.termination_character = '\n' self.port_settings = { 'baudrate': 9600, # 'bytesize':serial.EIGHTBITS, 'timeout': 2, #wait at most one second for a response } self.termination_character = '\r\n' SerialInstrument.__init__(self, port=port) def set_shutter_1_state(self, state): """Set State Command for Shutter 1 used by check box """ if state == True: self._open_shutter_1() elif state == False: self._close_shutter_1() def set_shutter_2_state(self, state): """Set State Command for Shutter 2 used by check box """ if state == True: self._open_shutter_2() elif state == False: self._close_shutter_2() def set_mirror_1_state(self, state): """Set State Command for flipper 1 used by check box """ if state == True: self._flip_mirror_0() elif state == False: self._flip_mirror_1() def open_shutter_1(self): """Usable open shutter 1 function that updates GUI when used""" self.Shutter_1_State = True def close_shutter_1(self): """Usable close shutter 1 function that updates GUI when used""" self.Shutter_1_State = False def open_shutter_2(self): """Usable open shutter 2 function that updates GUI when used""" self.Shutter_2_State = True def close_shutter_2(self): """Usable close shutter 2 function that updates GUI when used""" self.Shutter_2_State = False def flip_mirror_0(self): """Usable open flip_mirror 1 function that updates GUI when used""" self.Flipper_1_State = False def flip_mirror_1(self): """Usable close flip mirror 1 function that updates GUI when used""" self.Flipper_1_State = False def _open_shutter_1(self): """do not use! Hidden access to open shutter """ self.query('A') def _close_shutter_1(self): """do not use! hidden close shutter function""" self.query('B') def _open_shutter_2(self): """do not use! Hidden access to open shutter """ self.query('C') def _close_shutter_2(self): """do not use! hidden close shutter function""" self.query('D') def _flip_mirror_0(self): """do not use! hidden open flipper function""" self.query('E') def _flip_mirror_1(self): """do not use! hidden open flipper function""" self.query('F') # def get_state(self): # return self.query('Read') # def set_state(self,state): # self.query(state) def get_qt_ui(self): self.ui = tri_shutter_ui(self) return self.ui def read_state(self): states = self.query('S') states = states.split(',') states = [bool(int(state)) for state in states] return states states = NotifiedProperty(fget=read_state) def get_state_1(self): return self.states[0] def get_state_2(self): return self.states[1] def get_state_3(self): return self.states[2] Shutter_1_State = NotifiedProperty(fset=set_shutter_1_state, fget=get_state_1) Shutter_2_State = NotifiedProperty(fset=set_shutter_2_state, fget=get_state_2) Flipper_1_State = NotifiedProperty(fset=set_mirror_1_state, fget=get_state_3)
class Trandor(Andor): #Andor ''' Wrapper class for the Triax and the andor ''' def __init__(self, White_Shutter=None): # print '__________________' # print 'Triax Information:' super(Trandor, self).__init__() self.triax = Triax('GPIB0::1::INSTR', Calibration_Arrays, CCD_Size) #Initialise triax self.White_Shutter = White_Shutter self.SetParameter('SetTemperature', -90) #Turn on andor cooler self.CoolerON() self.triax.ccd_size = CCD_Size # print '______________________' # print 'Current Grating:',self.triax.Grating() # print 'Current Slit Width:', self.triax.Slit(),'um' # print '______________________' self.Notch_Filters_Tested = True def Grating(self, Set_To=None): return self.triax.Grating(Set_To) def Generate_Wavelength_Axis(self): return self.triax.Get_Wavelength_Array() def Set_Center_Wavelength(self, wavelength): ''' backwards compatability with lab codes that use trandor.Set_Center_Wavelength''' self.triax.Set_Center_Wavelength(wavelength) def Test_Notch_Alignment(self): Accepted = False while Accepted is False: Input = eval( input( 'WARNING! A slight misalignment of the narrow band notch filters could be catastrophic! Has the laser thoughput been tested? [Yes/No]' )) if Input.upper() in ['Y', 'N', 'YES', 'NO']: Accepted = True if len(Input) > 1: Input = Input.upper()[0] if Input.upper() == 'Y': print('You are now free to capture spectra') self.Notch_Filters_Tested = True else: print( 'The next spectrum capture will be allowed for you to test this. Please LOWER the laser power and REDUCE the integration time.' ) self.Notch_Filters_Tested = None def capture(self, Close_White_Shutter=True): """ Edits the capture function is a white light shutter object is supplied, to ensure it is closed while the image is taken. This behaviour can be overwirtten by passing Close_White_Shutter=False """ if self.Notch_Filters_Tested is False: self.Test_Notch_Alignment() return (np.array(list(range(CCD_Size))) * 0, 1, (CCD_Size, )) else: if self.Notch_Filters_Tested is None: self.Notch_Filters_Tested = False if self.White_Shutter is not None and Close_White_Shutter is True: try: self.White_Shutter.close_shutter() except: Dump = 1 Output = Andor_Capture_Function(self) try: self.White_Shutter.open_shutter() except: Dump = 1 return Output else: return Andor_Capture_Function(self) x_axis = NotifiedProperty( Generate_Wavelength_Axis) #This is grabbed by the Andor code