def get_next_sequence(self, i=None): """Use the values in the multirun array to make the next sequence to run in the multirun. Uses saved mr_param not UI""" if i == None: i = self.ind # row index esc = self.mrtr.get_esc() # shorthand num_s = len(esc[2]) - 2 # number of steps try: for col in range(len(self.mr_vals[i])): # edit the sequence try: val = float(self.mr_vals[i][col]) if self.mr_param['Type'][col] == 'Time step length': for head in [2, 9]: for t in self.mr_param['Time step name'][col]: esc[head][t + 2][3][1].text = str(val) elif self.mr_param['Type'][col] == 'Analogue voltage': for t in self.mr_param['Time step name'][col]: for c in self.mr_param['Analogue channel'][col]: if 'Fast' in self.mr_param['Analogue type'][ col]: esc[6][t + c * num_s + 3][3][1].text = str(val) else: esc[11][t + c * num_s + 3][3][1].text = str(val) except ValueError as e: pass # non-float variable self.mrtr.set_routine_name('Multirun ' + self.mr_param['Variable label'] + \ ': ' + self.mr_vals[i][0] + ' (%s / %s)'%(i+1, len(self.mr_vals))) except IndexError as e: error('Multirun failed to edit sequence at ' + self.mr_param['Variable label'] + ' = ' + self.mr_vals[i][0] + '\n' + str(e)) return self.mrtr.write_to_str()
def save_trace(self, file_name=''): """Save the data currently displayed on the trace to a csv file.""" file_name = file_name if file_name else self.try_browse( 'Save File', 'csv (*.csv);;all (*)', QFileDialog.getSaveFileName) if file_name: # metadata header = ', '.join(list(self.stats.keys())) + '\n' header += ', '.join(list(map( str, self.stats.values()))[:-1]) + ', ' + channel_str( self.stats['channels']) + '\n' # determine which channels are in the plot header += 'Time (s)' data = [] for key, d in self.stats['channels'].items(): if d['plot']: header += ', ' + key # column headings if len(data) == 0: # time (s) data.append(self.lines[int(key[-1])].xData) data.append(self.lines[int(key[-1])].yData) # voltage # data converted to the correct type out_arr = np.array(data).T try: np.savetxt(file_name, out_arr, fmt='%s', delimiter=',', header=header) info('DAQ trace saved to ' + file_name) except (PermissionError, FileNotFoundError) as e: error('DAQ controller denied permission to save file: \n' + str(e))
def save_mr_params(self, save_file_name=''): """Save the variable label, measure, measure prefix, # runs omitted, # runs per histogram, multirun type, list of timesteps, multirun # analogue type, list of channels, and array of variables.""" if not save_file_name: save_file_name = self.try_browse( title='Save File', file_type='csv(*.csv);;all (*)', open_func=QFileDialog.getSaveFileName) if save_file_name: if hasattr(self.sender(), 'text') and self.sender().text() == 'Save Parameters': params, vals = self.ui_param, self.get_table() # save from UI else: params, vals = self.mr_param, self.mr_vals # save from multirun try: with open(save_file_name, 'w+') as f: f.write('Multirun list of variables:\n') f.write(';'.join([ ','.join( [vals[row][col] for col in range(len(vals[0]))]) for row in range(len(vals)) ]) + '\n') f.write(';'.join(params.keys()) + '\n') f.write(';'.join(map(str, list(params.values())))) except (PermissionError, FileNotFoundError) as e: error("Couldn't save Multirun params to file: %s\n" % save_file_name + str(e))
def save_config(self, file_name='daqconfig.dat'): """Save the current acquisition settings to the config file.""" self.stats[ 'config_file'] = file_name if file_name else self.try_browse( 'Save Config File', 'dat (*.dat);;all (*)', QFileDialog.getSaveFileName) # make sure to save all of the channels save_stats = self.stats.copy() statstr = "[[" # dictionary of channel names and properties for i in range(self.channels.rowCount()): statstr += ', '.join([ self.channels.cellWidget(i, j).text() for j in range(self.channels.columnCount()) ]) + '],[' save_stats['channels'] = channel_stats(statstr[:-2] + ']') try: with open(save_stats['config_file'], 'w+') as f: for key, val in save_stats.items(): if key == 'channels': f.write(key + '=' + channel_str(val) + '\n') else: f.write(key + '=' + str(val) + '\n') info('DAQ config saved to ' + save_stats['config_file']) except Exception as e: error('DAQ settings could not be saved to config file.\n' + str(e))
def respond(self, msg=''): """Interpret a TCP message. For setting properties, the syntax is: value=property. E.g. 'Z:\Tweezer=save_dir'.""" if 'save_dir' in msg: self.set_save_dir(msg.split('=')[0]) elif 'trace_file' in msg: self.set_trace_file(msg.split('=')[0]) elif 'graph_file' in msg: self.set_graph_file(msg.split('=')[0]) elif 'start' in msg and not self.toggle.isChecked(): self.toggle.setChecked(True) self.activate() elif 'stop' in msg and self.toggle.isChecked(): self.toggle.setChecked(False) self.activate() elif 'save trace' in msg: self.save_trace( os.path.join(self.stats['save_dir'], self.stats['trace_file'])) elif 'save graph' in msg: self.save_graph( os.path.join(self.stats['save_dir'], self.stats['graph_file'])) elif 'reset graph' in msg: self.reset_graph() elif 'set fadelines' in msg: self.set_fadelines() elif 'measure' in msg: try: x = self.dc.slices[0] self.tcp.add_message( self.stats['n'], str(x.stats[list(x.stats.keys())[0]]['mean'][-1])) except Exception as e: error("Couldn't send measurement.\n" + str(e))
def save_roi_hists(self, file_name='AtomCheckerHist.csv'): """Save the histogram data from the ROIs""" if not file_name: file_name = self.try_browse(title='Select File', file_type='csv(*.csv);;all (*)', open_func=QFileDialog.getSaveFileName) if file_name: try: out_arr = np.zeros((len(self.rh.ROIs) * 2, self.rh.ROIs[0].i)) head0 = '' head1 = '' head2 = '' for i, r in enumerate(self.rh.ROIs): out_arr[2 * i] = r.c out_arr[2 * i + 1] = np.array(r.atom()) head0 += 'ROI%s LP, ROI%s Thresh, ' % (r.id, r.id) head1 += '%s, %s, ' % (r.LP(), r.t) head2 += 'ROI%s Counts, ROI%s Atom, ' % (r.id, r.id) if len(head0): header = head0[:-2] + '\n' + head1[:-2] + '\n' + head2[:-2] else: header = '.\n.\n.' np.savetxt(file_name, out_arr.T, fmt='%s', delimiter=',', header=header) except (ValueError, IndexError, PermissionError) as e: error("AtomChecker couldn't save file %s\n" % file_name + str(e))
def getScaleFactors(self, verbose=0, target=None): """Sort the ROIs and return an array of suggested scale factors to make the intensities uniform.""" lx, ly = self._s # make array of desired scale factors I0s = self.df['I0'].values.reshape(self._s) / self.ref print("\n", self.df['I0'].values / self.ref, "\n") if target: try: target = target / I0s except Exception as e: error("Invalid target for scale factor: " + str(target) + '\n' + str(e)) target = 1 / I0s else: target = 1 / I0s # invert to get correction def func(xy): return np.linalg.norm(np.outer(xy[:lx], xy[lx:]) - target) p0 = np.ones(lx + ly) result = minimize(func, p0, bounds=[[0, 10]] * (lx + ly)) if verbose: info('Array scale factors ' + result.message + '\n' + 'Cost: %s' % result.fun) if verbose > 1: info('Target:\n' + str(target.T) + '\nResult:\n' + str(np.outer(result.x[lx:], result.x[:lx]))) return (result.x[lx:], result.x[:lx]) # note: taking transform
def __init__(self, config_file=".\\ExExposure_config.dat"): super().__init__() # Initialise the parent classes self.lastImage = np.zeros((32, 32)) # last acquired image self.BufferSize = 0 # number of images that can fit in the buffer self.emg = 1.0 # applied EM gain self.pag = 4.50 # preamp gain sensitivity (e- per AD count) self.Nr = 8.8 # readout noise (counts) self.ind = 0 # counter for number of images taken self.idle_time = 0 # time between acquisitions self.t0 = time.time() # time at start of acquisition self.t1 = 0 # time time just after get acquisition self.t2 = time.time() # time after emitting signals self.timeout = 5e3 # number of milliseconds to wait for acquire self.initialised = 0 # check whether the camera functions were loaded try: self.AF = Andor() # functions for Andor camera self.AF.verbosity = False # Set True for debugging self.AF.connected = False self.initialised = 1 # functions loaded but camera not connected if self.AF.OS == "Windows" and self.AF.architecture == "64bit": self.CameraConnect() self.initialised = 2 # camera connected, default config if self.AF.connected == True: self.AF.SetDriverEvent(int(self.AcquisitionEvent)) self.ApplySettingsFromConfig(config_file=config_file) # self.StabiliseTemperature() self.initialised = 3 # fully initialised else: error("Andor SDK requires Windows 64 bit") except Exception as e: self.initialised = 0 warning('Andor EMCCD not initialised.\n' + str(e))
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 show_ROI_masks(self, toggle=True): """Make an image out of all of the masks from the ROIs and display it.""" im = np.zeros(self.rh.shape) for roi in self.rh.ROIs: try: im += roi.mask except ValueError as e: error('ROI %s has mask of wrong shape\n' % roi.id + str(e)) self.update_im(im)
def bind(self, host, port): """Start the socket listening on the given host and port. Fails if the socket is already bound, or if the port is already in use.""" try: self.__s.bind((host, port)) self.__s.listen(0) # only one connection at a time except OSError as e: error('Server address %s, %s'%(host, port) + ' already in use.\n'+str(e))
def write_to_file(self, fname='sequence_example.xml'): """Write the current sequence in the dictionary format to an XML file with name fname.""" try: with open(fname, 'w+') as f: f.write( etree.tostring(self.seq_tree, encoding='cp1252', method='html').decode('cp1252')) except (FileNotFoundError, OSError) as e: error('Translator could not save sequence:\n' + str(e))
def run(self): """Start a continuous acquisition, either with a digital trigger, or a fudged analogue trigger that reads continuously until the input is > TTL.""" try: if 'PFI' in self.trig_chan or 'port' in self.trig_chan: # digital trigger try: with nidaqmx.Task() as self.task, nidaqmx.Task() as ctr: for v, chan in zip(self.vranges, self.channels): # add AI channels c = self.task.ai_channels.add_ai_voltage_chan(chan, terminal_config=const.TerminalConfiguration.DIFFERENTIAL) c.ai_rng_high = v # set voltage range c.ai_rng_low = -v self.task.timing.cfg_samp_clk_timing(self.sample_rate, source='/Dev4/Ctr0InternalOutput', sample_mode=const.AcquisitionType.CONTINUOUS, samps_per_chan=self.n_samples*10, # buffer size must be multiple of n_samples and at least > 10x active_edge=self.edge) # set sample rate and number of samples ctr.co_channels.add_co_pulse_chan_freq('/Dev4/ctr0', # add a counter for triggering freq=self.sample_rate, idle_state=const.Level.LOW) ctr.timing.cfg_implicit_timing(sample_mode=const.AcquisitionType.FINITE, samps_per_chan=self.n_samples) # clock counter emits a pulse of n_samples when triggered # the counter can be retriggered, whereas for our DAQ, AI channels cannot ctr.triggers.start_trigger.cfg_dig_edge_start_trig(self.trig_chan, trigger_edge=self.edge) ctr.triggers.start_trigger.retriggerable = True # when triggered, the counter emits n_samples pulses, which means task reads n_samples in its buffer self.task.register_every_n_samples_acquired_into_buffer_event(self.n_samples, self.read_callback) self.task.start() ctr.start() while not self.check_stop(): self.app.processEvents() # avoid GUI lag time.sleep(0.01) # wait here until stop = True except Exception as e: if not "Some or all of the samples requested have not yet been acquired" in str(e): error("DAQ task setup failed\n"+str(e)) elif 'ai' in self.trig_chan: # fudged analogue trigger with nidaqmx.Task() as self.task: for v, chan in zip(self.vranges, self.channels): c = self.task.ai_channels.add_ai_voltage_chan(chan, terminal_config=const.TerminalConfiguration.DIFFERENTIAL) c.ai_rng_high = v # set voltage range c.ai_rng_low = -v self.task.timing.cfg_samp_clk_timing(self.sample_rate, sample_mode=const.AcquisitionType.CONTINUOUS, samps_per_chan=self.n_samples+10000) # set sample rate and number of samples while not self.check_stop(): self.app.processEvents() try: TTL = self.task.read()[self.trig] # read a single value from the trigger channel except TypeError: TTL = self.task.read() # if there is only one channel if TTL > self.lvl: data = self.task.read(number_of_samples_per_channel=self.n_samples) if np.size(np.shape(data)) == 1: data = [data] # if there's only one channel, still make it a 2D array self.acquired.emit(np.array(data)) except Exception as e: error("DAQ acquisition stopped.\n"+str(e))
def load_xml_str(self, text=""): """Load a sequence as a dictionary from an xml string.""" try: self.seq_tree = etree.fromstring(text, parser=self.parser) for e in self.seq_tree.iter(): if e.text == None: e.text = '' self.setup_multirun() self.write_to_str() except (lxml.etree.XMLSyntaxError) as e: self.seq_tree = root error('Translator could not load sequence:\n' + str(e))
def slave_acquire(self): """Stop the previous slave running and start the next. This allows us to cycle through channels and avoid ghosting.""" try: self.slaves[self.slaveind - 1].stop = True self.slaves[self.slaveind - 1].quit() time.sleep( 0.1) # need to give enough time for the previous slave to stop self.slaves[self.slaveind].stop = False self.slaves[self.slaveind].start() except (IndexError, ZeroDivisionError) as e: error('Could not start slave %s:\n' % self.slaveind + str(e))
def counter_out(self, channel, high_time, low_time): """Start a continuous counter output channel which is high for high_time and low for low_time in units of seconds. The counter channels are Dev/ctr0 and Dev/ctr1.""" try: with nidaqmx.Task() as task: task.co_channels.add_co_pulse_chan_time(channel) task.cfg_implicit_timing(const.AcquisitionType.CONTINUOUS) task.start() task.write(nidaqmx.types.CtrTime(high_time=high_time, low_time=low_time)) except Exception as e: error("DAQ CO write failed.\n"+str(e))
def load_xml(self, fname='./sequences/SequenceFiles/empty.xml'): """Load a sequence as a dictionary from an xml file.""" try: self.seq_tree = etree.parse(fname, parser=self.parser).getroot() for e in self.seq_tree.iter(): if e.text == None: e.text = '' self.setup_multirun() self.write_to_str() except (FileNotFoundError, OSError, IndexError) as e: self.seq_tree = root error('Translator could not load sequence:\n' + str(e))
def load_full_im(self, im_name): """return an array with the values of the pixels in an image. Assume that the first column is the column number. Keyword arguments: im_name -- absolute path to the image file to load""" # return np.genfromtxt(im_name, delimiter=self.delim)#[:,1:] # first column gives column number try: return np.loadtxt(im_name, delimiter=self.delim, usecols=range(1,self.pic_width+1)) except IndexError as e: error('Image analysis failed to load image '+im_name+'\n'+str(e)) return np.zeros((self.pic_width, self.pic_height))
def make_roi_grid(self, toggle=True, method=''): """Create a grid of ROIs and assign them to analysers that are using the same image. Methods: Single ROI -- make all ROIs the same as the first analyser's Square grid -- evenly divide the image into a square region for each of the analysers on this image. 2D Gaussian masks-- fit 2D Gaussians to atoms in the image.""" method = method if method else self.sender().text() pos, shape = self.rh.ROIs[0].roi.pos(), self.rh.ROIs[0].roi.size() if method == 'Single ROI': for r in self.rh.ROIs: r.resize(*map(int, [pos[0], pos[1], shape[0], shape[1]])) elif method == 'Square grid': n = len(self.rh.ROIs) # number of ROIs d = int((n - 1)**0.5 + 1) # number of ROIs per row X = int(self.rh.shape[0] / d) # horizontal distance between ROIs Y = int(self.rh.shape[1] / int((n - 3 / 4)**0.5 + 0.5)) # vertical distance for i in range(n): # ID of ROI try: newx, newy = int(X * (i % d + 0.5)), int(Y * (i // d + 0.5)) if any( [newx // self.rh.shape[0], newy // self.rh.shape[1]]): warning( 'Tried to set square ROI grid with (xc, yc) = (%s, %s)' % (newx, newy) + ' outside of the image') newx, newy = 0, 0 self.rh.ROIs[i].resize(*map(int, [newx, newy, 1, 1])) except ZeroDivisionError as e: error('Invalid parameters for square ROI grid: ' + 'x - %s, y - %s, pic size - %s, roi size - %s.\n' % (pos[0], pos[1], self.rh.shape[0], (shape[0], shape[1])) + 'Calculated width - %s, height - %s.\n' % (X, Y) + str(e)) elif method == '2D Gaussian masks': try: im = self.im_canvas.image.copy() - self.rh.bias if np.size(np.shape(im)) == 2: for r in self.rh.ROIs: r.create_gauss_mask( im) # fit 2D Gaussian to max pixel region # then block that region out of the image try: im[r.x - r.w:r.x + r.w + 1, r.y - r.h:r.y + r.h + 1] = np.zeros( (2 * r.w + 1, 2 * r.h + 1)) + np.min(im) except (IndexError, ValueError): pass except AttributeError: pass
def save_rois(self, file_name='', ROIlist=[]): """Save the coordinates and thresholds of the ROIs""" if not file_name: file_name = self.try_browse(title='Select File', file_type='txt(*.txt);;all (*)', open_func=QFileDialog.getSaveFileName) if file_name: try: with open(file_name, 'w+') as f: f.write(str(ROIlist)) except (ValueError, IndexError, PermissionError) as e: error("AtomChecker couldn't save file %s\n" % file_name + str(e))
def get_opt_sequence(self): """Edit the sequence with the optimised value.""" try: val = self.f.ps[self.setp['Param index']] except IndexError as e: error('Could not retrieve best fit param: '+str(f.ps)+'\n'+str(e)) return '' esc = self.mr.tr.get_esc() # shorthand num_s = len(esc[2]) - 2 # number of steps try: if self.mr.mr_param['Type'][0] == 'Time step length': for head in [2, 9]: for t in self.mr.mr_param['Time step name'][0]: esc[head][t+2][3][1].text = str(val) elif self.mr.mr_param['Type'][0] == 'Analogue voltage': for t in self.mr.mr_param['Time step name'][0]: for c in self.mr.mr_param['Analogue channel'][0]: if 'Fast' in self.mr.mr_param['Analogue type'][0]: esc[6][t + c*num_s + 3][3][1].text = str(val) else: esc[11][t + c*num_s + 3][3][1].text = str(val) tcpmsg = self.get_tcp_msg('%.4f'%val) self.mr.tr.set_routine_name('Fitted ' + self.mr.mr_param['Variable label'] + \ ': %.4f'%val except IndexError as e: error('Multirun failed to edit sequence at ' + self.mr.mr_param['Variable label'] + '\n' + str(e)) return (self.mr.tr.write_to_str(), tcpmsg) #### save and load parameters #### def load_params(self, load_file_name=''): """Load the multirun variables array from a file.""" if not load_file_name: load_file_name = self.mr.try_browse(title='Load File', file_type='csv(*.csv);;all (*)', open_func=QFileDialog.getOpenFileName) if load_file_name: self.mr.load_mr_params(load_file_name) try: 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(';') mr_params = f.readline().split(';') params = json.loads(f.readline()) for key, val in params.items(): self.setp[key] = val self.request_analysis.emit(self.setp['Analysis Window']) except Exception as e: self.display('Failed to load file %s.\n'%load_file_name+str(e))
def set_fadelines(self): """Take the data from the current lines and sets it to the fadelines.""" for j in range(8): ch = self.channels.cellWidget(j, 0).text() l = self.lines[j] # shorthand if ch in self.stats['channels'] and self.stats['channels'][ch][ 'plot']: try: self.fadelines[j].setData(l.xData, l.yData) except Exception as e: error('DAQ trace could not be plotted.\n' + str(e)) self.fadelines[j].show() else: self.fadelines[j].hide()
def load_rois(self, file_name=''): """Load the coordinates and thresholds of the ROIs""" if not file_name: file_name = self.try_browse(title='Select File', file_type='txt(*.txt);;all (*)', open_func=QFileDialog.getOpenFileName) if file_name: try: with open(file_name, 'r') as f: ROIlist = eval(f.readline()) self.rh.create_rois(len(ROIlist)) self.rh.resize_rois(ROIlist) self.display_rois() except (ValueError, IndexError, PermissionError) as e: error("AtomChecker couldn't save file %s\n" % file_name + str(e))
def analogue_awg_out(self, channel, data, sample_rate, n_samples, acq_type=const.AcquisitionType.FINITE): """Write the data provided to the analogue output channel. channel -- channel name, e.g. 'Dev4/ao0' data -- numpy array of the data to write to the channel sample_rate -- the rate at which to take samples from the data n_samples -- the number of samples to write. If n_samples > size(data) it will loop over the data acq_type -- FINITE writes n_samples then stops, CONTINUOUS loops indefinitely.""" try: with nidaqmx.Task() as task: task.ao_channels.add_ao_voltage_chan(channel) task.timing.cfg_samp_clk_timing(rate=sample_rate, sample_mode=acq_type, samps_per_chan=n_samples) writer = stream_writers.AnalogSingleChannelWriter(task.out_stream, auto_start=True) writer.write_many_sample(data) # task.wait_until_done() # blocks until the task has finished # task.stop() # end the task properly except Exception as e: error("DAQ AO write failed.\n"+str(e))
def analogue_acquisition(self): """Take a single acquisition on the specified channels.""" try: with nidaqmx.Task() as self.task: for v, chan in zip(self.vranges, self.channels): c = self.task.ai_channels.add_ai_voltage_chan(chan, terminal_config=const.TerminalConfiguration.DIFFERENTIAL) c.ai_rng_high = v # set voltage range c.ai_rng_low = -v self.task.timing.cfg_samp_clk_timing(self.sample_rate, sample_mode=const.AcquisitionType.CONTINUOUS, samps_per_chan=self.n_samples+1000) data = self.task.read(number_of_samples_per_channel=self.n_samples) # task.wait_until_done(-1) if np.size(np.shape(data)) == 1: data = [data] # if there's only one channel, still make it a 2D array self.acquired.emit(np.array(data)) except Exception as e: error("DAQ read failed\n"+str(e))
def run(self): """Use the values in the multirun array to make the next sequence to run in the multirun. Uses saved mr_param not UI""" if self.savedir: for i in range(len(self.mr_vals)): self.app.processEvents( ) # avoids GUI lag but slows this task down esc = self.mrtr.get_esc( ) # shorthand for experimental sequence cluster num_s = len(esc[2]) - 2 # number of steps try: for col in range(len( self.mr_vals[i])): # edit the sequence try: val = float(self.mr_vals[i][col]) if self.mr_param['Type'][ col] == 'Time step length': for head in [2, 9]: for t in self.mr_param['Time step name'][ col]: esc[head][t + 2][3][1].text = str( val) # time step length elif self.mr_param['Type'][ col] == 'Analogue voltage': for t in self.mr_param['Time step name'][col]: for c in self.mr_param['Analogue channel'][ col]: if 'Fast' in self.mr_param[ 'Analogue type'][col]: esc[6][t + c * num_s + 3][3][1].text = str(val) else: esc[11][t + c * num_s + 3][3][1].text = str(val) except ValueError: pass self.mrtr.set_routine_name('Multirun ' + self.mr_param['Variable label'] + \ ': ' + self.mr_vals[i][0] + ' (%s / %s)'%(i+1, len(self.mr_vals))) self.mrtr.write_to_file( os.path.join( self.savedir, self.mr_param['measure_prefix'] + '_' + str(i + self.mr_param['1st hist ID']) + '.xml')) except IndexError as e: error('Multirun failed to edit sequence at ' + self.mr_param['Variable label'] + ' = ' + self.mr_vals[i][0] + '\n' + str(e))
def multirun_save(self, msg): """end of histogram: fit, save, and reset --- check this doesn't miss an image if there's lag""" v = self.seq.mr.ind // ( self.seq.mr.mr_param['# omitted'] + self.seq.mr.mr_param['# in hist']) - 1 # previous variable try: prv = self.seq.mr.mr_vals[v][ 0] # get user variable from the previous row except AttributeError as e: error( 'Multirun step could not extract user variable from table at row %s.\n' % v + str(e)) prv = '' # fit and save data self.sw.multirun_save(self.sv.results_path, self.seq.mr.mr_param['measure_prefix'], self._n, prv, str(v + self.seq.mr.mr_param['1st hist ID']))
def skip_mr_hist(self): """Remove the TCP messages for the current histogram so that MR skips it""" try: queue = self.server.get_queue() self.server.clear_queue() for i, item in enumerate(queue): # find the end of the histogram if 'save and reset histogram' in item[1]: break self.next_mr = [[TCPENUM['TCP read'], '||||||||' + '0' * 2000] ] + queue[i + 1:] self.sw.all_hists(action='Reset') r = self.seq.mr.ind % (self.seq.mr.mr_param['# omitted'] + self.seq.mr.mr_param['# in hist']) self.seq.mr.ind += self.seq.mr.mr_param[ '# omitted'] + self.seq.mr.mr_param['# in hist'] - r self.add_mr_msgs() except IndexError as e: error('Failed to skip histogram. IndexError:\n' + str(e))
def write_to_str(self): """Store the current sequence in the dictionary in XML string format specified by LabVIEW and return this string.""" try: tree = self.copy().seq_tree _ = tree[1][tdict['Routine description']] # need to swap the order tree[1][tdict['Routine description']] = tree[1][ tdict['Routine name']] tree[1].append(_) txt = etree.tostring(tree, encoding='cp1252', method='html').decode('cp1252') self.seq_txt = txt[txt.index('<Cluster>'):].replace( '</LVData>', '') except TypeError as e: error('Translator could not write sequence to str\n' + str(e)) self.seq_txt = '' return self.seq_txt
def save_chan_selection(self, arg=None): """When the user changes the selection of channels/timesteps for the given column, save it. The selection will be reloaded if the user changes the column and then comes back.""" try: if self.col_index.text(): col = int(self.col_index.text()) for key in ['Type', 'Analogue type']: self.ui_param[key][col] = self.chan_choices[ key].currentText() for key in ['Time step name', 'Analogue channel']: self.ui_param[key][col] = list( map(self.chan_choices[key].row, self.chan_choices[key].selectedItems())) self.ui_param['list index'][col] = int( self.list_index.text()) if self.list_index.text() else 0 self.col_range_text[col] = self.col_range.text() except (ValueError, IndexError) as e: error("Multirun couldn't save channel choices for column " + self.col_index.text() + '.\n' + str(e))