def load_mr_params(self, load_file_name=''): """Load the multirun variables array from a file.""" if not load_file_name: load_file_name = self.try_browse( title='Load File', file_type='csv(*.csv);;all (*)', open_func=QFileDialog.getOpenFileName) if load_file_name: with open(load_file_name, 'r') as f: _ = f.readline() vals = [ x.split(',') for x in f.readline().replace('\n', '').split(';') ] header = f.readline().replace('\n', '').split(';') params = f.readline().split(';') for i in range(len(header)): if header[i] in self.ui_param: try: self.ui_param[header[i]] = self.types[header[i]]( params[i]) except ValueError as e: error( 'Multirun editor could not load parameter: %s\n' % params[i] + str(e)) # store values in case they're overwritten after setText() nrows, ncols = np.shape(vals) # update array of values col = int(self.col_index.text()) if self.col_index.text() else 0 nhist, nomit = map( str, [self.ui_param['# in hist'], self.ui_param['# omitted']]) runstep, endstep = self.ui_param[ 'Last time step run'], self.ui_param['Last time step end'] # then update the label edits for key in self.measures.keys( ): # update variable label and measure reset_slot(self.measures[key].textChanged, self.update_all_stats, False) self.measures[key].setText(str(self.ui_param[key])) reset_slot(self.measures[key].textChanged, self.update_all_stats, True) self.set_chan_listbox(col if col < ncols else 0) self.rows_edit.setText(str(nrows)) # triggers change_array_size self.cols_edit.setText(str(ncols)) self.change_array_size() # don't wait for it to be triggered self.reset_array(vals) self.nhist_edit.setText(nhist) self.omit_edit.setText(nomit) self.last_step_run_edit.setText( runstep) # triggers update_last_step self.last_step_end_edit.setText(endstep) for i in range( len(header) ): # restore values as change_array_size loads defaults if header[i] in self.ui_param: try: self.ui_param[header[i]] = self.types[header[i]]( params[i]) except ValueError as e: pass
def change_mr_type(self, newtype): """Enable/Disable list boxes to reflect the multirun type: newtype[str] -- Time step length: only needs timesteps -- Analogue voltage: also needs channels -- AWG: takes float values but with a list index.""" sht = self.tr.get_esc()[2][2:] # 'Sequence header top' if newtype == 'AWG1 chan : seg' or newtype == 'AWG2 chan : seg': self.chan_choices['Time step name'].clear() self.chan_choices['Time step name'].addItems( [str(i) + ', ' + str(j) for j in range(100) for i in range(2)]) reset_slot( self.chan_choices['Analogue type'].currentTextChanged[str], self.change_mr_anlg_type, False) self.chan_choices['Analogue type'].clear() self.chan_choices['Analogue type'].addItems(['AWG Parameter']) self.chan_choices['Analogue channel'].setEnabled(True) self.chan_choices['Analogue channel'].clear() self.chan_choices['Analogue channel'].addItems(self.awg_args) elif 'DDS' in newtype: self.chan_choices['Time step name'].clear() if 'DDS2' in newtype: ddsoptions = [ '%s : P%s - ' % (i + 1, j) + self.COM2[i] for i in range(4) for j in range(8) ] for i in range(4): ddsoptions.insert(i * 9 + 8, '%s : aux - ' % (i + 1) + self.COM2[i]) else: ddsoptions = [ 'COM%s : P%s - ' % (i + 7, j) + self.COM[i] for i in range(5) for j in range(8) ] for i in range(5): ddsoptions.insert(i * 9 + 8, 'COM%s : aux - ' % (i + 7) + self.COM[i]) self.chan_choices['Time step name'].addItems(ddsoptions) reset_slot( self.chan_choices['Analogue type'].currentTextChanged[str], self.change_mr_anlg_type, False) self.chan_choices['Analogue type'].clear() self.chan_choices['Analogue type'].addItems(['DDS Parameter']) self.chan_choices['Analogue channel'].setEnabled(True) self.chan_choices['Analogue channel'].clear() self.chan_choices['Analogue channel'].addItems(self.dds_args) elif newtype == 'SLM holograms': self.chan_choices['Time step name'].clear() slmoptions = ['Hologram %s' % (i) for i in range(9)] self.chan_choices['Time step name'].addItems(slmoptions) reset_slot( self.chan_choices['Analogue type'].currentTextChanged[str], self.change_mr_anlg_type, False) self.chan_choices['Analogue type'].clear() self.chan_choices['Analogue type'].addItems(['Hologram Parameter']) self.chan_choices['Analogue channel'].setEnabled(True) self.chan_choices['Analogue channel'].clear() self.chan_choices['Analogue channel'].addItems(self.slm_args) else: if any(self.chan_choices['Analogue type'].currentText() == x for x in ['AWG Parameter', 'DDS Parameter', 'Hologram Parameter']): self.chan_choices['Analogue type'].clear() self.chan_choices['Analogue type'].addItems( ['Fast analogue', 'Slow analogue']) self.chan_choices['Analogue type'].currentTextChanged[ str].connect(self.change_mr_anlg_type) if newtype == 'Other': self.chan_choices['Analogue channel'].setEnabled(False) self.chan_choices['Time step name'].clear() self.chan_choices['Time step name'].addItems(['Variable']) elif newtype == 'Time step length': self.chan_choices['Analogue channel'].setEnabled(False) self.chan_choices['Time step name'].clear() self.chan_choices['Time step name'].addItems( list( map(str.__add__, [str(i) for i in range(len(sht))], [': ' + hc[6][1].text for hc in sht]))) # time step names elif newtype == 'Analogue voltage': self.chan_choices['Time step name'].clear() self.chan_choices['Time step name'].addItems( list( map(str.__add__, [str(i) for i in range(len(sht))], [': ' + hc[6][1].text for hc in sht]))) # time step names self.chan_choices['Analogue channel'].setEnabled(True) self.chan_choices['Analogue channel'].clear() self.chan_choices['Analogue channel'].addItems( self.get_anlg_chans( self.chan_choices['Analogue type'].currentText().split( ' ')[0]))
def clear_queue(self): """Remove all of the messages from the queue.""" reset_slot(self.textin, self.clear_queue, False) # only trigger clear_queue once self.__mq = []
def init_UI(self): """Create all of the widget objects required""" layout = QVBoxLayout() self.setLayout(layout) # place scroll bars if the contents of the window are too large scroll = QScrollArea(self) layout.addWidget(scroll) scroll_content = QWidget(scroll) scroll.setWidgetResizable(True) scroll.setFixedHeight(800) self.grid = QGridLayout() scroll_content.setLayout(self.grid) #### validators for user input #### double_validator = QDoubleValidator() # floats int_validator = QIntValidator(0, 10000000) # positive integers msr_validator = QIntValidator(-1, 1000000) # integers >= -1 nat_validator = QIntValidator(1, 10000000) # natural numbers col_validator = QIntValidator(1, self.ncols - 1) # for number of columns #### table dimensions and ordering #### # choose the number of rows = number of multirun steps labels = ['# Omit', '# in Histogram', '# Columns', '# Rows'] default = ['5', '100', str(self.ncols), str(self.nrows)] vldtr = [int_validator, nat_validator, nat_validator, nat_validator] self.omit_edit, self.nhist_edit, self.cols_edit, self.rows_edit = [ self.make_label_edit(labels[i], self.grid, [0, 2 * i, 1, 1], default[i], vldtr[i])[1] for i in range(4) ] self.cols_edit.textChanged[str].connect(self.change_array_size) self.rows_edit.textChanged[str].connect(self.change_array_size) self.omit_edit.editingFinished.connect(self.update_repeats) self.nhist_edit.editingFinished.connect(self.update_repeats) # choose the order self.order_edit = QComboBox(self) self.order_edit.addItems( ['ascending', 'descending', 'random', 'coarse random', 'unsorted']) self.grid.addWidget(self.order_edit, 0, 8, 1, 1) #### create multirun list of values #### # metadata for the multirun list: which channels and timesteps self.measures = OrderedDict() labels = ['Variable label', 'measure', 'measure_prefix', '1st hist ID'] defaults = ['Variable 0', '0', 'Measure0', '0'] for i in range(len(labels)): label = QLabel(labels[i], self) self.grid.addWidget(label, i + 1, 0, 1, 1) self.measures[labels[i]] = QLineEdit(defaults[i], self) self.measures[labels[i]].textChanged.connect(self.update_all_stats) self.grid.addWidget(self.measures[labels[i]], i + 1, 1, 1, 3) self.measures['measure'].setValidator(int_validator) self.measures['1st hist ID'].setValidator(msr_validator) label.setText('1st ID (-1 to append)') # change label self.chan_choices = OrderedDict() labels = [ 'Type', 'Time step name', 'Analogue type', 'Analogue channel' ] sht = self.tr.get_esc()[2][2:] # 'Sequence header top' options = [ [ 'Time step length', 'Analogue voltage', 'GPIB', 'AWG1 chan : seg', 'AWG2 chan : seg', 'DDS1 port : profile', 'DDS2 module : profile', 'SLM holograms', 'Other' ], list( map(str.__add__, [str(i) for i in range(len(sht))], [': ' + hc[6][1].text for hc in sht])), # time step names ['Fast analogue', 'Slow analogue'], self.get_anlg_chans('Fast') ] positions = [[1, 4, 3, 2], [1, 6, 6, 1], [1, 7, 3, 1], [1, 8, 6, 1]] widgets = [QComboBox, QListWidget] for i in range(0, len(labels)): self.chan_choices[labels[i]] = widgets[i % 2]() if i % 2: self.chan_choices[labels[i]].setSelectionMode(3) self.chan_choices[labels[i]].addItems(options[i]) self.grid.addWidget(self.chan_choices[labels[i]], *positions[i]) self.chan_choices['Type'].currentTextChanged[str].connect( self.change_mr_type) self.chan_choices['Analogue type'].currentTextChanged[str].connect( self.change_mr_anlg_type) self.chan_choices['Analogue channel'].setEnabled(False) # enter desired time step selection via python cmd self.index_slice = QLineEdit('range(0,1,2)', self) self.grid.addWidget(self.index_slice, 3, 4, 3, 2) self.apply_slice_btn = QPushButton('Apply range', self) self.grid.addWidget(self.apply_slice_btn, 4, 4, 3, 2) self.apply_slice_btn.clicked.connect(self.apply_slice) # AWG takes a list for some arguments, so needs an index label = QLabel('List index:', self) self.grid.addWidget(label, 3, 7, 3, 1) self.list_index = QLineEdit('0', self) self.grid.addWidget(self.list_index, 4, 7, 3, 1) self.list_index.setValidator(int_validator) self.list_index.textEdited[str].connect(self.save_chan_selection) # add a new list of multirun values to the array self.col_index = self.make_label_edit('column index:', self.grid, position=[5, 0, 1, 1], default_text='0', validator=col_validator)[1] self.col_range = QLineEdit('np.linspace(0,1,%s)' % (self.nrows), self) self.grid.addWidget(self.col_range, 5, 2, 1, 2) # show the previously selected channels for this column: self.chan_choices['Time step name'].itemClicked.connect( self.save_chan_selection) self.chan_choices['Analogue channel'].itemClicked.connect( self.save_chan_selection) self.col_range.editingFinished.connect(self.save_chan_selection) self.col_index.textChanged[str].connect(self.set_chan_listbox) # add the column to the multirun values array add_var_button = QPushButton('Add column', self) add_var_button.clicked.connect(self.add_column_to_array) add_var_button.resize(add_var_button.sizeHint()) self.grid.addWidget(add_var_button, 6, 0, 1, 1) # clear the current list of user variables clear_vars_button = QPushButton('Clear', self) clear_vars_button.clicked.connect(self.clear_array) clear_vars_button.resize(clear_vars_button.sizeHint()) self.grid.addWidget(clear_vars_button, 6, 1, 1, 1) # suggest new measure when multirun started self.suggest_button = QPushButton('Auto-increment measure', self, checkable=True, checked=True) self.suggest_button.resize(self.suggest_button.sizeHint()) self.grid.addWidget(self.suggest_button, 6, 2, 1, 2) # choose last time step for multirun lts_label = QLabel('Last time step: ', self) self.grid.addWidget(lts_label, 7, 0, 1, 1) self.last_step_run_edit = self.make_label_edit('Running: ', self.grid, position=[7, 1, 1, 3])[1] self.last_step_run_edit.setText(self.ui_param['Last time step run']) self.last_step_run_edit.textChanged[str].connect(self.update_last_step) self.last_step_end_edit = self.make_label_edit('End: ', self.grid, position=[7, 5, 1, 3])[1] self.last_step_end_edit.setText(self.ui_param['Last time step end']) self.last_step_end_edit.textChanged[str].connect(self.update_last_step) # display current progress multirun_progress = QLabel( 'User variable: , omit 0 of 0 files, 0 of 100 histogram files, 0% complete' ) self.grid.addWidget(multirun_progress, 8, 0, 1, 12) reset_slot(self.progress, multirun_progress.setText, True) # table stores multirun values: self.table = QTableWidget(self.nrows, self.ncols) self.reset_array() self.grid.addWidget(self.table, 9, 0, 20, 12) scroll.setWidget(scroll_content)
def close(self, args=None): """Stop the event loop safely, ensuring that the sockets are closed. Once the thread has stopped, reset the stop toggle so that it doesn't block the thread starting again the next time.""" reset_slot(self.finished, self.reset_stop, True) self.stop = True