def _connect_to_vna(self): if self.channel is not None: return self.channel # Reuse previously opened object (and socket) try: ip_port = str(self.ui.vna_ip_field.text()).split(":") ip = ip_port[0] port = int(ip_port[1]) self.channel = VnaChannel(ip, port, 1) # Do connection except IndexError: QtGui.QMessageBox.information(self.ui.centralwidget, "IP no especificado", "Es necesario especificar un IP y puerto en el formato IP:puerto")
def _connect(self): if self.executor is not None: return self.channel # Reuse previously opened object (and socket) try: chan_number = int(self.ui.cal_presets_ui.channel_combo.currentText()) self.channels = range(1,chan_number+1) ip_port = str(self.ui.vna_ip_field.text()).split(":") ip = ip_port[0] port = int(ip_port[1]) self.channel = VnaChannel(ip, port, 1) # Do connection except IndexError: QtGui.QMessageBox.information(self.ui.centralwidget, "IP no especificado", "Es necesario especificar un IP y puerto en el formato IP:puerto")
def move(self, direction): ip_port = str(self.ui.vna_ip_field.text()).split(":") ip = ip_port[0] port = int(ip_port[1]) if self.channel is None: self.channel = VnaChannel(ip, port, 1) self.channel.add_marker(1) start_x = self.channel.get_start_x() stop_x = self.channel.get_stop_x() bandwidth = stop_x - start_x gran = bandwidth/100 # By default 1/100th bandwidth granularity self.curr_x = self.channel.get_x() if direction == Direction.LEFT: self.curr_x = self.curr_x - gran # Save curr_x in container for future use elif direction == Direction.RIGHT: self.curr_x = self.curr_x + gran # Save curr_x in container for future use self.channel.set_x(self.curr_x) y = self.channel.get_y() self.ui.y_re_label.setText(str(y[0])) self.ui.y_im_label.setText(str(y[1])) self.ui.x_label.setText(str(self.curr_x))
def VnaMeasure(ui, ip, port): # Disable button after click ui.measure_vna.setEnabled(False) ui.left_button.setEnabled(False) ui.right_button.setEnabled(False) channel = VnaChannel(ip, port, 1) # One channel # channel.reset() channel.set_four_channels() sdata = [] # Clean sdata for each measure for idx, spar in enumerate([SParameters.S11, SParameters.S12, SParameters.S21, SParameters.S22]): print "Now measuring: " + str(spar) channel.set_sweep_type(SweepType.LINEAR) channel.channel = idx + 1 points = str(ui.points_field.text()) fmat = DataFormat.LOG # By default we use MLOG fmat_index = ui.format_combobox.currentIndex() formats = [DataFormat.LOG, DataFormat.LIN, DataFormat.LIN_PHASE, DataFormat.PHASE, DataFormat.GDELAY, DataFormat.SMITH_LIN_PHASE, DataFormat.SMITH_LOG_PHASE, DataFormat.SMITH_RE_IM, DataFormat.SMITH_R_JX, DataFormat.SMITH_G_JB] fmat = formats[fmat_index] if ui.center_span_radio.isChecked(): groupbox = ui.bottom_layout.itemAt(3).widget() center_freq = float(groupbox.findChild(QtGui.QLineEdit, "center_field").text()) span_freq = float(groupbox.findChild(QtGui.QLineEdit, "span_field").text()) channel.set_center_span(center_freq, span_freq) channel.set_traces(1) channel.set_points(points) channel.set_sparam(1, spar) channel.set_format(fmat) # set the selected format channel.activate_channel() channel.activate_trace(1) channel.set_continuous(True) elif ui.start_stop_radio.isChecked(): groupbox = ui.bottom_layout.itemAt(3).widget() freq_start = float(groupbox.findChild(QtGui.QLineEdit, "freqstart_field").text()) freq_stop = float(groupbox.findChild(QtGui.QLineEdit, "freqstop_field").text()) channel.set_start_stop(freq_start, freq_stop) channel.set_traces(1) channel.set_points(points) channel.set_sparam(1, spar) channel.set_format(fmat) # set the selected format channel.activate_channel() channel.activate_trace(1) channel.set_continuous(True) if ui.autoscale_checkbox.isChecked(): channel.auto_scale() # Autoscale f = str(ui.vna_file_field.text()) retrieve_data(ip, port, f, fmat, channel.executor) for ch, sparam in zip([1,2,3,4], [SParameters.S11, SParameters.S12, SParameters.S21, SParameters.S22]): channel.channel = ch channel.set_sparam(1, sparam) channel.channel = 1 channel.executor.close() # Reenable buttons once measure has finished ui.measure_vna.setEnabled(True) ui.left_button.setEnabled(True) ui.right_button.setEnabled(True)
def VnaMeasureSingle(ui, ip, port): ui.measure_vna.setEnabled(False) ui.left_button.setEnabled(False) ui.right_button.setEnabled(False) channel = VnaChannel(ip, port, 1) # One channel # channel.reset() channel.set_sweep_type(SweepType.LINEAR) if ui.s11_radio.isChecked(): spar = SParameters.S11 elif ui.s12_radio.isChecked(): spar = SParameters.S12 elif ui.s21_radio.isChecked(): spar = SParameters.S21 elif ui.s22_radio.isChecked(): spar = SParameters.S22 points = str(ui.points_field.text()) fmat = DataFormat.LOG # By default we use MLOG fmat_index = ui.format_combobox.currentIndex() formats = [DataFormat.LOG, DataFormat.LIN, DataFormat.LIN_PHASE, DataFormat.PHASE, DataFormat.GDELAY, DataFormat.SMITH_LIN_PHASE, DataFormat.SMITH_LOG_PHASE, DataFormat.SMITH_RE_IM, DataFormat.SMITH_R_JX, DataFormat.SMITH_G_JB] fmat = formats[fmat_index] channel.set_one_channel() if ui.center_span_radio.isChecked(): groupbox = ui.bottom_layout.itemAt(3).widget() center_freq = float(groupbox.findChild(QtGui.QLineEdit, "center_field").text()) span_freq = float(groupbox.findChild(QtGui.QLineEdit, "span_field").text()) channel.set_center_span(center_freq, span_freq) channel.set_traces(1) channel.set_points(points) channel.set_sparam(1, spar) channel.set_format(fmat) # set the selected format channel.activate_channel() channel.activate_trace(1) channel.set_continuous(True) elif ui.start_stop_radio.isChecked(): groupbox = ui.bottom_layout.itemAt(3).widget() freq_start = float(groupbox.findChild(QtGui.QLineEdit, "freqstart_field").text()) freq_stop = float(groupbox.findChild(QtGui.QLineEdit, "freqstop_field").text()) channel.set_start_stop(freq_start, freq_stop) channel.set_traces(1) channel.set_points(points) channel.set_sparam(1, spar) channel.set_format(fmat) # set the selected format channel.activate_channel() channel.activate_trace(1) channel.set_continuous(True) if ui.autoscale_checkbox.isChecked(): channel.auto_scale() # Autoscale f = str(ui.vna_file_field.text()) channel.executor.close() # Reenable buttons once measure has finished ui.measure_vna.setEnabled(True) ui.left_button.setEnabled(True) ui.right_button.setEnabled(True) thread.start_new_thread(retrieve_data_single, (ip, port, f))
def do_measure(): channel = VnaChannel("","", 1) channel.reset() channel.set_sweep_type(SweepType.LINEAR) channel.set_center_span(1E9, 5E6) channel.set_points(21) channel.set_traces(2) channel.set_sparam(1, SParameters.S11) channel.activate_trace(1) channel.turn_on() channel.trigger()
class CalHandler(object): def __init__(self, ui): self.ui = ui self.ui.cal_ui.open_button.clicked.connect(self.calibrate_open) self.ui.cal_ui.short_button.clicked.connect(self.calibrate_short) self.ui.cal_ui.load_button.clicked.connect(self.calibrate_load) self.ui.cal_ui.savecal_button.clicked.connect(self.save_cal) self.cal_type_selected = False self.cal_kit_selected = False self.channel = None self.cals_done = [] def _connect_to_vna(self): if self.channel is not None: return self.channel # Reuse previously opened object (and socket) try: ip_port = str(self.ui.vna_ip_field.text()).split(":") ip = ip_port[0] port = int(ip_port[1]) self.channel = VnaChannel(ip, port, 1) # Do connection except IndexError: QtGui.QMessageBox.information(self.ui.centralwidget, "IP no especificado", "Es necesario especificar un IP y puerto en el formato IP:puerto") def _get_cal_data(self): if self.ui.cal_ui.cal_type_combo.currentIndex() == 0: cal_type = CalType.OPEN elif self.ui.cal_ui.cal_type_combo.currentIndex() == 1: cal_type = CalType.SHORT elif self.ui.cal_ui.cal_type_combo.currentIndex() == 2: cal_type = CalType.THRU elif self.ui.cal_ui.cal_type_combo.currentIndex() == 3: cal_type = CalType.FULL_2PORT elif self.ui.cal_ui.cal_type_combo.currentIndex() == 4: cal_type = CalType.FULL_1PORT if self.ui.cal_ui.cal_kit_combo.currentIndex() == 0: cal_kit = 1 # For 85033E return {"cal_type": cal_type, "cal_kit": cal_kit} def _disable_buttons(self): self.ui.cal_ui.open_button.setEnabled(False) self.ui.cal_ui.short_button.setEnabled(False) self.ui.cal_ui.load_button.setEnabled(False) def _selected_port(self): return self.ui.cal_ui.port_combo.currentIndex() + 1 def save_cal(self): self.channel.save_cal() def calibrate_open(self): ret = QtGui.QMessageBox.information(self.ui.centralwidget, "Conectar", "Conectar Open", buttons=QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel) if ret == QtGui.QMessageBox.Cancel: return def measure(): self._connect_to_vna() self._disable_buttons() buttons = [self.ui.cal_ui.open_button, self.ui.cal_ui.short_button, self.ui.cal_ui.load_button] self.cals_done.append("open") thread.start_new_thread(enable_when_ready, (buttons, self.channel, self.cals_done)) cal_data = self._get_cal_data() if not self.cal_kit_selected: self.channel.set_cal_kit(cal_data["cal_kit"]) self.cal_kit_selected = True if not self.cal_type_selected: self.channel.set_cal_type(cal_data["cal_type"], self._selected_port()) self.cal_type_selected = True self.channel.cal_measure_open(self._selected_port()) thread.start_new_thread(measure, ()) print "Calibrate open" def calibrate_short(self): ret = QtGui.QMessageBox.information(self.ui.centralwidget, "Conectar", "Conectar Short", buttons=QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel) if ret == QtGui.QMessageBox.Cancel: return def measure(): self._connect_to_vna() self._disable_buttons() buttons = [self.ui.cal_ui.open_button, self.ui.cal_ui.short_button, self.ui.cal_ui.load_button] self.cals_done.append("short") thread.start_new_thread(enable_when_ready, (buttons, self.channel, self.cals_done)) cal_data = self._get_cal_data() if not self.cal_kit_selected: self.channel.set_cal_kit(cal_data["cal_kit"]) self.cal_kit_selected = True if not self.cal_type_selected: self.channel.set_cal_type(cal_data["cal_type"], self._selected_port()) self.cal_type_selected = True self.channel.cal_measure_short(self._selected_port()) thread.start_new_thread(measure, ()) print "Calibrate short" def calibrate_load(self): ret = QtGui.QMessageBox.information(self.ui.centralwidget, "Conectar", "Conectar Load", buttons=QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel) if ret == QtGui.QMessageBox.Cancel: return def measure(): self._connect_to_vna() self._disable_buttons() buttons = [self.ui.cal_ui.open_button, self.ui.cal_ui.short_button, self.ui.cal_ui.load_button] self.cals_done.append("load") thread.start_new_thread(enable_when_ready, (buttons, self.channel, self.cals_done)) cal_data = self._get_cal_data() if not self.cal_kit_selected: self.channel.set_cal_kit(cal_data["cal_kit"]) self.cal_kit_selected = True if not self.cal_type_selected: self.channel.set_cal_type(cal_data["cal_type"], self._selected_port()) self.cal_type_selected = True self.channel.cal_measure_load(self._selected_port()) thread.start_new_thread(measure, ()) print "Calibrate load"
class SlotContainer(QtGui.QMainWindow): def __init__(self, ui): QtGui.QMainWindow.__init__(self) self.ui = ui self.handler = MeasureHandler() self.curr_x = 0 self.channel = None def checked_all(self, event): sender = self.sender() if sender.isChecked(): self.ui.s11_radio.setEnabled(False) self.ui.s12_radio.setEnabled(False) self.ui.s21_radio.setEnabled(False) self.ui.s22_radio.setEnabled(False) elif not sender.isChecked(): self.ui.s11_radio.setEnabled(True) self.ui.s12_radio.setEnabled(True) self.ui.s21_radio.setEnabled(True) self.ui.s22_radio.setEnabled(True) def browse(self, event): directory = QFileDialog.getExistingDirectory(self, "Donde guardar?", "~", options=QFileDialog.ShowDirsOnly) if self.sender().objectName() == "browse_button": data_file = os.path.join(str(directory), str(self.ui.fileField.text())) self.ui.fileField.setText(data_file) elif self.sender().objectName() == "vna_browse_button": data_file = os.path.join(str(directory), str(self.ui.vna_file_field.text())) self.ui.vna_file_field.setText(data_file) def selected_start_stop(self, event): if self.ui.start_stop_radio.isChecked(): print "Selected start stop" self.ui.bottom_layout.itemAt(3).widget().setParent(None) self.ui.bottom_layout.addWidget(LayoutUtil.get_start_stop_groupbox()) def selected_center_span(self, event): if self.ui.center_span_radio.isChecked(): print "Selected center span" self.ui.bottom_layout.itemAt(3).widget().setParent(None) self.ui.bottom_layout.addWidget(LayoutUtil.get_center_span_groupbox()) def get_port_ip(self): try: ip_port = str(self.ui.ipField.text()).split(":") ip = ip_port[0] port = int(ip_port[1]) self.handler.ip = ip self.handler.port = port return (ip, port) except IndexError: QtGui.QMessageBox.information(self.ui.centralwidget, "IP no especificado", "Es necesario especificar un IP y puerto en el formato IP:puerto") def on_measure(self, event): # WARNING: MAGIC AHEAD # Handler expects ip and port as members of the self.handler object. # get_port_ip() makes sure to put them there self.get_port_ip() params = self self.handler.handle(event, self.ui, params) def on_measure_select(self, event): # Two SMUs can't be in sweep mode or step mode at the same time! # List sweep or constant is fair enough in more than one SMU print "ComboBox: {cbox}, Text = {ctext}".format(cbox=self.sender().objectName(), ctext = self.sender().currentText()) # print self.modes_activated # Pass the sender to the handling function LayoutUtil.layout_update(self.sender(), self.ui) def on_vna_measure(self): if self.channel is not None: self.channel.executor.close() self.channel = None # Makes sure move recreates its executor VnaMeasureThreaded(self.ui) def restore_ui(self): restore_ui(self.ui) def save_ui(self): save_ui(self.ui) def launch_calibration(self): self.ui.cal_ui = Ui_cal_dialog() # Make the calibration dialog available app-wise dialog = QDialog() dialog.ui = self.ui.cal_ui dialog.ui.setupUi(dialog) dialog.setAttribute(QtCore.Qt.WA_DeleteOnClose) handler = CalHandler(self.ui) dialog.exec_() def launch_ri(self): self.ui.ri_ui = Ui_RI_dialog() dialog = QDialog() dialog.ui = self.ui.ri_ui dialog.ui.setupUi(dialog) dialog.setAttribute(QtCore.Qt.WA_DeleteOnClose) handler = RiHandler(self.ui) dialog.exec_() def launch_conalt(self): self.ui.conalt_ui = Ui_conalt_dialog() dialog = QDialog() dialog.ui = self.ui.conalt_ui dialog.ui.setupUi(dialog) dialog.setAttribute(QtCore.Qt.WA_DeleteOnClose) handler = ConAltHandler(self.ui) dialog.exec_() def launch_preset_calibration(self): self.ui.cal_presets_ui = Ui_cal_presets() dialog = QDialog() dialog.ui = self.ui.cal_presets_ui dialog.ui.setupUi(dialog) dialog.setAttribute(QtCore.Qt.WA_DeleteOnClose) handler = PresetHandler(self.ui) dialog.exec_() # TODO Move this elsewhere def move(self, direction): ip_port = str(self.ui.vna_ip_field.text()).split(":") ip = ip_port[0] port = int(ip_port[1]) if self.channel is None: self.channel = VnaChannel(ip, port, 1) self.channel.add_marker(1) start_x = self.channel.get_start_x() stop_x = self.channel.get_stop_x() bandwidth = stop_x - start_x gran = bandwidth/100 # By default 1/100th bandwidth granularity self.curr_x = self.channel.get_x() if direction == Direction.LEFT: self.curr_x = self.curr_x - gran # Save curr_x in container for future use elif direction == Direction.RIGHT: self.curr_x = self.curr_x + gran # Save curr_x in container for future use self.channel.set_x(self.curr_x) y = self.channel.get_y() self.ui.y_re_label.setText(str(y[0])) self.ui.y_im_label.setText(str(y[1])) self.ui.x_label.setText(str(self.curr_x)) def move_left(self): self.move(Direction.LEFT) def move_right(self): self.move(Direction.RIGHT) def open_file(self): MenuHandlers.handle_open(self.ui) def save_file(self): MenuHandlers.handle_save(self.ui) def save_as_file(self): MenuHandlers.handle_save_as(self.ui) def close(self): MenuHandlers.handle_close(self.ui)
class PresetHandler(object): def __init__(self, ui): self.ui = ui self.ui.cal_presets_ui.full_2port_button.clicked.connect(self.full_2port_cal) self.ui.cal_presets_ui.trl_2port_button.clicked.connect(self.trl_2port_cal) self.ui.cal_presets_ui.cal_kit_combo.currentIndexChanged.connect(self.toggle_buttons) self.executor = None def toggle_buttons(self): if self.ui.cal_presets_ui.cal_kit_combo.currentIndex() == 0: self.ui.cal_presets_ui.trl_2port_button.setEnabled(True) if self.ui.cal_presets_ui.cal_kit_combo.currentIndex() == 1: self.ui.cal_presets_ui.trl_2port_button.setEnabled(False) def _set_cal_kit(self): if self.ui.cal_presets_ui.cal_kit_combo.currentIndex() == 0: self.channel.set_cal_kit(1) elif self.ui.cal_presets_ui.cal_kit_combo.currentIndex() == 1: self.channel.set_cs5() self.channel.set_cal_kit(30) def _connect(self): if self.executor is not None: return self.channel # Reuse previously opened object (and socket) try: chan_number = int(self.ui.cal_presets_ui.channel_combo.currentText()) self.channels = range(1,chan_number+1) ip_port = str(self.ui.vna_ip_field.text()).split(":") ip = ip_port[0] port = int(ip_port[1]) self.channel = VnaChannel(ip, port, 1) # Do connection except IndexError: QtGui.QMessageBox.information(self.ui.centralwidget, "IP no especificado", "Es necesario especificar un IP y puerto en el formato IP:puerto") def full_2port_cal(self): self._connect() def assign_channels(vna): for ch in self.channels: vna.channel = ch vna.set_sparam(1, ch) self.channel.channel = 1 if len(self.channels) == 4: self.channel.set_four_channels() else: self.channel.set_one_channel() for ch in self.channels: self.channel.channel = ch self.channel.set_sparam(1, ch) for ch in self.channels: self.channel.channel = ch self._set_cal_kit() # Find and set cal kit for ch in self.channels: self.channel.channel = ch self.channel.set_cal_type(CalType.FULL_2PORT) QtGui.QMessageBox.information(self.ui.centralwidget,"Open", "Conectar open") for ch in self.channels: self.channel.channel = ch self.channel.is_ready() self.channel.cal_measure_open(1) self.channel.is_ready() self.channel.cal_measure_open(2) self.channel.is_ready() assign_channels(self.channel) QtGui.QMessageBox.information(self.ui.centralwidget,"Short", "Conectar short") for ch in self.channels: self.channel.channel = ch self.channel.is_ready() self.channel.cal_measure_short(1) self.channel.is_ready() self.channel.cal_measure_short(2) self.channel.is_ready() assign_channels(self.channel) QtGui.QMessageBox.information(self.ui.centralwidget,"Load", "Conectar load") for ch in self.channels: self.channel.channel = ch self.channel.is_ready() self.channel.cal_measure_load(1) self.channel.is_ready() self.channel.cal_measure_load(2) self.channel.is_ready() assign_channels(self.channel) QtGui.QMessageBox.information(self.ui.centralwidget,"Thru", "Conectar thru") for ch in self.channels: self.channel.channel = ch self.channel.is_ready() self.channel.cal_measure_thru(1, 2) self.channel.is_ready() self.channel.cal_measure_thru(2, 1) self.channel.is_ready() assign_channels(self.channel) isolation = QtGui.QMessageBox.question(self.ui.centralwidget,"Isolation", "Calibrar isolation? (opcional)", QtGui.QMessageBox.Yes| QtGui.QMessageBox.No) if isolation == QtGui.QMessageBox.Yes: QtGui.QMessageBox.information(self.ui.centralwidget,"Isolation", "Conectar load en 1 y 2") for ch in self.channels: self.channel.channel = ch self.channel.is_ready() self.channel.cal_measure_isol(1, 2) self.channel.is_ready() assign_channels(self.channel) self.channel.is_ready() should_save = QtGui.QMessageBox.question(self.ui.centralwidget, "Guardar?", "Guardar calibracion?", QtGui.QMessageBox.Yes| QtGui.QMessageBox.No) if should_save == QtGui.QMessageBox.Yes: for ch in self.channels: self.channel.channel = ch self.channel.save_cal() def trl_2port_cal(self): self._connect() for ch in self.channels: self.channel.channel = ch self.channel.set_cal_kit(1) # Calkit 85033E self.channel.set_cal_type(CalType.TRL_2PORT) QtGui.QMessageBox.information(self.ui.centralwidget,"Thru", "Conectar THRU") for ch in self.channels: self.channel.channel = ch self.channel.trl_thru_line(1, 2) self.channel.is_ready() self.channel.trl_thru_line(2, 1) self.channel.is_ready() QtGui.QMessageBox.information(self.ui.centralwidget,"Reflect", "Conectar REFLECT") for ch in self.channels: self.channel.channel = ch self.channel.trl_reflect(1) self.channel.is_ready() self.channel.trl_reflect(2) self.channel.is_ready() QtGui.QMessageBox.information(self.ui.centralwidget,"Line/Match", "Conectar Line Match") for ch in self.channels: self.channel.channel = ch self.channel.trl_line_match(1,2) self.channel.is_ready() self.channel.trl_line_match(2,1) self.channel.is_ready() should_save = QtGui.QMessageBox.question(self.ui.centralwidget, "Guardar?", "Guardar calibracion?", QtGui.QMessageBox.Yes| QtGui.QMessageBox.No) if should_save == QtGui.QMessageBox.Yes: for ch in self.channels: self.channel.channel = ch self.channel.save_cal()
def con_alt_measure(smu_params, vna_params, delay, conn_keithley, conn_vna): points = smu_params["steps"] sweep_time = delay*points # Prepare K4200 to measure params.append(smu_params) params.append(vna_params) ch = smu_params["index"] + 1 if smu_params["mode"] == "voltage": source_mode = SourceMode.VOLTAGE source_type = SourceType.VOLTAGE if smu_params["mode"] == "current": source_mode = SourceMode.CURRENT source_type = SourceType.CURRENT start = smu_params["start"] stop = smu_params["stop"] step = smu_params["step"] compliance = smu_params["compliance"] sweep_type = SweepType.LINEAR # Always linear. smu = SMUSweep(ch, source_mode, source_type, start, stop, step, compliance, sweep_type, 'V%s' % ch, "I%s"%ch) device = K4200(conn_keithley[0], conn_keithley[1]) device.attach(smu) device.configure() device.executor.execute_command("SS DT {time}".format(time=delay)) # device.executor.execute_command("SS HT {time}".format(time=2.2)) # Prepare VNA to measure vna = VnaChannel(conn_vna[0], conn_vna[1], 1) vna.set_four_channels() vna.set_bus_trigger() def measure_vna(vna): vlock.acquire() vna.trigger() vlock.release() def measure_keithley(keithley): klock.acquire() keithley.measure() klock.release() for i in range(1,5): # Measure using four channels, once per S parameter vna.channel = i vna.set_continuous(False) vna.set_immediate() vna.activate_channel() vna.set_traces(1) vna.activate_trace(1) vna.set_points(points) vna.set_format(vna_params["format"]) vna.set_sparam(1, i) # Assign S11 to ch1, S12 to ch2, S21 to ch3 and S22 to ch4 vna.set_sweep_time(sweep_time) if vna_params["type"] == "center_span": vna.set_center_span(vna_params["freq_center"], vna_params["freq_span"]) elif vna_params["type"] == "start_stop": vna.set_center_span(vna_params["freq_start"], vna_params["freq_stop"]) # Run in different threads to ensure start at the same time start_new_thread(measure_vna, (vna,)) start_new_thread(measure_keithley, (device,)) start_new_thread(check_vna, (vna,vna_params)) start_new_thread(check_keithley, (device,smu_params))