def plugin_setup_complete(self, BLACS): self.BLACS = BLACS self.ui = UiLoader().load(os.path.join(PLUGINS_DIR, module, 'controls.ui')) self.bar = self.ui.bar self.style = QtWidgets.QStyleFactory.create('Fusion') if self.style is None: # If we're on Qt4, fall back to Plastique style: self.style = QtWidgets.QStyleFactory.create('Plastique') if self.style is None: # Not sure what's up, but fall back to app's default style: self.style = QtWidgets.QApplication.style() self.bar.setStyle(self.style) self.bar.setMaximum(BAR_MAX) self.bar.setAlignment(QtCore.Qt.AlignCenter) # Add our controls to the BLACS gui: BLACS['ui'].queue_status_verticalLayout.insertWidget(0, self.ui) # We need to know the name of the master pseudoclock so we can look up # the duration of each shot: self.master_pseudoclock = self.BLACS['experiment_queue'].master_pseudoclock # Check if the wait monitor device, if any, supports wait completed events: with h5py.File(self.BLACS['connection_table_h5file'], 'r') as f: if 'waits' in f: acq_device = f['waits'].attrs['wait_monitor_acquisition_device'] acq_device = _ensure_str(acq_device) if acq_device: props = properties.get(f, acq_device, 'connection_table_properties') if props.get('wait_monitor_supports_wait_completed_events', False): self.wait_completed_events_supported = True self.ui.wait_warning.hide()
def transition_to_buffered(self, device_name, h5file, initial_values, fresh): self.logger.debug('transition_to_buffered') # read channels, acquisition rate, etc from H5 file with h5py.File(h5file, 'r') as f: group = f['/devices/' + device_name] if 'AI' not in group: # No acquisition return {} AI_table = group['AI'][:] device_properties = properties.get(f, device_name, 'device_properties') chans = [_ensure_str(c) for c in AI_table['connection']] # Remove duplicates and sort: if chans: self.buffered_chans = sorted(set(chans), key=split_conn_AI) self.h5_file = h5file self.buffered_rate = device_properties['acquisition_rate'] self.acquired_data = [] # Stop the manual mode task and start the buffered mode task: self.stop_task() self.buffered_mode = True self.start_task(self.buffered_chans, self.buffered_rate) return {}
def transition_to_buffered(self, device_name, h5file, initial_values, fresh): # get stop time: with h5py.File(h5file, 'r') as f: props = properties.get(f, self.device_name, 'device_properties') self.stop_time = props.get( 'stop_time', None ) # stop_time may be absent if we are not the master pseudoclock return {}
def transition_to_buffered(self, device_name, h5file, initial_values, fresh): print('boo! transtion to buffered') # get stop time: with h5py.File(h5file, 'r') as hdf5_file: props = properties.get(hdf5_file, device_name, 'device_properties') self.stop_time = props.get( 'stop_time', None ) # stop_time may be absent if we are not the master pseudoclock group = hdf5_file['devices/%s' % device_name] pulse_program = group['PULSE_PROGRAM'][:] device_properties = labscript_utils.properties.get( hdf5_file, device_name, 'device_properties') self.is_master_pseudoclock = device_properties[ 'is_master_pseudoclock'] return {}
def _start(self, h5_filepath): """Called from the mainloop when starting a shot""" self.h5_filepath = h5_filepath # Get the stop time, any waits and any markers from the shot: with h5py.File(h5_filepath, 'r') as f: props = properties.get(f, self.master_pseudoclock, 'device_properties') self.stop_time = props['stop_time'] try: self.markers = f['time_markers'][:] self.markers.sort(order=(bytes if PY2 else str)('time')) except KeyError: self.markers = None try: self.waits = f['waits'][:] self.waits.sort(order=(bytes if PY2 else str)('time')) except KeyError: self.waits = None self.shot_start_time = time.time() self.time_spent_waiting = 0 self.next_marker_index = 0 self.next_wait_index = 0
def get_traces(self, add_trace, clock=None): """Reads the shot file and extracts hardware instructions to produce runviewer traces. Args: add_trace (func): function handle that adds traces to runviewer clock (tuple, optional): clock times from timing device, if not the primary pseudoclock Returns: dict: Dictionary of clocklines and triggers derived from instructions """ if clock is not None: times, clock_value = clock[0], clock[1] clock_indices = np.where( (clock_value[1:] - clock_value[:-1]) == 1)[0] + 1 # If initial clock value is 1, then this counts as a rising edge # (clock should be 0 before experiment) but this is not picked up # by the above code. So we insert it! if clock_value[0] == 1: clock_indices = np.insert(clock_indices, 0, 0) clock_ticks = times[clock_indices] # get the pulse program pulse_programs = [] with h5py.File(self.path, "r") as f: # Get the device properties device_props = properties.get(f, self.name, "device_properties") conn_props = properties.get(f, self.name, "connection_table_properties") self.clock_resolution = device_props["clock_resolution"] self.trigger_delay = device_props["trigger_delay"] self.wait_delay = device_props["wait_delay"] # Extract the pulse programs num_pseudoclocks = conn_props["num_pseudoclocks"] for i in range(num_pseudoclocks): pulse_programs.append( f[f"devices/{self.name}/PULSE_PROGRAM_{i}"][:]) # Generate clocklines and triggers clocklines_and_triggers = {} for pseudoclock_name, pseudoclock in self.device.child_list.items(): # Get pseudoclock index connection_parts = pseudoclock.parent_port.split() # Skip if not one of the 4 possible pseudoclock outputs (there is one for # the wait monitor too potentially) if connection_parts[0] != "pseudoclock": continue # Get the pulse program index = int(connection_parts[1]) pulse_program = pulse_programs[index] time = [] states = [] trigger_index = 0 t = 0 if clock is None else clock_ticks[ trigger_index] + self.trigger_delay trigger_index += 1 clock_factor = self.clock_resolution / 2.0 last_instruction_was_wait = False for row in pulse_program: if row["reps"] == 0 and not last_instruction_was_wait: # WAIT last_instruction_was_wait = True if clock is not None: t = clock_ticks[trigger_index] + self.trigger_delay trigger_index += 1 else: t += self.wait_delay elif last_instruction_was_wait: # two waits in a row means an indefinite wait, so we just skip this # instruction. last_instruction_was_wait = False continue else: last_instruction_was_wait = False for i in range(row["reps"]): for j in range(1, -1, -1): time.append(t) states.append(j) t += row["half_period"] * clock_factor pseudoclock_clock = (np.array(time), np.array(states)) for clock_line_name, clock_line in pseudoclock.child_list.items(): # Ignore the dummy internal wait monitor clockline if clock_line.parent_port.startswith("GPIO"): clocklines_and_triggers[ clock_line_name] = pseudoclock_clock add_trace(clock_line_name, pseudoclock_clock, self.name, clock_line.parent_port) return clocklines_and_triggers
def get_traces(self, add_trace, clock=None): with h5py.File(self.path, 'r') as f: group = f['devices/' + self.name] if 'AO' in group: AO_table = group['AO'][:] else: AO_table = None if 'DO' in f['devices/%s' % self.name]: DO_table = group['DO'][:] else: DO_table = None props = properties.get(f, self.name, 'connection_table_properties') version = props.get('__version__', None) if version is None: msg = """Shot was compiled with the old version of the NI_DAQmx device class. The new runviewer parser is not backward compatible with old shot files. Either downgrade labscript_devices to 2.2.0 or less, or recompile the shot with labscript_devices 2.3.0 or greater.""" raise VersionException(dedent(msg)) ports = props['ports'] static_AO = props['static_AO'] static_DO = props['static_DO'] times, clock_value = clock[0], clock[1] clock_indices = np.where((clock_value[1:] - clock_value[:-1]) == 1)[0] + 1 # If initial clock value is 1, then this counts as a rising edge (clock should # be 0 before experiment) but this is not picked up by the above code. So we # insert it! if clock_value[0] == 1: clock_indices = np.insert(clock_indices, 0, 0) clock_ticks = times[clock_indices] traces = {} if DO_table is not None: ports_in_use = DO_table.dtype.names for port_str in ports_in_use: for line in range(ports[port_str]["num_lines"]): # Extract each digital value from the packed bits: line_vals = (((1 << line) & DO_table[port_str]) != 0).astype(float) if static_DO: line_vals = np.full(len(clock_ticks), line_vals[0]) traces['%s/line%d' % (port_str, line)] = (clock_ticks, line_vals) if AO_table is not None: for chan in AO_table.dtype.names: vals = AO_table[chan] if static_AO: vals = np.full(len(clock_ticks), vals[0]) traces[chan] = (clock_ticks, vals) triggers = {} for channel_name, channel in self.device.child_list.items(): if channel.parent_port in traces: trace = traces[channel.parent_port] if channel.device_class == 'Trigger': triggers[channel_name] = trace add_trace(channel_name, trace, self.name, channel.parent_port) return triggers