class View(QWidget): def __init__(self, parent=None): super(View, self).__init__(parent) self.__watchdog = Watchdog.Watchdog() self.__watchdog.fileChanged.connect(self.refreshAll) self.figure = plt.figure() self.canvas = FigureCanvas(self.figure) self.canvas.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) toolbar = NavigationToolbar(self.canvas, self) self.navigationLayout = QHBoxLayout() layout = QHBoxLayout(self) self.navigations = [] self.addNavigation(True) self.filters = [ Filters.Lowpass(), Filters.Deconvolve(), Filters.Rotate() ] filterLayout = QVBoxLayout() for f in self.filters: filterLayout.addWidget(f) f.filterChanged.connect(self.plot) filterLayout.addStretch() addIcon = QIcon.fromTheme('list-add') addNaviButton = QPushButton(addIcon, 'Add navigation', self) addNaviButton.clicked.connect(self.addNavigation) self.maxFreq = QDoubleSpinBox(self) self.maxFreq.setValue(10.0) self.maxFreq.setVisible(False) self.maxFreq.valueChanged.connect(self.plot) spectrumIcon = QIcon.fromTheme('network-wireless') self.spectrum = QPushButton(spectrumIcon, 'Spectrum', self) self.spectrum.setCheckable(True) self.spectrum.clicked.connect(self.plot) self.spectrum.toggled.connect(self.maxFreq.setVisible) self.diff = QPushButton('Diff', self) self.diff.setCheckable(True) self.diff.clicked.connect(self.plot) self.diff.clicked.connect(self.spectrum.setHidden) self.spectrum.toggled.connect(self.diff.setHidden) autoRefresh = QPushButton(QIcon.fromTheme('view-refresh'), 'Auto', self) autoRefresh.setCheckable(True) autoRefresh.clicked.connect(self.__watchdog.toggle) saveAll = QPushButton(QIcon.fromTheme('document-save'), '', self) saveAll.clicked.connect(self.savePlots) self.normalize = QPushButton('Normalize', self) self.normalize.setCheckable(True) self.normalize.clicked.connect(self.plot) toolLayout = QHBoxLayout() toolLayout.addWidget(addNaviButton) toolLayout.addWidget(self.diff) toolLayout.addWidget(self.spectrum) toolLayout.addWidget(self.maxFreq) toolLayout.addWidget(autoRefresh) toolLayout.addWidget(saveAll) toolLayout.addWidget(self.normalize) toolLayout.addWidget(toolbar) plotLayout = QVBoxLayout() plotLayout.addLayout(toolLayout) plotLayout.addWidget(self.canvas) layout.addLayout(self.navigationLayout) layout.addLayout(plotLayout) layout.addLayout(filterLayout) def addNavigation(self, noclose=False): navigation = Navigation.Navigation(noclose) navigation.activeItemChanged.connect(self.plot) navigation.folderChanged.connect(self.navigationFolderChanged) navigation.close.connect(self.closeNavigation) navigation.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Minimum) self.navigationLayout.addWidget(navigation) self.navigations.append(navigation) def navigationFolderChanged(self, oldFolder, newFolder): self.__watchdog.removeFolder(oldFolder) self.__watchdog.addFolder(newFolder) def closeNavigation(self, widget): self.navigations.remove(widget) self.navigationLayout.removeWidget(widget) widget.deleteLater() self.plot() def refreshAll(self): for navigation in self.navigations: navigation.refreshFolder() def plot(self): wfc = [ wf for nav in self.navigations for wf in nav.getActiveWaveforms() ] for filt in self.filters: if filt.isChecked(): for wf in wfc: filt.apply(wf) if self.normalize.isChecked(): #normalize traces for nWf, wf in enumerate(wfc): wfc[nWf].normalize() if self.diff.isChecked() and len(wfc) > 0: wf0 = wfc.pop() for nWf, wf in enumerate(wfc): wfc[nWf].subtract(wf0) names = set([name for wf in wfc for name in wf.waveforms.keys()]) numPlots = len(names) self.figure.clear() if numPlots > 0: names = list(names) names.sort() numRows = math.ceil(math.sqrt(numPlots)) numCols = math.ceil(numPlots / numRows) subplots = dict() for i in range(len(names)): subplots[names[i]] = self.figure.add_subplot( numRows, numCols, i + 1) wf_ref = wfc[0] for nWf, wf in enumerate(wfc): for name, waveform in wf.waveforms.items(): p = subplots[name] if self.spectrum.isChecked(): n = len(waveform) dt = wf.time[1] - wf.time[ 0] # assume equally spaced samples f = scipy.fftpack.fftfreq(n, dt) W = dt * scipy.fftpack.fft(waveform) maxFreqIndices = numpy.argwhere( f > self.maxFreq.value()) L = maxFreqIndices[ 0, 0] if numpy.size(maxFreqIndices) > 0 else n / 2 p.loglog(f[1:L], numpy.absolute(W[1:L]), label=str(nWf)) p.set_xlabel('f [Hz]') elif self.diff.isChecked(): p.plot(wf.time, waveform, label='{}-0'.format(nWf + 1)) p.set_xlabel('t (s)') else: p.plot(wf.time, waveform, label=str(nWf)) p.set_xlabel('t (s)') p.set_ylabel(name) #print L2 difference if nWf > 0 and not self.diff.isChecked(): time_union = numpy.union1d(wf.time, wf_ref.time) wf_interp = scipy.interpolate.interp1d( wf.time, waveform) ref_interp = scipy.interpolate.interp1d( wf_ref.time, wf_ref.waveforms[name]) wf_union = wf_interp(time_union) ref_union = ref_interp(time_union) diff = numpy.sqrt( scipy.integrate.trapz((wf_union - ref_union)**2, x=time_union)) p.text(0.05, 1 - 0.1 * nWf, f"L2 diff={diff:.2e}", transform=p.transAxes) self.figure.tight_layout() for i in range(len(names)): subplots[names[i]].legend(prop={'size': 8}, frameon=False) self.canvas.draw() def savePlots(self): filetypes = self.canvas.get_supported_filetypes_grouped() defaultFiletype = self.canvas.get_default_filetype() filters = [] selectedFilter = '' for name, extensions in sorted(filetypes.items()): filtr = '{0} ({1})'.format( name, ' '.join(['*.{0}'.format(ext) for ext in extensions])) if defaultFiletype in extensions: selectedFilter = filtr filters.append(filtr) fileName, filtr = QFileDialog.getSaveFileNameAndFilter( self, 'Choose a save location.', '', ';;'.join(filters), selectedFilter) fileName = os.path.splitext(str(fileName))[0] extension = re.search(r'\*(\.[a-zA-Z]+)', str(filtr)).group(1) maxRow = min([nav.numberOfRows() for nav in self.navigations]) for row in range(maxRow): for nav in self.navigations: nav.selectWaveformAt(row) self.plot() self.canvas.print_figure('{0}{1:03}{2}'.format( fileName, row + 1, extension))
class GuiProgram(Ui_sweepergui): cols = 0 sweep_id = 'mereni' full_data = [] negative_current = False log_sweep = True stop = True decade_combo_values = ['5', '10', '25', '50'] save_directory = False save_filename = False def __init__(self, dialog): Ui_sweepergui.__init__(self) self.setupUi(dialog) # Connect "add" button with a custom function (addInputTextToListbox) self.exportButton.clicked.connect(self.export_data) self.startBtn.clicked.connect(self.startFunc) self.logRadioButton.clicked.connect(self.switch_linear) self.linRadioButton.clicked.connect(self.switch_linear) self.dynamicDelayRadio.clicked.connect(self.switch_dynamic_delay) self.constantDelayRadio.clicked.connect(self.switch_dynamic_delay) # Populate comboBox self.decadeComboBox.clear() self.decadeComboBox.addItems(self.decade_combo_values) self.decadeComboBox.setCurrentIndex(1) self.exportButton.setEnabled(False) # Try to load last parameters from Pickle self.load_parameters() self.save_directory = os.path.dirname(os.path.abspath(__file__)) # Připojení k instrumentu #self.inst = Instrument('GPIB0::17::INSTR', visa_location='C:\WINDOWS\SysWOW64\\visa32.dll') self.inst = Instrument('GPIB0::17::INSTR', virtual=True) def make_pretty(self): self.littleProgBar.setValue(84) self.littleProgBar.setMaximum(100) self.bigProgBar.setMaximum(5) self.bigProgBar.setValue(3) self.startBtn.setText('Stop') self.ax.clear() # Clear contents of current axis # Plot cosmetics self.ax.set_xlabel('Current $I$ (nA)') self.ax.set_ylabel('Voltage $U$ (V)') self.ax.set_title( 'Sweep ID: 2018-04-21_11:22:37 $n$-ZnO/$p$-GaN sample #692') data = [] dd = np.loadtxt('demo_data/01.txt') for i in range(int(len(dd.T) / 2)): data.append((dd[:, 2 * i] * 1e6, dd[:, 2 * i + 1])) color_1 = '#0066FF' color_3 = '#6600CC' color_2 = '#FF0000' self.ax.plot(data[2][0], data[2][1], color=color_2) self.ax.plot(data[3][0], data[3][1], '--', color=color_2) self.ax.plot(data[4][0], data[4][1], color=color_3) self.ax.plot(data[5][0], data[5][1], '--', color=color_3) self.ax.plot(data[0][0], data[0][1], color=color_1) self.ax.plot(data[1][0], data[1][1], '--', color=color_1) #plt.tight_layout() # --- PLOTTING ----------------------------------------------------------- # ------------------------------------------------------------------------ # ------------------------------------------------------------------------ # ------------------------------------------------------------------------ def plot_data(self, data): ''' Plots the provided data onto the figure in the GUI. ''' original_xlim = self.ax.get_xlim() original_ylim = self.ax.get_ylim() self.ax.clear() # Clear contents of current axis # Plot cosmetics self.ax.set_xlabel('I [A]') self.ax.set_ylabel('U [V]') self.ax.set_title('Sweep ID: ' + self.sweep_id) for i in range(len(data)): x, y = data[i] if i == len(data) - 1: color = '#0066FF' elif i == len(data) - 2: color = '#6600CC' else: color = '#FF0000' if self.chkLoop.checkState(): half = int(len(x) / 2) end = len(x) self.ax.plot(x[0:half], y[0:half], color=color) self.ax.plot(x[half:end], y[half:end], '--', color=color) else: self.ax.plot(x, y, color=color) if self.log_sweep: self.ax.set_xscale('log') else: self.ax.set_xscale('linear') if i != 0 and self.chkLockRange.checkState(): self.ax.set_xlim(original_xlim) self.ax.set_ylim(original_ylim) self.canvas.get_default_filename = self.get_default_filename self.canvas.draw() # Propagate changes to GUI def clear_plot(self): self.ax.clear() # Clear contents of current axis self.canvas.draw() # Propagate changes to GUI def put_figure_into_gui(self, fig, ax): ''' Creates a figure and places it inside the GUI container. ''' # Figure self.fig = fig self.ax = ax # Canvas self.canvas = FigureCanvas(self.fig) self.mplvl.addWidget(self.canvas) self.canvas.draw() # Toolbar self.toolbar = NavigationToolbar(self.canvas, self.mplwindow, coordinates=True) self.mplvl.addWidget(self.toolbar) def remove_figure_from_gui(self, ): ''' Deletes the figure from the GUI. ''' # Canvas self.mplvl.removeWidget(self.canvas) self.canvas.close() self.canvas.deleteLater() # this prevents memory leaks # Toolbar self.mplvl.removeWidget(self.toolbar) self.toolbar.close() self.toolbar.deleteLater() # this prevent memory leaks def get_default_filename(self): """ Return a string, which includes extension, suitable for use as a default filename. """ default_basename = self.save_filename or "sweep_{}".format( self.sweep_id) or 'image' default_filetype = self.canvas.get_default_filetype() default_filename = default_basename + '.' + default_filetype save_dir = os.path.expanduser( matplotlib.rcParams.get('savefig.directory', '')) # ensure non-existing filename in save dir i = 1 while os.path.isfile(os.path.join(save_dir, default_filename)): # attach numerical count to basename default_filename = '{0}_({1}).{2}'.format(default_basename, i, default_filetype) i += 1 return default_filename # --- GUI collecting and starting MEASUREMENTS --------------------------- # ------------------------------------------------------------------------ # ------------------------------------------------------------------------ # ------------------------------------------------------------------------ def validateInput(self, sw_min, sw_max, decade, delay, log_sweep, step): # Unit testing :P try: a = float(sw_min) a = float(sw_max) if not log_sweep: a = float(step) except: return False, "Některé parametry se nedají převést na čísla." # Code if log_sweep: if (float(sw_min) > 0 and float(sw_max) > 0 and float(sw_min) != float(sw_max)): return True, "OK" else: return False, "Kraje intervalu jsou stejné nebo je alespoň jeden záp**ný." else: # lin sweep if (float(sw_min) != float(sw_max) and abs(float(sw_max) - float(sw_min)) > float(step)): # step fits into (start, stop) interval and start != stop test_array = np.arange(float(sw_max), float(sw_min), float(step)) if self.chkLoop.checkState() and len(test_array) * 2 > 1000: return False, "Počet bodů ve sweepu je {} > 1000. \nBuffer by přetekl, zvolte jemnější krok, menší rozsah nebo vypněte obousměrnost měření.".format( 2 * len(test_array)) elif len(test_array) > 1000: return False, "Počet bodů ve sweepu je {} > 1000. \nBuffer by přetekl, zvolte jemnější krok nebo menší rozsah.".format( len(test_array)) else: return True, "OK" else: return False, "Kraje intervalu se rovnají, nebo je krok větší než rozsah." def stopFunc(self): print('ABORT! Attempted to STOP sweep!') self.inst.operate(False) self.stop = True def startFunc(self): ''' Posbírá z GUI parametry a odpovídajícím způsobem přeloží.''' # vypnout ruční brzdu self.stop = False # aktuální čas pro ID self.sweep_id = '{0:%Y-%m-%d_%H-%M-%S}'.format(datetime.datetime.now()) self.save_filename = False sense_local = self.senseLocalRadioButton.isChecked() sense_remote = self.senseRemoteRadioButton.isChecked() self.sense_local = sense_local sw_min = str(self.startEdit.text()) sw_max = str(self.endEdit.text()) step = str(self.stepEdit.text()) # Pokud je zapojený zesilovač if not self.sense_local: sw_min = str(float(sw_min) * 1e3) sw_max = str(float(sw_max) * 1e3) step = str(float(step) * 1e3) # TODO: this should be made more logical... self.custom_capacity_used = self.dynamicDelayRadio.isChecked() if self.custom_capacity_used: self.custom_capacity = int(self.capacitySpinBox.value()) delay = str(self.delaySpinBox.value()) decade = str(self.decadeComboBox.currentIndex()) n = self.pocetMereniBox.value() self.bigProgBar.setValue(0) self.bigProgBar.setMaximum(n) self.littleProgBar.setValue(0) log_sweep = self.logRadioButton.isChecked() lin_sweep = self.linRadioButton.isChecked() self.log_sweep = log_sweep col_source = self.sourceCheckBox.checkState() col_delay = self.delayCheckBox.checkState() col_measure = self.measureCheckBox.checkState() col_time = self.timeCheckBox.checkState() self.cols = 0 if col_source: self.cols += 1 if col_delay: self.cols += 2 if col_measure: self.cols += 4 if col_time: self.cols += 8 input_valid, err = self.validateInput(sw_min, sw_max, decade, delay, log_sweep, step) if self.chkAutorange.checkState(): sweep_range = '0' else: sweep_range = str( misc.get_range_number(float(sw_min), float(sw_max))) print("!! Using sweep range: {}".format(sweep_range)) if sweep_range == '0': print( 'POZOR: Manualni nastaveni range selhalo, prilis vysoke proudy?' ) if input_valid: self.save_parameters() self.measure(sw_min, sw_max, decade, delay, log_sweep, step, n, sweep_range) else: self.show_notification(err) # --- ACTUAL MEASUREMENTS ------------------------------------------------ # ------------------------------------------------------------------------ # ------------------------------------------------------------------------ # ------------------------------------------------------------------------ def measure(self, sw_min, sw_max, decade, delay, log_sweep, step, n, sweep_range): ''' Spustí měření s již validovanými parametry. ''' # Disable UI self.enable_ui(False) # Smaže aktuální graf self.clear_plot() # Declare Export not done on this sweep self.exportButton.setText('Export') # Local or Remote sense? if self.sense_local: print("Zapinam Sense - LOCAL.") self.inst.write("O0X") else: print("Zapinam Sense - REMOTE.") self.inst.write("O1X") # Úvodní stabilizace stabilize_time = self.stableSpinBox.value() print("Uvodni stabilizace v DC modu - {} s.".format(stabilize_time)) self.stabilize(sw_min, stabilize_time) # Nastavení sweepu self.inst.set_source_and_function('I', 'Sweep') # Nastavení formátu dat self.inst.write("G" + str(self.cols) + ",2,2X") if self.log_sweep: self.inst.write("Q2," + sw_min + "," + sw_max + "," + decade + "," + sweep_range + "," + delay + "X") if self.chkLoop.checkState(): self.inst.write("Q8," + sw_max + "," + sw_min + "," + decade + "," + sweep_range + "," + delay + "X") else: self.inst.write("Q1," + sw_min + "," + sw_max + "," + step + "," + sweep_range + "," + delay + "X") if self.chkLoop.checkState(): self.inst.write("Q7," + sw_max + "," + sw_min + "," + step + "," + sweep_range + "," + delay + "X") # Manual modification of delays for each value if self.custom_capacity_used: if self.chkLoop.checkState(): delay_arr = delays.delays_round(float(sw_min), float(sw_max), int(decade), self.custom_capacity) else: delay_arr = delays.delays_up(float(sw_min), float(sw_max), int(decade), self.custom_capacity) self.inst.set_custom_delays(delay_arr) data = [] self.full_data = [] self.np_data = [] n_hotovych_mereni = 0 for mereni in range(n): if self.stop: break output = self.run_sweep() if output: if not self.sense_local: output = misc.shift_data(output, cols=self.cols, shift=-3) sweep_results = misc.nice_format(output, cols=self.cols) unpacked_results = misc.unpack(sweep_results, cols=self.cols) data.append(unpacked_results) self.full_data.append(sweep_results) self.np_data = misc.pack_data(self.np_data, unpacked_results) print('Ukladam docasna data...') self.dump_data() n_hotovych_mereni += 1 self.bigProgBar.setValue(n_hotovych_mereni) self.plot_data(data) if n_hotovych_mereni != n: sleep_time = self.sleepSpinBox.value() print("Pauza mezi sweepy - {} s.".format(sleep_time)) self.artSleep(sleep_time) else: print("Output byl prazdny. Prerusene mereni?") self.inst.operate(False) self.enable_ui(True) def run_sweep(self): ''' Provede jeden sweep, který už musí být definovaný ve stroji. Na konci 3 vteřiny spí, aby se mělo napětí čas ustálit před dalším měřením. Vrací string se všemi hodnotami sweepu. ''' print('\nSpoustim sweep...') self.inst.write("U8X") out = self.inst.read() print('U8X -> ' + out) out = out.replace('\r', '').replace('\n', '') print("Out: {}".format(out)) sweep_defined_size = int(out[-4:]) print('Pocet bodu ve sweepu: ' + str(sweep_defined_size)) self.littleProgBar.setValue(0) self.inst.trigger() # Immediate trigger sweep_done = False while not sweep_done: if self.stop: break self.artSleep(0.2) self.inst.write("U11X") status = self.inst.read() if (status == 'SMS' + str(sweep_defined_size).zfill(4) + '\r\n'): sweep_done = True else: status_edit = status.replace('\r', '').replace('\n', '') try: progress = int(status_edit[-4:]) self.littleProgBar.setValue( int(progress / sweep_defined_size * 100)) except: print('Invalid progress!') print('Jeden sweep hotov.') self.littleProgBar.setValue(100) if self.stop: return "" else: return self.inst.read() def stabilize(self, bias, stabilize_time): # Počáteční stabilizace self.inst.set_source_and_function('I', 'DC') self.inst.write("B" + bias + ",0,20X") self.inst.operate(True) self.inst.trigger() self.artSleep(stabilize_time) # --- EXPORT and DATA operations ----------------------------------------- # ------------------------------------------------------------------------ # ------------------------------------------------------------------------ # ------------------------------------------------------------------------ def dump_data(self): save_file_name = 'C:\Repa\k237\data_temp.txt' try: np.savetxt(save_file_name, self.np_data, fmt='%.4e', header=self.get_measurement_parameters() + "\nPOZOR, prubezne ukladana data mohou byt nekompletni", delimiter='\t') except: print("Nouzovy dump se nepovedl.") def export_data(self): """ Exportuje data pomocí ukládacího dialogu Qt. V případě chybného zadání souboru nic neudělá a postěžuje si do konzole. """ proposed_name = self.save_filename or 'sweep_' + self.sweep_id # Qt Dialog na výběr souboru k uložení save_file_name, _ = QtWidgets.QFileDialog.getSaveFileName( None, 'Exportovat výsledky měření', #'C:\Repa\k237\data\sweep_' + proposed_name + '.txt', os.path.join(self.save_directory, proposed_name + '.txt'), 'Text Files (*.txt);;All Files (*)') # Vlastní uložení souboru try: np.savetxt(save_file_name, self.np_data, fmt='%.4e', header=self.get_measurement_parameters(), delimiter='\t') # Update GUI self.exportButton.setText('Export ✔') self.save_directory = os.path.dirname(save_file_name) self.save_filename = os.path.splitext( os.path.basename(save_file_name))[0] except: print("Export neuspesny. Data pravdepodobne nejsou ulozena!") # Update GUI self.exportButton.setText('Export ✗') def get_measurement_parameters(self): out = '' out += "Sweep ID: {}\n".format(self.sweep_id) if self.log_sweep: out += "Log sweep:\n" out += "Rozsah (min, max) [A]: {}, {}\n".format( self.startEdit.text(), self.endEdit.text()) out += "Bodu na dekadu [-]: {}\n".format( self.decade_combo_values[self.decadeComboBox.currentIndex()]) else: out += "Linear sweep\n" out += "Rozsah (min, max, points) [A]: {}, {}, {}\n".format( self.startEdit.text(), self.endEdit.text(), self.stepEdit.text()) out += "Delay [ms]: {}\n".format(self.delaySpinBox.value()) out += "Pocet charakteristik [-]: {}\n".format( self.pocetMereniBox.value()) if self.sense_local: out += "Sense: local\n" else: out += "Sense: remote\n" out += "Sloupce (Source, Measure, Delay, Time): {} {} {} {}\n".format( int(self.sourceCheckBox.checkState() / 2), int(self.measureCheckBox.checkState() / 2), int(self.delayCheckBox.checkState() / 2), int(self.timeCheckBox.checkState() / 2)) out += "Uvodni DC stabilizace [s]: {}\n".format( self.stableSpinBox.value()) out += "Stabilizace [s]: {}\n".format(self.sleepSpinBox.value()) out += "\nI[A] (x)\tU[V .e-3] (y1, y2, ...) " return out # --- GUI parameters and ENABLE/DISABLE ---------------------------------- # ------------------------------------------------------------------------ # ------------------------------------------------------------------------ # ------------------------------------------------------------------------ def save_parameters(self): parameters_dict = { 'sw_min': str(self.startEdit.text()), 'sw_max': str(self.endEdit.text()), 'step': str(self.stepEdit.text()), 'delay': int(self.delaySpinBox.value()), 'decade': int(self.decadeComboBox.currentIndex()), 'n': int(self.pocetMereniBox.value()), 'log_sweep': self.logRadioButton.isChecked(), 'lin_sweep': self.linRadioButton.isChecked(), 'sense_local': self.senseLocalRadioButton.isChecked(), 'sense_remote': self.senseRemoteRadioButton.isChecked(), 'col_source': self.sourceCheckBox.checkState(), 'col_delay': self.delayCheckBox.checkState(), 'col_measure': self.measureCheckBox.checkState(), 'col_time': self.timeCheckBox.checkState(), 'stabilize_time': self.stableSpinBox.value(), 'sleep_time': self.sleepSpinBox.value(), 'chk_loop': self.chkLoop.checkState(), 'chk_lock_range': self.chkLockRange.checkState(), 'chk_autorange': self.chkAutorange.checkState(), } # For pickle, the file needs to be opened in binary mode, hence the "wb" with open("last_parameters.pickle", "wb") as params_file: pickle.dump(parameters_dict, params_file) def load_parameters(self): try: # For pickle, the file needs to be opened in binary mode, hence the "wb" with open("last_parameters.pickle", "rb") as params_file: parameters_dict = pickle.load(params_file) self.startEdit.setText(parameters_dict['sw_min']) self.endEdit.setText(parameters_dict['sw_max']) self.stepEdit.setText(parameters_dict['step']) self.delaySpinBox.setValue(parameters_dict['delay']) self.decadeComboBox.setCurrentIndex(parameters_dict['decade']) self.pocetMereniBox.setValue(parameters_dict['n']) self.logRadioButton.setChecked(parameters_dict['log_sweep']) self.linRadioButton.setChecked(parameters_dict['lin_sweep']) self.senseLocalRadioButton.setChecked( parameters_dict['sense_local']) self.senseRemoteRadioButton.setChecked( parameters_dict['sense_remote']) self.sourceCheckBox.setChecked(parameters_dict['col_source']) self.delayCheckBox.setChecked(parameters_dict['col_delay']) self.measureCheckBox.setChecked(parameters_dict['col_measure']) self.timeCheckBox.setChecked(parameters_dict['col_time']) self.stableSpinBox.setValue(parameters_dict['stabilize_time']) self.sleepSpinBox.setValue(parameters_dict['sleep_time']) self.chkLoop.setChecked(parameters_dict['chk_loop']) self.chkLockRange.setChecked(parameters_dict['chk_lock_range']) self.chkAutorange.setChecked(parameters_dict['chk_autorange']) self.switch_linear() self.switch_dynamic_delay() print("Nacteni poslednich parametru uspesne! :)") except: print("Nacteni poslednich parametru selhalo. :(") def switch_linear(self): log_sweep = self.logRadioButton.isChecked() lin_sweep = self.linRadioButton.isChecked() if log_sweep: self.stepEdit.setEnabled(False) self.decadeComboBox.setEnabled(True) else: self.decadeComboBox.setEnabled(False) self.stepEdit.setEnabled(True) def switch_dynamic_delay(self): const_delay = self.constantDelayRadio.isChecked() dynamic_delay = self.dynamicDelayRadio.isChecked() if const_delay: self.capacitySpinBox.setEnabled(False) self.delaySpinBox.setEnabled(True) else: self.delaySpinBox.setEnabled(False) self.capacitySpinBox.setEnabled(True) def enable_ui(self, status): ui_elements = [ self.startEdit, self.endEdit, self.stepEdit, self.delaySpinBox, self.decadeComboBox, self.pocetMereniBox, self.logRadioButton, self.linRadioButton, self.senseLocalRadioButton, self.senseRemoteRadioButton, self.sourceCheckBox, self.delayCheckBox, self.measureCheckBox, self.timeCheckBox, self.stableSpinBox, self.sleepSpinBox, self.chkLoop, self.chkAutorange, self.exportButton, ] for element in ui_elements: element.setEnabled(status) if status: self.switch_linear() self.switch_dynamic_delay() if status: self.startBtn.clicked.disconnect() self.startBtn.clicked.connect(self.startFunc) self.startBtn.setText("Start") self.exportButton.setFocus() else: self.startBtn.clicked.disconnect() self.startBtn.clicked.connect(self.stopFunc) self.startBtn.setText("Abort") self.startBtn.setFocus() self.exportButton.setText('Export') def artSleep(self, sleepTime): """ Čeká čas sleepTime v sekundách, zatím ale každých 50 milisekund řeší akce, o které se někdo pokoušel v GUI. """ stop_time = QtCore.QTime() stop_time.restart() while stop_time.elapsed() < sleepTime * 1000: QtWidgets.QApplication.processEvents(QtCore.QEventLoop.AllEvents, 50) def show_notification(self, err): msg = QtWidgets.QMessageBox() msg.setIcon(QtWidgets.QMessageBox.Warning) msg.setText("Chybné parametry sweepu.") msg.setInformativeText(err) msg.setWindowTitle("Sweeper - varování") msg.exec_()