diff --git a/CrameRaoFunctions.py b/CrameRaoFunctions.py index e87ff7e..27a83cd 100644 --- a/CrameRaoFunctions.py +++ b/CrameRaoFunctions.py @@ -27,13 +27,12 @@ def white_noise(rho, sr, n, mu=0): A - amplitude NSD - Noise Spectral Density T - Period of acquisition -T2 - Relaxation rate +T2 - Inverse relaxation rate N - Number of samples ret - sigma, sigma2, C return: STD, C """ - def cr(A, NSD, T, N, T2=0): if T2 == 0: C = 1 diff --git a/app.pyw b/app.pyw index 4baa10d..b08fabb 100644 --- a/app.pyw +++ b/app.pyw @@ -38,10 +38,6 @@ from gui import Ui_MainWindow # generated by designer, DO NOT EDIT import libtiepie from playsound import playsound # pip install playsound -try: - import nidaqmx -except: - pass # extend Ui_MainWindow class class MyUi(Ui_MainWindow): @@ -57,17 +53,15 @@ class MyUi(Ui_MainWindow): colorX = (100, 200, 250) colorY = (100, 250, 200) colorZ = (250, 100, 200) - penX = pg.mkPen(colorX, width=2, style=QtCore.Qt.SolidLine) - penY = pg.mkPen(colorY, width=2, style=QtCore.Qt.SolidLine) - penZ = pg.mkPen(colorZ, width=2, style=QtCore.Qt.SolidLine) - decimationArr = np.array([5, 4]) # 5,2 + penX = pg.mkPen(colorX, width=2, style=QtCore.Qt.PenStyle.SolidLine) + penY = pg.mkPen(colorY, width=2, style=QtCore.Qt.PenStyle.SolidLine) + penZ = pg.mkPen(colorZ, width=2, style=QtCore.Qt.PenStyle.SolidLine) + decimationArr = np.array([5]) # 5,2 countRemainingToSave = 0 soundPlayed = False - niTask = False # object for NI USB-6002 - """Initialize the app""" @@ -76,12 +70,8 @@ class MyUi(Ui_MainWindow): self.dialogs = list() + self.gen = arbGenerator() self.scp = oscilloscope() - print(self.scp.scp_list_sn) - gen_sn = self.scp.scp_list_sn[0] - print(f"Selected generator SN: {gen_sn}") - self.gen = arbGenerator(gen_sn) - self.threadpool = QThreadPool() self.theWorkerBlocks = Worker(self.getBlocks) # Any other args, kwargs are passed to the run function @@ -94,18 +84,25 @@ class MyUi(Ui_MainWindow): self.timerStart.setInterval(1000) self.timerStart.timeout.connect(self.boot) + self.theWorkerBlocks_enabled = True + + """ override function of the parent class to connect actions and buttons set user interface """ def setupUi(self, MainWindow): super(MyUi, self).setupUi(MainWindow) # call function of the parent class + self.loadSettings() self.okButton_GeneratorStart.clicked.connect(self.genStartStop) self.tabWidget.currentChanged.connect(self.tabChanged) self.doubleSpinBox_RecordsToSave.valueChanged.connect(self.saveRecordsChanged) + self.actionSave_settings.triggered.connect(self.actionSave_settings_handler) + self.actionLoad_settings.triggered.connect(self.actionLoad_settings_handler) + elements = [self.doubleSpinBox_PumpLevel, self.doubleSpinBox_ProbeLevel, self.doubleSpinBox_ZeroLevel, @@ -113,7 +110,9 @@ class MyUi(Ui_MainWindow): self.doubleSpinBox_TotalTime_ms, self.doubleSpinBox_DutyCycle, self.doubleSpinBox_PumpTime_ms, - self.doubleSpinBox_Points + self.doubleSpinBox_Points, + self.doubleSpinBox_ExpAmplitude, + self.doubleSpinBox_ExpRelaxation ] for el in elements: el.valueChanged.connect(self.arbSet) @@ -128,24 +127,13 @@ class MyUi(Ui_MainWindow): ] for el in elements: el.valueChanged.connect(self.fit) - - elements = [self.doubleSpinBox_setBiasRange_min, - self.doubleSpinBox_setBiasRange_max - ] - for el in elements: - el.valueChanged.connect(self.setBiasRange) - self.comboBox_FilterType.currentIndexChanged.connect(self.fitUISet) self.radioButton_FITSource_CH1.clicked.connect(self.fitUISet) self.radioButton_FITSource_CH2.clicked.connect(self.fitUISet) - self.radioButton_FITSource_CH3.clicked.connect(self.fitUISet) - self.radioButton_FITSource_CH4.clicked.connect(self.fitUISet) self.pushButton_Set_FIT_init.clicked.connect(self.copyFITtoInit) self.pushButton_SelectFolder.clicked.connect(self.selectFolder) self.lineEdit_FolderName.setText(os.getcwd()+"\\data\\") - self.doubleSpinBox_setBiasValue.valueChanged.connect(self.setBiasVoltage) - # change CH parameters on the data tab elements = [ self.comboBox_CH1Range, @@ -165,12 +153,19 @@ class MyUi(Ui_MainWindow): self.arbPlot = PG_layout.addPlot() PG_layout.nextRow() self.ch1Plot = PG_layout.addPlot() + self.ch1Plot_lr = pg.LinearRegionItem([15, 16], hoverBrush=None) + self.ch1Plot_lr.setZValue(10) + + self.ch1Plot_lrM = pg.LinearRegionItem([self.doubleSpinBox_TotalTime_ms.value(), self.doubleSpinBox_TotalTime_ms.value()-1], hoverBrush=None) + self.ch1Plot_lrM.setZValue(10) + #self.ch1Plot_lr.sigRegionChangeFinished.connect(self.something) + + PG_layout.nextRow() self.ch2Plot = PG_layout.addPlot() self.plotWindow.setCentralItem(PG_layout) # set layout to the widget self.checkBox_SaveData.setStyleSheet("QCheckBox::indicator { width: 70; height: 70;}") - self.checkBox_ActivateEOMstab.setStyleSheet("QCheckBox::indicator { width: 70; height: 70;}") containing_layout = self.FITPlotPlaceholder.parent().layout() containing_layout.replaceWidget(self.FITPlotPlaceholder, self.FITplotWindow_Widget) @@ -218,13 +213,16 @@ class MyUi(Ui_MainWindow): self.tabWidget.setCurrentIndex(0) + + # Execute self.scpWorkerStart(self.theWorkerBlocks) self.timerPlotSCP.start() # self.genStartStop() self.showDiskSpace() - self.setBiasRange() + + @@ -245,6 +243,8 @@ class MyUi(Ui_MainWindow): def scpWorkerStop(self, worker): try: + self.theWorkerBlocks_enabled = False + self.threadpool.stop(worker) except Exception as e: print("scpWorkerStop exception: ", e) @@ -288,65 +288,11 @@ class MyUi(Ui_MainWindow): return False - def setBiasRange(self): - self.doubleSpinBox_setBiasValue.setRange( - self.doubleSpinBox_setBiasRange_min.value(), - self.doubleSpinBox_setBiasRange_max.value()) - - def stabilizeProbeLevel(self): - - # print("Stab now!") - # get current probe level - if self.radioButton_PrStabSourceCH1.isChecked(): - pos = 0 - else: - if self.radioButton_PrStabSourceCH2.isChecked(): - pos = 1 - else: - if self.radioButton_PrStabSourceCH3.isChecked(): - pos = 2 - else: - pos = 3 - - try: - signalData = self.SCPData[pos] - except: - return - probeValue = np.mean(signalData[-3000:-100]) - self.label_ActualProbeValue.setText(f"{probeValue:0.6f} V") - - if self.checkBox_ActivateEOMstab.isChecked(): - error = self.doubleSpinBox_setProbeValue.value() -probeValue - tolerancePercent = self.doubleSpinBox_ProbeValueTolerance.value() - if np.abs(error) < probeValue * tolerancePercent/100 and self.checkBox_useTolerance.isChecked(): - # no correction - return - correction = error * self.doubleSpinBox_ProbeLevelCorrectionFactor.value()/1000 - old = self.doubleSpinBox_setBiasValue.value() - biasValue = old + correction - if biasValue > 10: - biasValue = 10 - if biasValue < -10: - biasValue = -10 - self.doubleSpinBox_setBiasValue.setValue(biasValue) - - def setBiasVoltage(self): - if self.niTask is False: - try: - self.niTask = nidaqmx.Task() - self.niTask.ao_channels.add_ao_voltage_chan("Dev1/ao0") - except Exception() as e: - print("Error connecting to the NI USB device:") - print(e) - return - - self.niTask.write(self.doubleSpinBox_setBiasValue.value(), auto_start=True) - def getBlocks(self, progress_callback): print("Worker here") scp = self.scp.scp - while True: + while self.theWorkerBlocks_enabled: if self.radioButton_modeBlock.isChecked(): # block mode if scp.is_running and scp.measure_mode == libtiepie.MM_STREAM: @@ -364,7 +310,8 @@ class MyUi(Ui_MainWindow): # Get data: self.SCPData = scp.get_data() # print("Got SCP data!") - + # print(f"scp {scp.sample_rate=}") + # print(f" self.SCPData len = {len(self.SCPData[0])}") else: # stream mode # print("Stream mode") @@ -381,7 +328,8 @@ class MyUi(Ui_MainWindow): # Get data: self.SCPData = scp.get_data() - # print("Got SCP data!") + #print("Got SCP data!") + #print(f"scp {scp.sample_rate=}") # print(scp.measure_mode) if self.checkBox_SaveData.isChecked(): self.doubleSpinBox_RecordsToSave.setDisabled(True) @@ -433,9 +381,6 @@ class MyUi(Ui_MainWindow): def plotSCP(self): - # stabilize probe level - self.stabilizeProbeLevel() - if self.tabWidget.currentIndex() == 2: # Monitor tab return self.plotSCPMonitor() if self.tabWidget.currentIndex() != 0: # Data tab @@ -447,22 +392,70 @@ class MyUi(Ui_MainWindow): if samples < 10: return - sr = self.scp.scp.sample_frequency + sr = self.scp.scp.sample_rate t = np.linspace(0, 1000 * samples / sr, samples, endpoint=False) + # print(f"plotSCP: {samples=}, {sr=}") + + fltr = signal.firwin(51, [2e3,50e3], pass_zero=False, fs=sr) + self.ch1Plot.clear() self.ch2Plot.clear() self.ch1Plot.setLabel('bottom', "time (ms)") self.ch1Plot.setLabel('left', "CH1 (V)") self.ch1Plot.plot(t, self.SCPData[0]) + redPen = pg.mkPen('r', width=2, style=QtCore.Qt.DashLine) + grid = pg.GridItem(pen=redPen) + grid.setTickSpacing(x=[1e5], y=[float(self.comboBox_CH1Range.currentText())]) + self.ch1Plot.addItem(grid) + vr = self.ch1Plot.getViewBox().viewRange() + + + rst= self.doubleSpinBox_PumpTime_ms.value()+.5 + self.ch1Plot_lr.setRegion((rst,rst+1)) + self.ch1Plot.addItem(self.ch1Plot_lr) + + self.ch1Plot_lrM.setRegion((self.doubleSpinBox_TotalTime_ms.value()-1, self.doubleSpinBox_TotalTime_ms.value())) + self.ch1Plot.addItem(self.ch1Plot_lrM) + + # get signal amplitude + start, stop = self.ch1Plot_lr.getRegion() + tSel = (t > start) & (t < stop) + #print(tSel) + elValsCH1 = np.array(self.SCPData[0])[tSel] + + filtered = signal.convolve(elValsCH1, fltr, mode='valid') + + min= np.min(filtered) + max = np.max(filtered) + amplitude = .92*(max-min)/2 + + text = pg.TextItem(f"{(1e3*amplitude):.2f}") + self.ch1Plot.addItem(text) + + # print(vr[1][1]) + text.setPos(rst + 1, vr[1][1]) + + # get mean probe at the end + start, stop = self.ch1Plot_lrM.getRegion() + tSel = (t > start) & (t < stop) + # print(tSel) + mvValsCH1 = np.array(self.SCPData[0])[tSel] + meanProbe = np.mean(mvValsCH1) + + textMean=pg.TextItem(f"{(1e3*(meanProbe+self.doubleSpinBox_SignalOffset.value())):.2f}") + textMean.setPos(self.doubleSpinBox_TotalTime_ms.value()*.9, vr[1][1]) + self.ch1Plot.addItem(textMean) + + + + #self.ch1Plot.setLabel('top', f"{amplitude=}") self.ch2Plot.setLabel('bottom', "time (ms)") self.ch2Plot.setLabel('left', "CH2 (V)") self.ch2Plot.plot(t, self.SCPData[1]) - - def plotSCPMonitor(self): if isinstance(self.SCPData, bool): @@ -470,7 +463,7 @@ class MyUi(Ui_MainWindow): samples = len(self.SCPData[0]) if samples < 10: return - sr = self.scp.scp.sample_frequency + sr = self.scp.scp.sample_rate t = np.linspace(0, 1000 * samples / sr, samples, endpoint=False) # print(self.__dict__.get("monitorPlotCH1")) @@ -495,7 +488,7 @@ class MyUi(Ui_MainWindow): self.radioButton_CH2AC.toggle() if not self.scp.set(mode=self.getSCPmode(), - sample_frequency=self.getSampleRate(), + sample_rate=self.getSampleRate(), record_length=int(self.doubleSpinBox_Samples.value()), CH_ranges=[ float(self.comboBox_M_CH1Range.currentText()), @@ -614,7 +607,7 @@ class MyUi(Ui_MainWindow): if self.scp.scp is None: self.FITSampleRate = 3125000 else: - self.FITSampleRate = self.scp.scp.sample_frequency + self.FITSampleRate = self.scp.scp.sample_rate r = (self.doubleSpinBox_FIT_f0.value() + 500, self.doubleSpinBox_FIT_f0.value() + 1500) self.FFTdataPlotFIT_lr.setRegion(r) @@ -633,12 +626,8 @@ class MyUi(Ui_MainWindow): if self.radioButton_FITSource_CH1.isChecked(): self.dataFIT = self.dataSCPtoFITtab[0] - if self.radioButton_FITSource_CH2.isChecked(): + else: self.dataFIT = self.dataSCPtoFITtab[1] - if self.radioButton_FITSource_CH3.isChecked(): - self.dataFIT = self.dataSCPtoFITtab[2] - if self.radioButton_FITSource_CH4.isChecked(): - self.dataFIT = self.dataSCPtoFITtab[3] totalTime_ms = float(self.doubleSpinBox_FITStop_ms.value()) t = np.linspace(0, totalTime_ms, len(self.dataFIT), endpoint=False) @@ -674,7 +663,7 @@ class MyUi(Ui_MainWindow): # filter the data ciFilter = self.comboBox_FilterType.currentIndex() filRange = 1e3 - filterLength = 1001 # must be odd number!!!!!!!!!!!!!!!!!!!! + filterLength = 601 # must be odd number!!!!!!!!!!!!!!!!!!!! pass_zero = False if ciFilter == 0: # High pass from 1k filRange = 10e3 @@ -693,8 +682,7 @@ class MyUi(Ui_MainWindow): pass_zero = True # drop = int((filterLength - 1) / 2) - tstart = time.perf_counter() - fltr = signal.firwin(filterLength, filRange, window='hamming', pass_zero=pass_zero, fs=self.FITSampleRate / np.prod(self.decimationArr)) + fltr = signal.firwin(filterLength, filRange, pass_zero=pass_zero, fs=self.FITSampleRate / np.prod(self.decimationArr)) filtered = signal.convolve(decimated - np.mean(decimated), fltr, mode='valid') self.filteredDataFIT = signal.detrend(filtered, type='constant') @@ -710,8 +698,6 @@ class MyUi(Ui_MainWindow): 2 * np.pi * self.doubleSpinBox_FIT_Gamma.value(), # from Hz to rad^-1 self.doubleSpinBox_FIT_DC.value()] popt, pcov = curve_fit(self.FITfunc, tf, self.filteredDataFIT, p0=p0) - tperf = time.perf_counter() - tstart - print(f"FIT time {tperf=} s") self.lastFIT = [popt, pcov] print("popt = ", popt) plainText = "f = {:.4f} Hz\n".format(popt[0]) # +str(popt[0]) + "\n" @@ -739,21 +725,30 @@ class MyUi(Ui_MainWindow): detrend='constant', return_onesided=True, scaling='density', axis=- 1) """ + + mean = np.mean(self.unFilteredDataFit) + sh_V = np.sqrt(2 * 1.6e-19 * (mean + self.doubleSpinBox_SignalOffset.value())/ self.doubleSpinBox_TransImp_Gain.value()) * self.doubleSpinBox_TransImp_Gain.value() # shot noise spectral noise density + print(f"shot Noise for FFT {sh_V} (V/sqrt(Hz))") + + vsqrtHztext = "V/√ Hz " f, pxx = signal.periodogram(self.unFilteredDataFit, self.FITSampleRate, window='hann') self.FITlastFFT = f, pxx self.FFTdataPlotFIT.clear() self.FFTdataPlotFIT.setLogMode(y=True) self.FFTdataPlotFIT.plot(f, np.sqrt(pxx)) + self.FFTdataPlotFIT.plot([0, np.max(f)], [sh_V, sh_V], pen=self.penY) self.FFTdataPlotFIT.addItem(self.FFTdataPlotFIT_lr) self.FFTdataPlotFIT.setLabel('bottom', "Frequency", units="Hz") self.FFTdataPlotFIT.setLabel('left', "PSD", units=vsqrtHztext) + f, pxx = signal.periodogram(self.filteredDataFIT, self.FITSampleRate/ np.prod(self.decimationArr), window='hann') self.FFTFilteredDataPlotFIT.clear() self.FFTFilteredDataPlotFIT.setLogMode(y=True) self.FFTFilteredDataPlotFIT.plot(f, np.sqrt(pxx)) + self.FFTFilteredDataPlotFIT.plot([0, np.max(f)], [sh_V, sh_V], pen=self.penY) self.FFTFilteredDataPlotFIT.setLabel('bottom', "Frequency", units="Hz") self.FFTFilteredDataPlotFIT.setLabel('left', "PSD filtered", units=vsqrtHztext) self.FFTFilteredDataPlotFIT.addItem(self.FFTFilteredDataPlotFIT_lr) @@ -793,38 +788,59 @@ class MyUi(Ui_MainWindow): start, stop = self.FFTFilteredDataPlotFIT_lr.getRegion() self.FFTdataPlotFIT_lr.setRegion([start, stop]) print(start, stop) + f, pxx = self.FITlastFFT fSel = (f > start) & (f < stop) pxxSelVals = pxx[fSel] NSD = np.sqrt(np.mean(pxxSelVals)) print("Noise:", NSD, " V/sqrt(Hz)") + mean = np.mean(self.unFilteredDataFit) + sh = np.sqrt(2 * 1.6e-19 * (mean + self.doubleSpinBox_SignalOffset.value()) / self.doubleSpinBox_TransImp_Gain.value()) # shot noise spectral noise density + sh_V = sh * self.doubleSpinBox_TransImp_Gain.value() + + popt, pcov = self.lastFIT A = np.sqrt(popt[1]**2 + popt[2]**2) T2 = 1./popt[3] - - gain = float(self.lineEdit_transImpGain.text()) - mean_I = np.mean(self.unFilteredDataFit) / gain # A - NSD_sh = np.sqrt(2 * 1.602e-19 * mean_I) # shot noise A/sqrt Hz + scaleToSens = np.sqrt(500/self.doubleSpinBox_TotalTime_ms.value()) T = (self.doubleSpinBox_FilterStop_ms.value() - self.doubleSpinBox_FilterStart_ms.value())/1e3 N = T * self.FITSampleRate - CramerRao_sh, C = cr.cr(A/gain, NSD_sh, T, N, T2=T2) CramerRao, C = cr.cr(A, NSD, T, N, T2=T2) print("cr = {:.2e}".format(CramerRao)) text = "Freq. range = [{:.2f}, {:.2f}] Hz\n".format(start, stop) text += "R = {:.2e} V\n".format(A) - text += "NSD = {:.3e} V/sqrt(Hz)\n".format(NSD) - text += f"NSD_sh = {NSD_sh:.3e} V/sqrt(Hz) (shot noise)\n" + text += " NSD = {:.3e} V/sqrt(Hz)\n".format(NSD) + text += f"shSD = {sh_V:.3e} V/sqrt(Hz)\n" text += "C = {:.3e}\n".format(C) text += "cr = {:.1e} Hz\n".format(CramerRao) - text += f"dB(FSP) = {CramerRao * 1e6/3.5:.1f} fT ({CramerRao_sh * 1e6/3.5:.1f})\n" - text += f"dB(FAP) = {CramerRao * 1e6/7.0:.1f} fT ({CramerRao_sh * 1e6/7.0:.1f})\n" + #text += "dB(FSP) = {:.1f} fT\n".format(CramerRao * 1e6/3.5) + #text += "dB(FAP) = {:.1f} fT\n".format(CramerRao * 1e6/7.0) + text += f"dB(FSP) = {(CramerRao * 1e6 / 3.5):.1f} fT sens = {(CramerRao * 1e6 / (scaleToSens* 3.5)):.1f} ft/sqrt(Hz) \n" + text += f"dB(FAP) = {(CramerRao * 1e6 / 7.0):.1f} fT sens = {(CramerRao * 1e6 / (scaleToSens* 7)):.1f} ft/sqrt(Hz) \n" + + + + print(f"Shot noise: {sh} A/sqrt(Hz)") + print(f"Shot noise: {sh * self.doubleSpinBox_TransImp_Gain.value()} V/sqrt(Hz)") + CramerRaoSH, C = cr.cr(A, sh * self.doubleSpinBox_TransImp_Gain.value(), T, N, T2=T2) + text += f"\nIn shotnoise limit with {self.doubleSpinBox_TransImp_Gain.value()} V/A gain:\n" + text += f"dB(FSP) = {(CramerRaoSH * 1e6 / 3.5):.1f} fT sens = {(CramerRaoSH * 1e6 / (scaleToSens* 3.5)):.1f} ft/sqrt(Hz)\n" + text += f"dB(FAP) = {(CramerRaoSH * 1e6 / 7.0):.1f} fT sens = {(CramerRaoSH * 1e6 / (scaleToSens* 7)):.1f} ft/sqrt(Hz)\n" + + self.plainTextEdit_SensitivityFFT.setPlainText(text) + def selectFilename(self, use='open', type="All files (*)"): + if use=='open': + return QtWidgets.QFileDialog.getOpenFileName(None, 'Select settings file',"",type) + else: + return QtWidgets.QFileDialog.getSaveFileName(None, 'Select settings file',"",type) + def selectFolder(self): folderpath = QtWidgets.QFileDialog.getExistingDirectory(None, 'Select Folder') - self.lineEdit_FolderName.setText(folderpath+"/") + self.lineEdit_FolderName.setText(folderpath+"\\") """ import shutil @@ -843,13 +859,12 @@ class MyUi(Ui_MainWindow): # msg.buttonClicked.connect(self.popup_button) def genStartStop(self): # self.okButton_GeneratorStart.clicked.connect(self.genStartStop) - if self.gen.gen.output_on: + if self.gen.gen.output_enable: # output_on self.gen.stop() else: self.arbSet() def arbSet(self): - arbObj = arbcalc(totalTime=float(self.doubleSpinBox_TotalTime_ms.value()) / 1000, pumpTime=float(self.doubleSpinBox_PumpTime_ms.value()) / 1000, dutyCycle=float(self.doubleSpinBox_DutyCycle.value()), @@ -857,23 +872,102 @@ class MyUi(Ui_MainWindow): pumpLevel=float(self.doubleSpinBox_PumpLevel.value()), zeroLevel=float(self.doubleSpinBox_ZeroLevel.value()), pumpFrequency=float(self.doubleSpinBox_Frequency_Hz.value()), - noPoints=int(self.doubleSpinBox_Points.value()) + noPoints=int(self.doubleSpinBox_Points.value()), + expAmplitude=float(self.doubleSpinBox_ExpAmplitude.value()), + expRelaxation=float(self.doubleSpinBox_ExpRelaxation.value()) ) arb = arbObj.arb() t, y = arb - if not len(y) == int(self.doubleSpinBox_Points.value()): - print("Arb length is wrong!") - print(f"{len(y)=} == points={int(self.doubleSpinBox_Points.value())}") - else: - print(f"{len(y)=} == points={int(self.doubleSpinBox_Points.value())}") if not self.gen.arbLoad(y, - amplitude=max(y), + amplitude=np.max(np.abs(y)), frequency=1000 / float(self.doubleSpinBox_TotalTime_ms.value())): self.statusbar.showMessage("The Generator is not accesible.", 2000) self.plotArb(t, y) self.gen.start() + """ + Stop the app, save settings etc. + """ + def onClose(self): + print("Time to close...") + self.timerPlotSCP.stop() + self.gen.stop() + self.scpWorkerStop(self.theWorkerBlocks) + + # stop save + try: + if self.checkBox_SaveData.isChecked(): + self.checkBox_SaveData.setChecked(False) + self.threadpool.stop(self.theWorkerSave) + except Exception as e: + print(e) + + # save settings + self.saveSettings() + + print("|End of onClose!") + + def saveSettings(self, file='settings.zg.npy'): + # print(f"{vars(self)=}") + settingsToSave = [] + for key, v in self.__dict__.items(): + o = self.__getattribute__(key) + """ + QtWidgets.QRadioButton + QtWidgets.QComboBox + QtWidgets.QDoubleSpinBox + QtWidgets.QCheckBox - not important + QtWidgets.QLineEdit + """ + # print(o.__class__) + if o.__class__ == QtWidgets.QComboBox: + # print(f"{o=} -> {o.currentIndex()}") + settingsToSave.append([key, o.currentIndex(), 'QtWidgets.QComboBox']) + + if o.__class__ == QtWidgets.QRadioButton: + # print(f"{o=} -> {o.isChecked()}") + settingsToSave.append([key, o.isChecked(), 'QtWidgets.QRadioButton']) + + if o.__class__ == QtWidgets.QDoubleSpinBox: + # print(f"{o=} -> {o.value()}") + settingsToSave.append([key, o.value(), 'QtWidgets.QDoubleSpinBox']) + if o.__class__ == QtWidgets.QLineEdit: + # print(f"{o=} -> {o.text()}") + settingsToSave.append([key, o.text(), 'QtWidgets.QLineEdit']) + + # print(settingsToSave) + np.save(file, settingsToSave) + print("Settings saved.") + + def loadSettings(self, file='settings.zg.npy'): + + # load settings + settings = np.load(file) + # print(settings) + for setting in settings: + o = self.__getattribute__(setting[0]) + if setting[2] == "QtWidgets.QDoubleSpinBox": + o.setValue(float(setting[1])) + if setting[2] == "QtWidgets.QComboBox": + o.setCurrentIndex(int(setting[1])) + # if setting[2] == "QtWidgets.QRadioButton": + # o.setChecked(setting[1] in ['true', 'True']) + if setting[2] == "QtWidgets.QLineEdit": + o.setText(setting[1]) + print("Settings applied!") + + def actionSave_settings_handler(self): + file, type = self.selectFilename(use='save', type="Settings file (*.zg.npy)") + print("actionSave_settings_handler file=", file) + self.saveSettings(file=file) + + def actionLoad_settings_handler(self): + file, type = self.selectFilename(use='open',type="Settings file (*.zg.npy)") + #print(file) + self.loadSettings(file=file) + + ############################################################################################## # @@ -885,6 +979,7 @@ def main(): app = QtWidgets.QApplication(sys.argv) app.setStyleSheet(qdarkgraystyle.load_stylesheet()) + # not working, icon set in te Qt Designer # app_icon = QtGui.QIcon() # app_icon.addFile('images/ZG-Speach-Bubble-16x16-icon.png', QtCore.QSize(16, 16)) @@ -896,12 +991,12 @@ def main(): MainWindow = QtWidgets.QMainWindow() ui = MyUi() + app.aboutToQuit.connect(ui.onClose) # close the app handler function ui.setupUi(MainWindow) MainWindow.show() sys.exit(app.exec_()) # del MainWindow - if __name__.endswith('__main__'): main() \ No newline at end of file diff --git a/arbcalc.py b/arbcalc.py index 943cb7b..32791b1 100644 --- a/arbcalc.py +++ b/arbcalc.py @@ -12,13 +12,15 @@ class arbcalc(): def __init__(self, totalTime=0.1, - pumpTime=0.3, + pumpTime=0.05, zeroLevel=0, pumpLevel=5, probeLevel=1, - noPoints=10000, - pumpFrequency=300, - dutyCycle=0.5): + noPoints=50000, + pumpFrequency=100, + dutyCycle=0.5, + expAmplitude=0.1, + expRelaxation=1e3): self.totalTime = totalTime self.pumpTime = pumpTime @@ -28,23 +30,56 @@ def __init__(self, self.pumpFrequency = pumpFrequency self.noPoints = noPoints self.dutyCycle = dutyCycle + self.expAmplitude = expAmplitude + self.expRelaxation = expRelaxation*1e3 - def arb(self): + def arb_old(self): # data = np.zeros(self.noPoints)+self.probeLevel self.t = np.linspace(0, self.totalTime, self.noPoints, endpoint=False) onePumpPeriod = 1.0 / self.pumpFrequency nPumpPeriods = int(self.pumpTime / onePumpPeriod) - self.data = (1 + signal.square(2 * np.pi * self.pumpFrequency * self.t, duty=self.dutyCycle))/2 + self.data = (1 + signal.square(2 * np.pi * self.pumpFrequency * self.t, duty=self.dutyCycle)) / 2 self.data = self.data * (self.pumpLevel - self.zeroLevel) + self.zeroLevel nProbe = nPumpPeriods + self.dutyCycle - 1 - nProbe = int(self.noPoints * nProbe * onePumpPeriod/self.totalTime) + nProbe = int(self.noPoints * nProbe * onePumpPeriod / self.totalTime) for n in range(nProbe, self.noPoints): self.data[n] = self.probeLevel return self.t, self.data + def arb(self): + # data = np.zeros(self.noPoints)+self.probeLevel + #print(f"arbcalc {self.totalTime=}") + self.t = np.linspace(0, self.totalTime, self.noPoints, endpoint=False) + sr = self.noPoints/self.totalTime + onePumpPeriod = 1.0 / self.pumpFrequency + nPumpPeriods = int(self.pumpTime / onePumpPeriod) + + if self.expAmplitude == 0: + self.data = (1 + signal.square(2 * np.pi * self.pumpFrequency * self.t, duty=self.dutyCycle)) / 2 + self.data = self.data * (self.pumpLevel - self.zeroLevel) + self.zeroLevel + nProbe = nPumpPeriods + self.dutyCycle - 1 + nProbe = int(self.noPoints * nProbe * onePumpPeriod / self.totalTime) + for n in range(nProbe, self.noPoints): + self.data[n] = self.probeLevel + + else: + upTime = onePumpPeriod * self.dutyCycle + downTime= onePumpPeriod * (1.0-self.dutyCycle) + tUp = np.linspace(0, upTime, int(upTime*sr), endpoint=False) + tDown = np.linspace(0, downTime, int(downTime*sr), endpoint=False) + + upData = self.pumpLevel - self.expAmplitude*(1-np.exp(-self.expRelaxation * tUp)) + downData = self.zeroLevel + self.expAmplitude*(1-np.exp(-self.expRelaxation * tDown)) + cycleData = np.concatenate((upData, downData)) + pumpData = np.tile(cycleData, nPumpPeriods-1) + pumpData = np.concatenate((pumpData, upData)) #add one more Pump level + probeData = np.zeros(self.noPoints-len(pumpData)) + self.probeLevel + + self.data = np.concatenate((pumpData, probeData)) + return self.t, self.data \ No newline at end of file diff --git a/gui.py b/gui.py index ee9a190..56a1a38 100644 --- a/gui.py +++ b/gui.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'gui.ui' # -# Created by: PyQt5 UI code generator 5.15.7 +# Created by: PyQt5 UI code generator 5.15.10 # # WARNING: Any manual changes made to this file will be lost when pyuic5 is # run again. Do not edit this file unless you know what you are doing. @@ -14,7 +14,7 @@ class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") - MainWindow.resize(1193, 869) + MainWindow.resize(1197, 869) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap("images/ZG-Speach-Bubble-256x256-icon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) MainWindow.setWindowIcon(icon) @@ -79,7 +79,7 @@ def setupUi(self, MainWindow): self.doubleSpinBox_Samples.setMinimum(1.0) self.doubleSpinBox_Samples.setMaximum(32000000.0) self.doubleSpinBox_Samples.setSingleStep(1.0) - self.doubleSpinBox_Samples.setProperty("value", 312500.0) + self.doubleSpinBox_Samples.setProperty("value", 156250.0) self.doubleSpinBox_Samples.setObjectName("doubleSpinBox_Samples") self.gridLayout.addWidget(self.doubleSpinBox_Samples, 1, 1, 1, 1) self.label_5 = QtWidgets.QLabel(self.groupBox_3) @@ -168,45 +168,53 @@ def setupUi(self, MainWindow): self.verticalLayout_3.setObjectName("verticalLayout_3") self.gridLayout_2 = QtWidgets.QGridLayout() self.gridLayout_2.setObjectName("gridLayout_2") + self.doubleSpinBox_ZeroLevel = QtWidgets.QDoubleSpinBox(self.groupBox) + self.doubleSpinBox_ZeroLevel.setDecimals(4) + self.doubleSpinBox_ZeroLevel.setMinimum(-10.0) + self.doubleSpinBox_ZeroLevel.setMaximum(10.0) + self.doubleSpinBox_ZeroLevel.setSingleStep(0.001) + self.doubleSpinBox_ZeroLevel.setProperty("value", 0.0) + self.doubleSpinBox_ZeroLevel.setObjectName("doubleSpinBox_ZeroLevel") + self.gridLayout_2.addWidget(self.doubleSpinBox_ZeroLevel, 3, 1, 1, 1) self.doubleSpinBox_Frequency_Hz = QtWidgets.QDoubleSpinBox(self.groupBox) self.doubleSpinBox_Frequency_Hz.setMaximum(1000000.0) self.doubleSpinBox_Frequency_Hz.setSingleStep(5.0) - self.doubleSpinBox_Frequency_Hz.setProperty("value", 7000.0) + self.doubleSpinBox_Frequency_Hz.setProperty("value", 13746.0) self.doubleSpinBox_Frequency_Hz.setObjectName("doubleSpinBox_Frequency_Hz") self.gridLayout_2.addWidget(self.doubleSpinBox_Frequency_Hz, 0, 1, 1, 1) - self.doubleSpinBox_DutyCycle = QtWidgets.QDoubleSpinBox(self.groupBox) - self.doubleSpinBox_DutyCycle.setSuffix("") - self.doubleSpinBox_DutyCycle.setDecimals(3) - self.doubleSpinBox_DutyCycle.setMaximum(1.0) - self.doubleSpinBox_DutyCycle.setSingleStep(0.1) - self.doubleSpinBox_DutyCycle.setProperty("value", 0.3) - self.doubleSpinBox_DutyCycle.setObjectName("doubleSpinBox_DutyCycle") - self.gridLayout_2.addWidget(self.doubleSpinBox_DutyCycle, 3, 3, 1, 1) self.doubleSpinBox_TotalTime_ms = QtWidgets.QDoubleSpinBox(self.groupBox) self.doubleSpinBox_TotalTime_ms.setMaximum(5000.0) self.doubleSpinBox_TotalTime_ms.setSingleStep(1.0) - self.doubleSpinBox_TotalTime_ms.setProperty("value", 100.0) + self.doubleSpinBox_TotalTime_ms.setProperty("value", 50.0) self.doubleSpinBox_TotalTime_ms.setObjectName("doubleSpinBox_TotalTime_ms") self.gridLayout_2.addWidget(self.doubleSpinBox_TotalTime_ms, 1, 3, 1, 1) - self.label_9 = QtWidgets.QLabel(self.groupBox) - self.label_9.setObjectName("label_9") - self.gridLayout_2.addWidget(self.label_9, 3, 2, 1, 1) self.label_4 = QtWidgets.QLabel(self.groupBox) self.label_4.setObjectName("label_4") self.gridLayout_2.addWidget(self.label_4, 0, 0, 1, 1) - self.label_3 = QtWidgets.QLabel(self.groupBox) - self.label_3.setObjectName("label_3") - self.gridLayout_2.addWidget(self.label_3, 2, 2, 1, 1) self.label = QtWidgets.QLabel(self.groupBox) self.label.setObjectName("label") self.gridLayout_2.addWidget(self.label, 0, 2, 1, 1) + self.doubleSpinBox_DutyCycle = QtWidgets.QDoubleSpinBox(self.groupBox) + self.doubleSpinBox_DutyCycle.setSuffix("") + self.doubleSpinBox_DutyCycle.setDecimals(3) + self.doubleSpinBox_DutyCycle.setMaximum(1.0) + self.doubleSpinBox_DutyCycle.setSingleStep(0.1) + self.doubleSpinBox_DutyCycle.setProperty("value", 0.5) + self.doubleSpinBox_DutyCycle.setObjectName("doubleSpinBox_DutyCycle") + self.gridLayout_2.addWidget(self.doubleSpinBox_DutyCycle, 3, 3, 1, 1) self.label_2 = QtWidgets.QLabel(self.groupBox) self.label_2.setObjectName("label_2") self.gridLayout_2.addWidget(self.label_2, 1, 2, 1, 1) + self.label_9 = QtWidgets.QLabel(self.groupBox) + self.label_9.setObjectName("label_9") + self.gridLayout_2.addWidget(self.label_9, 3, 2, 1, 1) + self.label_3 = QtWidgets.QLabel(self.groupBox) + self.label_3.setObjectName("label_3") + self.gridLayout_2.addWidget(self.label_3, 2, 2, 1, 1) self.doubleSpinBox_PumpTime_ms = QtWidgets.QDoubleSpinBox(self.groupBox) self.doubleSpinBox_PumpTime_ms.setMaximum(5000.0) self.doubleSpinBox_PumpTime_ms.setSingleStep(1.0) - self.doubleSpinBox_PumpTime_ms.setProperty("value", 30.0) + self.doubleSpinBox_PumpTime_ms.setProperty("value", 15.0) self.doubleSpinBox_PumpTime_ms.setObjectName("doubleSpinBox_PumpTime_ms") self.gridLayout_2.addWidget(self.doubleSpinBox_PumpTime_ms, 2, 3, 1, 1) self.doubleSpinBox_Points = QtWidgets.QDoubleSpinBox(self.groupBox) @@ -217,14 +225,6 @@ def setupUi(self, MainWindow): self.doubleSpinBox_Points.setProperty("value", 500000.0) self.doubleSpinBox_Points.setObjectName("doubleSpinBox_Points") self.gridLayout_2.addWidget(self.doubleSpinBox_Points, 0, 3, 1, 1) - self.doubleSpinBox_ZeroLevel = QtWidgets.QDoubleSpinBox(self.groupBox) - self.doubleSpinBox_ZeroLevel.setDecimals(4) - self.doubleSpinBox_ZeroLevel.setMinimum(-10.0) - self.doubleSpinBox_ZeroLevel.setMaximum(10.0) - self.doubleSpinBox_ZeroLevel.setSingleStep(0.01) - self.doubleSpinBox_ZeroLevel.setProperty("value", 0.0) - self.doubleSpinBox_ZeroLevel.setObjectName("doubleSpinBox_ZeroLevel") - self.gridLayout_2.addWidget(self.doubleSpinBox_ZeroLevel, 3, 1, 1, 1) self.doubleSpinBox_ProbeLevel = QtWidgets.QDoubleSpinBox(self.groupBox) self.doubleSpinBox_ProbeLevel.setDecimals(4) self.doubleSpinBox_ProbeLevel.setMinimum(-10.0) @@ -233,23 +233,44 @@ def setupUi(self, MainWindow): self.doubleSpinBox_ProbeLevel.setProperty("value", 0.5) self.doubleSpinBox_ProbeLevel.setObjectName("doubleSpinBox_ProbeLevel") self.gridLayout_2.addWidget(self.doubleSpinBox_ProbeLevel, 2, 1, 1, 1) - self.label_7 = QtWidgets.QLabel(self.groupBox) - self.label_7.setObjectName("label_7") - self.gridLayout_2.addWidget(self.label_7, 2, 0, 1, 1) - self.label_6 = QtWidgets.QLabel(self.groupBox) - self.label_6.setObjectName("label_6") - self.gridLayout_2.addWidget(self.label_6, 1, 0, 1, 1) self.doubleSpinBox_PumpLevel = QtWidgets.QDoubleSpinBox(self.groupBox) self.doubleSpinBox_PumpLevel.setDecimals(4) self.doubleSpinBox_PumpLevel.setMinimum(-10.0) self.doubleSpinBox_PumpLevel.setMaximum(10.0) - self.doubleSpinBox_PumpLevel.setSingleStep(0.01) - self.doubleSpinBox_PumpLevel.setProperty("value", 4.0) + self.doubleSpinBox_PumpLevel.setSingleStep(0.001) + self.doubleSpinBox_PumpLevel.setProperty("value", 1.0) self.doubleSpinBox_PumpLevel.setObjectName("doubleSpinBox_PumpLevel") self.gridLayout_2.addWidget(self.doubleSpinBox_PumpLevel, 1, 1, 1, 1) self.label_8 = QtWidgets.QLabel(self.groupBox) self.label_8.setObjectName("label_8") self.gridLayout_2.addWidget(self.label_8, 3, 0, 1, 1) + self.label_7 = QtWidgets.QLabel(self.groupBox) + self.label_7.setObjectName("label_7") + self.gridLayout_2.addWidget(self.label_7, 2, 0, 1, 1) + self.label_6 = QtWidgets.QLabel(self.groupBox) + self.label_6.setObjectName("label_6") + self.gridLayout_2.addWidget(self.label_6, 1, 0, 1, 1) + self.doubleSpinBox_ExpAmplitude = QtWidgets.QDoubleSpinBox(self.groupBox) + self.doubleSpinBox_ExpAmplitude.setDecimals(4) + self.doubleSpinBox_ExpAmplitude.setMinimum(-10.0) + self.doubleSpinBox_ExpAmplitude.setMaximum(10.0) + self.doubleSpinBox_ExpAmplitude.setSingleStep(0.01) + self.doubleSpinBox_ExpAmplitude.setProperty("value", 0.0) + self.doubleSpinBox_ExpAmplitude.setObjectName("doubleSpinBox_ExpAmplitude") + self.gridLayout_2.addWidget(self.doubleSpinBox_ExpAmplitude, 4, 1, 1, 1) + self.label_32 = QtWidgets.QLabel(self.groupBox) + self.label_32.setObjectName("label_32") + self.gridLayout_2.addWidget(self.label_32, 4, 0, 1, 1) + self.label_33 = QtWidgets.QLabel(self.groupBox) + self.label_33.setObjectName("label_33") + self.gridLayout_2.addWidget(self.label_33, 4, 2, 1, 1) + self.doubleSpinBox_ExpRelaxation = QtWidgets.QDoubleSpinBox(self.groupBox) + self.doubleSpinBox_ExpRelaxation.setDecimals(4) + self.doubleSpinBox_ExpRelaxation.setMaximum(500.0) + self.doubleSpinBox_ExpRelaxation.setSingleStep(1.0) + self.doubleSpinBox_ExpRelaxation.setProperty("value", 87.0) + self.doubleSpinBox_ExpRelaxation.setObjectName("doubleSpinBox_ExpRelaxation") + self.gridLayout_2.addWidget(self.doubleSpinBox_ExpRelaxation, 4, 3, 1, 1) self.verticalLayout_3.addLayout(self.gridLayout_2) self.okButton_GeneratorStart = QtWidgets.QPushButton(self.groupBox) self.okButton_GeneratorStart.setObjectName("okButton_GeneratorStart") @@ -368,14 +389,34 @@ def setupUi(self, MainWindow): self.verticalLayout_10.setObjectName("verticalLayout_10") self.gridLayout_9 = QtWidgets.QGridLayout() self.gridLayout_9.setObjectName("gridLayout_9") - self.label_17 = QtWidgets.QLabel(self.groupBox_7) + self.label_18 = QtWidgets.QLabel(self.groupBox_7) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.label_17.sizePolicy().hasHeightForWidth()) - self.label_17.setSizePolicy(sizePolicy) - self.label_17.setObjectName("label_17") - self.gridLayout_9.addWidget(self.label_17, 0, 0, 1, 1) + sizePolicy.setHeightForWidth(self.label_18.sizePolicy().hasHeightForWidth()) + self.label_18.setSizePolicy(sizePolicy) + self.label_18.setObjectName("label_18") + self.gridLayout_9.addWidget(self.label_18, 1, 0, 1, 1) + self.label_19 = QtWidgets.QLabel(self.groupBox_7) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.label_19.sizePolicy().hasHeightForWidth()) + self.label_19.setSizePolicy(sizePolicy) + self.label_19.setObjectName("label_19") + self.gridLayout_9.addWidget(self.label_19, 2, 0, 1, 1) + self.doubleSpinBox_FITStart_ms = QtWidgets.QDoubleSpinBox(self.groupBox_7) + self.doubleSpinBox_FITStart_ms.setMaximum(1000.0) + self.doubleSpinBox_FITStart_ms.setSingleStep(0.1) + self.doubleSpinBox_FITStart_ms.setProperty("value", 30.0) + self.doubleSpinBox_FITStart_ms.setObjectName("doubleSpinBox_FITStart_ms") + self.gridLayout_9.addWidget(self.doubleSpinBox_FITStart_ms, 3, 1, 1, 1) + self.doubleSpinBox_FITStop_ms = QtWidgets.QDoubleSpinBox(self.groupBox_7) + self.doubleSpinBox_FITStop_ms.setMaximum(1000.0) + self.doubleSpinBox_FITStop_ms.setSingleStep(0.1) + self.doubleSpinBox_FITStop_ms.setProperty("value", 100.0) + self.doubleSpinBox_FITStop_ms.setObjectName("doubleSpinBox_FITStop_ms") + self.gridLayout_9.addWidget(self.doubleSpinBox_FITStop_ms, 4, 1, 1, 1) self.comboBox_FilterType = QtWidgets.QComboBox(self.groupBox_7) self.comboBox_FilterType.setObjectName("comboBox_FilterType") self.comboBox_FilterType.addItem("") @@ -384,38 +425,18 @@ def setupUi(self, MainWindow): self.comboBox_FilterType.addItem("") self.comboBox_FilterType.addItem("") self.gridLayout_9.addWidget(self.comboBox_FilterType, 0, 1, 1, 1) - self.doubleSpinBox_FITStop_ms = QtWidgets.QDoubleSpinBox(self.groupBox_7) - self.doubleSpinBox_FITStop_ms.setMaximum(1000.0) - self.doubleSpinBox_FITStop_ms.setSingleStep(0.1) - self.doubleSpinBox_FITStop_ms.setProperty("value", 100.0) - self.doubleSpinBox_FITStop_ms.setObjectName("doubleSpinBox_FITStop_ms") - self.gridLayout_9.addWidget(self.doubleSpinBox_FITStop_ms, 4, 1, 1, 1) - self.doubleSpinBox_FilterStop_ms = QtWidgets.QDoubleSpinBox(self.groupBox_7) - self.doubleSpinBox_FilterStop_ms.setMaximum(1000.0) - self.doubleSpinBox_FilterStop_ms.setSingleStep(0.1) - self.doubleSpinBox_FilterStop_ms.setProperty("value", 100.0) - self.doubleSpinBox_FilterStop_ms.setObjectName("doubleSpinBox_FilterStop_ms") - self.gridLayout_9.addWidget(self.doubleSpinBox_FilterStop_ms, 2, 1, 1, 1) - self.doubleSpinBox_FITStart_ms = QtWidgets.QDoubleSpinBox(self.groupBox_7) - self.doubleSpinBox_FITStart_ms.setMaximum(1000.0) - self.doubleSpinBox_FITStart_ms.setSingleStep(0.1) - self.doubleSpinBox_FITStart_ms.setProperty("value", 30.0) - self.doubleSpinBox_FITStart_ms.setObjectName("doubleSpinBox_FITStart_ms") - self.gridLayout_9.addWidget(self.doubleSpinBox_FITStart_ms, 3, 1, 1, 1) + self.doubleSpinBox_TransImp_Gain = QtWidgets.QDoubleSpinBox(self.groupBox_7) + self.doubleSpinBox_TransImp_Gain.setMaximum(100000000.0) + self.doubleSpinBox_TransImp_Gain.setSingleStep(1.0) + self.doubleSpinBox_TransImp_Gain.setProperty("value", 1000000.0) + self.doubleSpinBox_TransImp_Gain.setObjectName("doubleSpinBox_TransImp_Gain") + self.gridLayout_9.addWidget(self.doubleSpinBox_TransImp_Gain, 5, 1, 1, 1) self.doubleSpinBox_FilterStart_ms = QtWidgets.QDoubleSpinBox(self.groupBox_7) self.doubleSpinBox_FilterStart_ms.setMaximum(1000.0) self.doubleSpinBox_FilterStart_ms.setSingleStep(0.1) self.doubleSpinBox_FilterStart_ms.setProperty("value", 30.0) self.doubleSpinBox_FilterStart_ms.setObjectName("doubleSpinBox_FilterStart_ms") self.gridLayout_9.addWidget(self.doubleSpinBox_FilterStart_ms, 1, 1, 1, 1) - self.label_19 = QtWidgets.QLabel(self.groupBox_7) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.label_19.sizePolicy().hasHeightForWidth()) - self.label_19.setSizePolicy(sizePolicy) - self.label_19.setObjectName("label_19") - self.gridLayout_9.addWidget(self.label_19, 2, 0, 1, 1) self.label_25 = QtWidgets.QLabel(self.groupBox_7) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) @@ -424,14 +445,28 @@ def setupUi(self, MainWindow): self.label_25.setSizePolicy(sizePolicy) self.label_25.setObjectName("label_25") self.gridLayout_9.addWidget(self.label_25, 4, 0, 1, 1) - self.label_18 = QtWidgets.QLabel(self.groupBox_7) + self.label_34 = QtWidgets.QLabel(self.groupBox_7) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.label_18.sizePolicy().hasHeightForWidth()) - self.label_18.setSizePolicy(sizePolicy) - self.label_18.setObjectName("label_18") - self.gridLayout_9.addWidget(self.label_18, 1, 0, 1, 1) + sizePolicy.setHeightForWidth(self.label_34.sizePolicy().hasHeightForWidth()) + self.label_34.setSizePolicy(sizePolicy) + self.label_34.setObjectName("label_34") + self.gridLayout_9.addWidget(self.label_34, 5, 0, 1, 1) + self.doubleSpinBox_FilterStop_ms = QtWidgets.QDoubleSpinBox(self.groupBox_7) + self.doubleSpinBox_FilterStop_ms.setMaximum(1000.0) + self.doubleSpinBox_FilterStop_ms.setSingleStep(0.1) + self.doubleSpinBox_FilterStop_ms.setProperty("value", 100.0) + self.doubleSpinBox_FilterStop_ms.setObjectName("doubleSpinBox_FilterStop_ms") + self.gridLayout_9.addWidget(self.doubleSpinBox_FilterStop_ms, 2, 1, 1, 1) + self.label_17 = QtWidgets.QLabel(self.groupBox_7) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.label_17.sizePolicy().hasHeightForWidth()) + self.label_17.setSizePolicy(sizePolicy) + self.label_17.setObjectName("label_17") + self.gridLayout_9.addWidget(self.label_17, 0, 0, 1, 1) self.label_24 = QtWidgets.QLabel(self.groupBox_7) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) @@ -440,17 +475,22 @@ def setupUi(self, MainWindow): self.label_24.setSizePolicy(sizePolicy) self.label_24.setObjectName("label_24") self.gridLayout_9.addWidget(self.label_24, 3, 0, 1, 1) - self.label_34 = QtWidgets.QLabel(self.groupBox_7) + self.doubleSpinBox_SignalOffset = QtWidgets.QDoubleSpinBox(self.groupBox_7) + self.doubleSpinBox_SignalOffset.setDecimals(3) + self.doubleSpinBox_SignalOffset.setMinimum(-10.0) + self.doubleSpinBox_SignalOffset.setMaximum(10.0) + self.doubleSpinBox_SignalOffset.setSingleStep(0.001) + self.doubleSpinBox_SignalOffset.setProperty("value", 0.0) + self.doubleSpinBox_SignalOffset.setObjectName("doubleSpinBox_SignalOffset") + self.gridLayout_9.addWidget(self.doubleSpinBox_SignalOffset, 6, 1, 1, 1) + self.label_35 = QtWidgets.QLabel(self.groupBox_7) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.label_34.sizePolicy().hasHeightForWidth()) - self.label_34.setSizePolicy(sizePolicy) - self.label_34.setObjectName("label_34") - self.gridLayout_9.addWidget(self.label_34, 5, 0, 1, 1) - self.lineEdit_transImpGain = QtWidgets.QLineEdit(self.groupBox_7) - self.lineEdit_transImpGain.setObjectName("lineEdit_transImpGain") - self.gridLayout_9.addWidget(self.lineEdit_transImpGain, 5, 1, 1, 1) + sizePolicy.setHeightForWidth(self.label_35.sizePolicy().hasHeightForWidth()) + self.label_35.setSizePolicy(sizePolicy) + self.label_35.setObjectName("label_35") + self.gridLayout_9.addWidget(self.label_35, 6, 0, 1, 1) self.verticalLayout_10.addLayout(self.gridLayout_9) self.horizontalLayout_2.addWidget(self.groupBox_7) self.groupBox_8 = QtWidgets.QGroupBox(self.tab_FIT) @@ -470,15 +510,6 @@ def setupUi(self, MainWindow): self.radioButton_FITSource_CH2.setObjectName("radioButton_FITSource_CH2") self.horizontalLayout_4.addWidget(self.radioButton_FITSource_CH2) self.verticalLayout_11.addLayout(self.horizontalLayout_4) - self.horizontalLayout_12 = QtWidgets.QHBoxLayout() - self.horizontalLayout_12.setObjectName("horizontalLayout_12") - self.radioButton_FITSource_CH3 = QtWidgets.QRadioButton(self.groupBox_8) - self.radioButton_FITSource_CH3.setObjectName("radioButton_FITSource_CH3") - self.horizontalLayout_12.addWidget(self.radioButton_FITSource_CH3) - self.radioButton_FITSource_CH4 = QtWidgets.QRadioButton(self.groupBox_8) - self.radioButton_FITSource_CH4.setObjectName("radioButton_FITSource_CH4") - self.horizontalLayout_12.addWidget(self.radioButton_FITSource_CH4) - self.verticalLayout_11.addLayout(self.horizontalLayout_12) self.gridLayout_12 = QtWidgets.QGridLayout() self.gridLayout_12.setObjectName("gridLayout_12") self.doubleSpinBox_FIT_B = QtWidgets.QDoubleSpinBox(self.groupBox_8) @@ -550,10 +581,9 @@ def setupUi(self, MainWindow): self.plainTextEdit_FITResults.setObjectName("plainTextEdit_FITResults") self.verticalLayout_14.addWidget(self.plainTextEdit_FITResults) self.gridLayout_FITRES.addWidget(self.groupBox_FIT_Results, 0, 0, 1, 1) - self.pushButton_FIT_Realtime = QtWidgets.QPushButton(self.tab_FIT) - self.pushButton_FIT_Realtime.setCheckable(True) - self.pushButton_FIT_Realtime.setObjectName("pushButton_FIT_Realtime") - self.gridLayout_FITRES.addWidget(self.pushButton_FIT_Realtime, 1, 1, 1, 1) + self.pushButton = QtWidgets.QPushButton(self.tab_FIT) + self.pushButton.setObjectName("pushButton") + self.gridLayout_FITRES.addWidget(self.pushButton, 1, 1, 1, 1) self.groupBox_10 = QtWidgets.QGroupBox(self.tab_FIT) self.groupBox_10.setObjectName("groupBox_10") self.verticalLayout_13 = QtWidgets.QVBoxLayout(self.groupBox_10) @@ -729,167 +759,10 @@ def setupUi(self, MainWindow): self.gridLayout_CH_settings.addWidget(self.groupBox_M_CH2, 0, 1, 1, 1) self.verticalLayout_15.addLayout(self.gridLayout_CH_settings) self.tabWidget.addTab(self.tab_Monitor, "") - self.tab_EOM = QtWidgets.QWidget() - self.tab_EOM.setObjectName("tab_EOM") - self.verticalLayout_16 = QtWidgets.QVBoxLayout(self.tab_EOM) - self.verticalLayout_16.setObjectName("verticalLayout_16") - self.gridLayout_16 = QtWidgets.QGridLayout() - self.gridLayout_16.setObjectName("gridLayout_16") - spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) - self.gridLayout_16.addItem(spacerItem2, 0, 1, 1, 1) - self.checkBox_ActivateEOMstab = QtWidgets.QCheckBox(self.tab_EOM) - self.checkBox_ActivateEOMstab.setMinimumSize(QtCore.QSize(0, 0)) - self.checkBox_ActivateEOMstab.setBaseSize(QtCore.QSize(0, 0)) - font = QtGui.QFont() - font.setPointSize(20) - self.checkBox_ActivateEOMstab.setFont(font) - self.checkBox_ActivateEOMstab.setIconSize(QtCore.QSize(50, 50)) - self.checkBox_ActivateEOMstab.setObjectName("checkBox_ActivateEOMstab") - self.gridLayout_16.addWidget(self.checkBox_ActivateEOMstab, 0, 0, 1, 1) - self.verticalLayout_16.addLayout(self.gridLayout_16) - self.horizontalLayout_8 = QtWidgets.QHBoxLayout() - self.horizontalLayout_8.setObjectName("horizontalLayout_8") - self.groupBox_5 = QtWidgets.QGroupBox(self.tab_EOM) - self.groupBox_5.setMinimumSize(QtCore.QSize(0, 50)) - self.groupBox_5.setObjectName("groupBox_5") - self.horizontalLayout_9 = QtWidgets.QHBoxLayout(self.groupBox_5) - self.horizontalLayout_9.setObjectName("horizontalLayout_9") - self.radioButton_PrStabSourceCH1 = QtWidgets.QRadioButton(self.groupBox_5) - font = QtGui.QFont() - font.setPointSize(10) - self.radioButton_PrStabSourceCH1.setFont(font) - self.radioButton_PrStabSourceCH1.setChecked(True) - self.radioButton_PrStabSourceCH1.setObjectName("radioButton_PrStabSourceCH1") - self.horizontalLayout_9.addWidget(self.radioButton_PrStabSourceCH1) - self.radioButton_PrStabSourceCH2 = QtWidgets.QRadioButton(self.groupBox_5) - font = QtGui.QFont() - font.setPointSize(10) - self.radioButton_PrStabSourceCH2.setFont(font) - self.radioButton_PrStabSourceCH2.setObjectName("radioButton_PrStabSourceCH2") - self.horizontalLayout_9.addWidget(self.radioButton_PrStabSourceCH2) - self.radioButton_PrStabSourceCH3 = QtWidgets.QRadioButton(self.groupBox_5) - font = QtGui.QFont() - font.setPointSize(10) - self.radioButton_PrStabSourceCH3.setFont(font) - self.radioButton_PrStabSourceCH3.setObjectName("radioButton_PrStabSourceCH3") - self.horizontalLayout_9.addWidget(self.radioButton_PrStabSourceCH3) - self.radioButton_PrStabSourceCH4 = QtWidgets.QRadioButton(self.groupBox_5) - font = QtGui.QFont() - font.setPointSize(10) - self.radioButton_PrStabSourceCH4.setFont(font) - self.radioButton_PrStabSourceCH4.setObjectName("radioButton_PrStabSourceCH4") - self.horizontalLayout_9.addWidget(self.radioButton_PrStabSourceCH4) - self.horizontalLayout_8.addWidget(self.groupBox_5) - spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) - self.horizontalLayout_8.addItem(spacerItem3) - self.verticalLayout_16.addLayout(self.horizontalLayout_8) - self.horizontalLayout_6 = QtWidgets.QHBoxLayout() - self.horizontalLayout_6.setObjectName("horizontalLayout_6") - self.groupBox_9 = QtWidgets.QGroupBox(self.tab_EOM) - self.groupBox_9.setObjectName("groupBox_9") - self.horizontalLayout_7 = QtWidgets.QHBoxLayout(self.groupBox_9) - self.horizontalLayout_7.setObjectName("horizontalLayout_7") - self.gridLayout_17 = QtWidgets.QGridLayout() - self.gridLayout_17.setObjectName("gridLayout_17") - self.doubleSpinBox_setBiasValue = QtWidgets.QDoubleSpinBox(self.groupBox_9) - self.doubleSpinBox_setBiasValue.setMinimumSize(QtCore.QSize(200, 0)) - self.doubleSpinBox_setBiasValue.setDecimals(8) - self.doubleSpinBox_setBiasValue.setMinimum(-10.0) - self.doubleSpinBox_setBiasValue.setMaximum(10.0) - self.doubleSpinBox_setBiasValue.setSingleStep(0.01) - self.doubleSpinBox_setBiasValue.setProperty("value", -1.5) - self.doubleSpinBox_setBiasValue.setObjectName("doubleSpinBox_setBiasValue") - self.gridLayout_17.addWidget(self.doubleSpinBox_setBiasValue, 1, 1, 1, 1) - self.label_32 = QtWidgets.QLabel(self.groupBox_9) - self.label_32.setObjectName("label_32") - self.gridLayout_17.addWidget(self.label_32, 0, 0, 1, 1) - self.label_ActualProbeValue = QtWidgets.QLabel(self.groupBox_9) - self.label_ActualProbeValue.setMinimumSize(QtCore.QSize(100, 0)) - self.label_ActualProbeValue.setObjectName("label_ActualProbeValue") - self.gridLayout_17.addWidget(self.label_ActualProbeValue, 0, 2, 1, 1) - self.doubleSpinBox_setProbeValue = QtWidgets.QDoubleSpinBox(self.groupBox_9) - self.doubleSpinBox_setProbeValue.setMinimumSize(QtCore.QSize(200, 0)) - self.doubleSpinBox_setProbeValue.setDecimals(8) - self.doubleSpinBox_setProbeValue.setSingleStep(0.01) - self.doubleSpinBox_setProbeValue.setProperty("value", 0.55) - self.doubleSpinBox_setProbeValue.setObjectName("doubleSpinBox_setProbeValue") - self.gridLayout_17.addWidget(self.doubleSpinBox_setProbeValue, 0, 1, 1, 1) - self.label_33 = QtWidgets.QLabel(self.groupBox_9) - self.label_33.setObjectName("label_33") - self.gridLayout_17.addWidget(self.label_33, 1, 0, 1, 1) - self.doubleSpinBox_setBiasRange_min = QtWidgets.QDoubleSpinBox(self.groupBox_9) - self.doubleSpinBox_setBiasRange_min.setMinimumSize(QtCore.QSize(50, 0)) - self.doubleSpinBox_setBiasRange_min.setDecimals(1) - self.doubleSpinBox_setBiasRange_min.setMinimum(-100.0) - self.doubleSpinBox_setBiasRange_min.setMaximum(100.0) - self.doubleSpinBox_setBiasRange_min.setSingleStep(0.1) - self.doubleSpinBox_setBiasRange_min.setProperty("value", -10.0) - self.doubleSpinBox_setBiasRange_min.setObjectName("doubleSpinBox_setBiasRange_min") - self.gridLayout_17.addWidget(self.doubleSpinBox_setBiasRange_min, 1, 3, 1, 1) - self.label_ActualProbeValue_2 = QtWidgets.QLabel(self.groupBox_9) - self.label_ActualProbeValue_2.setMinimumSize(QtCore.QSize(100, 0)) - self.label_ActualProbeValue_2.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) - self.label_ActualProbeValue_2.setObjectName("label_ActualProbeValue_2") - self.gridLayout_17.addWidget(self.label_ActualProbeValue_2, 1, 2, 1, 1) - self.doubleSpinBox_setBiasRange_max = QtWidgets.QDoubleSpinBox(self.groupBox_9) - self.doubleSpinBox_setBiasRange_max.setMinimumSize(QtCore.QSize(50, 0)) - self.doubleSpinBox_setBiasRange_max.setDecimals(1) - self.doubleSpinBox_setBiasRange_max.setMinimum(-100.0) - self.doubleSpinBox_setBiasRange_max.setMaximum(100.0) - self.doubleSpinBox_setBiasRange_max.setSingleStep(0.1) - self.doubleSpinBox_setBiasRange_max.setProperty("value", 10.0) - self.doubleSpinBox_setBiasRange_max.setObjectName("doubleSpinBox_setBiasRange_max") - self.gridLayout_17.addWidget(self.doubleSpinBox_setBiasRange_max, 1, 4, 1, 1) - self.horizontalLayout_7.addLayout(self.gridLayout_17) - self.horizontalLayout_6.addWidget(self.groupBox_9) - spacerItem4 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) - self.horizontalLayout_6.addItem(spacerItem4) - self.verticalLayout_16.addLayout(self.horizontalLayout_6) - self.horizontalLayout_11 = QtWidgets.QHBoxLayout() - self.horizontalLayout_11.setObjectName("horizontalLayout_11") - self.groupBox_11 = QtWidgets.QGroupBox(self.tab_EOM) - self.groupBox_11.setObjectName("groupBox_11") - self.horizontalLayout_10 = QtWidgets.QHBoxLayout(self.groupBox_11) - self.horizontalLayout_10.setObjectName("horizontalLayout_10") - self.gridLayout_20 = QtWidgets.QGridLayout() - self.gridLayout_20.setObjectName("gridLayout_20") - self.label_35 = QtWidgets.QLabel(self.groupBox_11) - self.label_35.setObjectName("label_35") - self.gridLayout_20.addWidget(self.label_35, 0, 0, 1, 1) - self.doubleSpinBox_ProbeLevelCorrectionFactor = QtWidgets.QDoubleSpinBox(self.groupBox_11) - self.doubleSpinBox_ProbeLevelCorrectionFactor.setMinimumSize(QtCore.QSize(200, 0)) - self.doubleSpinBox_ProbeLevelCorrectionFactor.setMinimum(-1000.0) - self.doubleSpinBox_ProbeLevelCorrectionFactor.setMaximum(1000.0) - self.doubleSpinBox_ProbeLevelCorrectionFactor.setSingleStep(0.1) - self.doubleSpinBox_ProbeLevelCorrectionFactor.setProperty("value", -100.0) - self.doubleSpinBox_ProbeLevelCorrectionFactor.setObjectName("doubleSpinBox_ProbeLevelCorrectionFactor") - self.gridLayout_20.addWidget(self.doubleSpinBox_ProbeLevelCorrectionFactor, 0, 1, 1, 1) - self.doubleSpinBox_ProbeValueTolerance = QtWidgets.QDoubleSpinBox(self.groupBox_11) - self.doubleSpinBox_ProbeValueTolerance.setMinimumSize(QtCore.QSize(200, 0)) - self.doubleSpinBox_ProbeValueTolerance.setDecimals(1) - self.doubleSpinBox_ProbeValueTolerance.setSingleStep(0.1) - self.doubleSpinBox_ProbeValueTolerance.setProperty("value", 3.0) - self.doubleSpinBox_ProbeValueTolerance.setObjectName("doubleSpinBox_ProbeValueTolerance") - self.gridLayout_20.addWidget(self.doubleSpinBox_ProbeValueTolerance, 1, 1, 1, 1) - self.label_36 = QtWidgets.QLabel(self.groupBox_11) - self.label_36.setObjectName("label_36") - self.gridLayout_20.addWidget(self.label_36, 1, 0, 1, 1) - self.checkBox_useTolerance = QtWidgets.QCheckBox(self.groupBox_11) - self.checkBox_useTolerance.setChecked(False) - self.checkBox_useTolerance.setObjectName("checkBox_useTolerance") - self.gridLayout_20.addWidget(self.checkBox_useTolerance, 1, 2, 1, 1) - self.horizontalLayout_10.addLayout(self.gridLayout_20) - self.horizontalLayout_11.addWidget(self.groupBox_11) - spacerItem5 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) - self.horizontalLayout_11.addItem(spacerItem5) - self.verticalLayout_16.addLayout(self.horizontalLayout_11) - spacerItem6 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.verticalLayout_16.addItem(spacerItem6) - self.tabWidget.addTab(self.tab_EOM, "") self.verticalLayout_9.addWidget(self.tabWidget) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) - self.menubar.setGeometry(QtCore.QRect(0, 0, 1193, 26)) + self.menubar.setGeometry(QtCore.QRect(0, 0, 1197, 26)) self.menubar.setObjectName("menubar") self.menuFAP = QtWidgets.QMenu(self.menubar) self.menuFAP.setObjectName("menuFAP") @@ -899,6 +772,12 @@ def setupUi(self, MainWindow): self.statusbar.setStatusTip("") self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) + self.actionSave_settings = QtWidgets.QAction(MainWindow) + self.actionSave_settings.setObjectName("actionSave_settings") + self.actionLoad_settings = QtWidgets.QAction(MainWindow) + self.actionLoad_settings.setObjectName("actionLoad_settings") + self.menuFAP.addAction(self.actionSave_settings) + self.menuFAP.addAction(self.actionLoad_settings) self.menubar.addAction(self.menuFAP.menuAction()) self.retranslateUi(MainWindow) @@ -957,21 +836,27 @@ def retranslateUi(self, MainWindow): self.comboBox_CH1Range.setItemText(7, _translate("MainWindow", "40")) self.comboBox_CH1Range.setItemText(8, _translate("MainWindow", "80")) self.groupBox.setTitle(_translate("MainWindow", "Drive")) + self.doubleSpinBox_ZeroLevel.setSuffix(_translate("MainWindow", " V")) self.doubleSpinBox_Frequency_Hz.setSuffix(_translate("MainWindow", " Hz")) self.doubleSpinBox_TotalTime_ms.setSuffix(_translate("MainWindow", " ms")) - self.label_9.setText(_translate("MainWindow", "Duty cycle")) self.label_4.setText(_translate("MainWindow", "Frequency")) - self.label_3.setText(_translate("MainWindow", "Pump time")) self.label.setText(_translate("MainWindow", "Points")) self.label_2.setText(_translate("MainWindow", "Cycle total time")) + self.label_9.setText(_translate("MainWindow", "Duty cycle")) + self.label_3.setText(_translate("MainWindow", "Pump time")) self.doubleSpinBox_PumpTime_ms.setSuffix(_translate("MainWindow", " ms")) self.doubleSpinBox_Points.setPrefix(_translate("MainWindow", "# ")) - self.doubleSpinBox_ZeroLevel.setSuffix(_translate("MainWindow", " V")) self.doubleSpinBox_ProbeLevel.setSuffix(_translate("MainWindow", " V")) - self.label_7.setText(_translate("MainWindow", "Probe level")) - self.label_6.setText(_translate("MainWindow", "Pump level")) self.doubleSpinBox_PumpLevel.setSuffix(_translate("MainWindow", " V")) self.label_8.setText(_translate("MainWindow", "Zero level")) + self.label_7.setText(_translate("MainWindow", "Probe level")) + self.label_6.setText(_translate("MainWindow", "Pump level")) + self.doubleSpinBox_ExpAmplitude.setToolTip(_translate("MainWindow", "Exponential amplitude. Set to 0 to turn off.")) + self.doubleSpinBox_ExpAmplitude.setSuffix(_translate("MainWindow", " V")) + self.label_32.setText(_translate("MainWindow", "Exp. amplitude")) + self.label_33.setText(_translate("MainWindow", "Exp. relaxation")) + self.doubleSpinBox_ExpRelaxation.setToolTip(_translate("MainWindow", "Exponential relaxation rate")) + self.doubleSpinBox_ExpRelaxation.setSuffix(_translate("MainWindow", "k rad/s")) self.okButton_GeneratorStart.setText(_translate("MainWindow", "Start/Stop generator")) self.groupBox_6.setTitle(_translate("MainWindow", "Save data")) self.label_28.setText(_translate("MainWindow", "Filename prefix")) @@ -997,29 +882,30 @@ def retranslateUi(self, MainWindow): self.label_RemainingToSave.setText(_translate("MainWindow", "Remaining")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_data), _translate("MainWindow", "Acquire data")) self.groupBox_7.setTitle(_translate("MainWindow", "Filter")) - self.label_17.setText(_translate("MainWindow", "Type")) + self.label_18.setText(_translate("MainWindow", "Data start")) + self.label_19.setText(_translate("MainWindow", "Data stop")) + self.doubleSpinBox_FITStart_ms.setSuffix(_translate("MainWindow", " ms")) + self.doubleSpinBox_FITStop_ms.setSuffix(_translate("MainWindow", " ms")) self.comboBox_FilterType.setItemText(0, _translate("MainWindow", "High pass from 10k")) self.comboBox_FilterType.setItemText(1, _translate("MainWindow", "Band pass 1-12k")) self.comboBox_FilterType.setItemText(2, _translate("MainWindow", "Band pass 8-22k")) self.comboBox_FilterType.setItemText(3, _translate("MainWindow", "Band pass 18-32k")) self.comboBox_FilterType.setItemText(4, _translate("MainWindow", "Low pass up to 12k")) - self.doubleSpinBox_FITStop_ms.setSuffix(_translate("MainWindow", " ms")) - self.doubleSpinBox_FilterStop_ms.setSuffix(_translate("MainWindow", " ms")) - self.doubleSpinBox_FITStart_ms.setSuffix(_translate("MainWindow", " ms")) + self.doubleSpinBox_TransImp_Gain.setToolTip(_translate("MainWindow", "Used for Shot noise calculation only when conversion from V to A is required.")) + self.doubleSpinBox_TransImp_Gain.setSuffix(_translate("MainWindow", " V/A")) self.doubleSpinBox_FilterStart_ms.setSuffix(_translate("MainWindow", " ms")) - self.label_19.setText(_translate("MainWindow", "Data stop")) self.label_25.setText(_translate("MainWindow", "FIT stop")) - self.label_18.setText(_translate("MainWindow", "Data start")) - self.label_24.setText(_translate("MainWindow", "FIT start")) self.label_34.setText(_translate("MainWindow", "Transimp. gain")) - self.lineEdit_transImpGain.setToolTip(_translate("MainWindow", "Transimpedance gain [V/A] in scientific format.")) - self.lineEdit_transImpGain.setText(_translate("MainWindow", "1e6")) + self.doubleSpinBox_FilterStop_ms.setSuffix(_translate("MainWindow", " ms")) + self.label_17.setText(_translate("MainWindow", "Type")) + self.label_24.setText(_translate("MainWindow", "FIT start")) + self.doubleSpinBox_SignalOffset.setToolTip(_translate("MainWindow", "Used for Shot noise calculation only. It indicates voltage substracted from the signal before oscilloscope.")) + self.doubleSpinBox_SignalOffset.setSuffix(_translate("MainWindow", " V")) + self.label_35.setText(_translate("MainWindow", "Signal Offset")) self.groupBox_8.setTitle(_translate("MainWindow", "FIT initial parameters")) self.label_27.setText(_translate("MainWindow", "Fit src:")) self.radioButton_FITSource_CH1.setText(_translate("MainWindow", "CH1")) self.radioButton_FITSource_CH2.setText(_translate("MainWindow", "CH2")) - self.radioButton_FITSource_CH3.setText(_translate("MainWindow", "CH3")) - self.radioButton_FITSource_CH4.setText(_translate("MainWindow", "CH4")) self.doubleSpinBox_FIT_f0.setSuffix(_translate("MainWindow", " Hz")) self.label_21.setText(_translate("MainWindow", "B:")) self.label_20.setText(_translate("MainWindow", "f0:")) @@ -1033,8 +919,7 @@ def retranslateUi(self, MainWindow): self.plainTextEdit_FITResults.setPlainText(_translate("MainWindow", "Some text here\n" "\n" "f: 2568.258")) - self.pushButton_FIT_Realtime.setToolTip(_translate("MainWindow", "Not implemented")) - self.pushButton_FIT_Realtime.setText(_translate("MainWindow", "Fit contineously")) + self.pushButton.setText(_translate("MainWindow", "Not implemented")) self.groupBox_10.setTitle(_translate("MainWindow", "FFT + FIT sensitivity")) self.plainTextEdit_SensitivityFFT.setPlainText(_translate("MainWindow", "Some text here\n" "\n" @@ -1097,34 +982,6 @@ def retranslateUi(self, MainWindow): self.radioButton_M_CH2DC.setText(_translate("MainWindow", "DC")) self.label_64.setText(_translate("MainWindow", "Range")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_Monitor), _translate("MainWindow", "CH Monitor")) - self.checkBox_ActivateEOMstab.setText(_translate("MainWindow", "Activate EOM stabilization")) - self.groupBox_5.setTitle(_translate("MainWindow", "Select Input")) - self.radioButton_PrStabSourceCH1.setText(_translate("MainWindow", "CH1")) - self.radioButton_PrStabSourceCH2.setText(_translate("MainWindow", "CH2")) - self.radioButton_PrStabSourceCH3.setText(_translate("MainWindow", "CH3")) - self.radioButton_PrStabSourceCH4.setText(_translate("MainWindow", "CH4")) - self.groupBox_9.setTitle(_translate("MainWindow", "Set point")) - self.doubleSpinBox_setBiasValue.setToolTip(_translate("MainWindow", "Set bias voltage here!")) - self.doubleSpinBox_setBiasValue.setSuffix(_translate("MainWindow", "V")) - self.label_32.setText(_translate("MainWindow", "Set probe value")) - self.label_ActualProbeValue.setText(_translate("MainWindow", "Actual probe value")) - self.doubleSpinBox_setProbeValue.setSuffix(_translate("MainWindow", "V")) - self.label_33.setText(_translate("MainWindow", "Set bias value")) - self.doubleSpinBox_setBiasRange_min.setToolTip(_translate("MainWindow", "Set bias voltage here!")) - self.doubleSpinBox_setBiasRange_min.setPrefix(_translate("MainWindow", "min ")) - self.doubleSpinBox_setBiasRange_min.setSuffix(_translate("MainWindow", " V")) - self.label_ActualProbeValue_2.setText(_translate("MainWindow", "Range:")) - self.doubleSpinBox_setBiasRange_max.setToolTip(_translate("MainWindow", "Set bias voltage here!")) - self.doubleSpinBox_setBiasRange_max.setPrefix(_translate("MainWindow", "max ")) - self.doubleSpinBox_setBiasRange_max.setSuffix(_translate("MainWindow", " V")) - self.groupBox_11.setTitle(_translate("MainWindow", "Loop parameters")) - self.label_35.setText(_translate("MainWindow", "Correction factor")) - self.doubleSpinBox_ProbeLevelCorrectionFactor.setToolTip(_translate("MainWindow", "error * correction factor + old")) - self.doubleSpinBox_ProbeLevelCorrectionFactor.setSuffix(_translate("MainWindow", "mV/V")) - self.doubleSpinBox_ProbeValueTolerance.setToolTip(_translate("MainWindow", "If with in tolerance no correction will be applied")) - self.doubleSpinBox_ProbeValueTolerance.setSuffix(_translate("MainWindow", "%")) - self.label_36.setText(_translate("MainWindow", "Tolerance")) - self.checkBox_useTolerance.setToolTip(_translate("MainWindow", "If checked no correction to bias will be applied if within +/- tolerance.")) - self.checkBox_useTolerance.setText(_translate("MainWindow", "Use tolerance?")) - self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_EOM), _translate("MainWindow", "EOM stab.")) self.menuFAP.setTitle(_translate("MainWindow", "FAP")) + self.actionSave_settings.setText(_translate("MainWindow", "Save settings")) + self.actionLoad_settings.setText(_translate("MainWindow", "Load settings")) diff --git a/gui.ui b/gui.ui index adc8d00..b6090eb 100644 --- a/gui.ui +++ b/gui.ui @@ -6,7 +6,7 @@ 0 0 - 1193 + 1197 869 @@ -151,7 +151,7 @@ 1.000000000000000 - 312500.000000000000000 + 156250.000000000000000 @@ -379,38 +379,41 @@ - - + + - Hz + V + + + 4 + + + -10.000000000000000 - 1000000.000000000000000 + 10.000000000000000 - 5.000000000000000 + 0.001000000000000 - 7000.000000000000000 + 0.000000000000000 - - + + - - - - 3 + Hz - 1.000000000000000 + 1000000.000000000000000 - 0.100000000000000 + 5.000000000000000 - 0.300000000000000 + 13746.000000000000000 @@ -426,14 +429,7 @@ 1.000000000000000 - 100.000000000000000 - - - - - - - Duty cycle + 50.000000000000000 @@ -444,13 +440,6 @@ - - - - Pump time - - - @@ -458,6 +447,25 @@ + + + + + + + 3 + + + 1.000000000000000 + + + 0.100000000000000 + + + 0.500000000000000 + + + @@ -465,6 +473,20 @@ + + + + Duty cycle + + + + + + + Pump time + + + @@ -477,7 +499,7 @@ 1.000000000000000 - 30.000000000000000 + 15.000000000000000 @@ -503,8 +525,8 @@ - - + + V @@ -521,12 +543,12 @@ 0.010000000000000 - 0.000000000000000 + 0.500000000000000 - - + + V @@ -540,10 +562,17 @@ 10.000000000000000 - 0.010000000000000 + 0.001000000000000 - 0.500000000000000 + 1.000000000000000 + + + + + + + Zero level @@ -561,8 +590,11 @@ - - + + + + Exponential amplitude. Set to 0 to turn off. + V @@ -579,14 +611,43 @@ 0.010000000000000 - 4.000000000000000 + 0.000000000000000 - - + + - Zero level + Exp. amplitude + + + + + + + Exp. relaxation + + + + + + + Exponential relaxation rate + + + k rad/s + + + 4 + + + 500.000000000000000 + + + 1.000000000000000 + + + 87.000000000000000 @@ -884,8 +945,8 @@ - - + + 0 @@ -893,7 +954,52 @@ - Type + Data start + + + + + + + + 0 + 0 + + + + Data stop + + + + + + + ms + + + 1000.000000000000000 + + + 0.100000000000000 + + + 30.000000000000000 + + + + + + + ms + + + 1000.000000000000000 + + + 0.100000000000000 + + + 100.000000000000000 @@ -929,24 +1035,27 @@ - - + + + + Used for Shot noise calculation only when conversion from V to A is required. + - ms + V/A - 1000.000000000000000 + 100000000.000000000000000 - 0.100000000000000 + 1.000000000000000 - 100.000000000000000 + 1000000.000000000000000 - - + + ms @@ -957,28 +1066,38 @@ 0.100000000000000 - 100.000000000000000 + 30.000000000000000 - - - - ms + + + + + 0 + 0 + - - 1000.000000000000000 + + FIT stop - - 0.100000000000000 + + + + + + + 0 + 0 + - - 30.000000000000000 + + Transimp. gain - - + + ms @@ -989,12 +1108,12 @@ 0.100000000000000 - 30.000000000000000 + 100.000000000000000 - - + + 0 @@ -1002,12 +1121,12 @@ - Data stop + Type - - + + 0 @@ -1015,38 +1134,37 @@ - FIT stop + FIT start - - - - - 0 - 0 - + + + + Used for Shot noise calculation only. It indicates voltage substracted from the signal before oscilloscope. - - Data start + + V - - - - - - - 0 - 0 - + + 3 - - FIT start + + -10.000000000000000 + + + 10.000000000000000 + + + 0.001000000000000 + + + 0.000000000000000 - - + + 0 @@ -1054,17 +1172,7 @@ - Transimp. gain - - - - - - - Transimpedance gain [V/A] in scientific format. - - - 1e6 + Signal Offset @@ -1107,24 +1215,6 @@ - - - - - - CH3 - - - - - - - CH4 - - - - - @@ -1287,15 +1377,9 @@ f: 2568.258 - - - Not implemented - + - Fit contineously - - - true + Not implemented @@ -1750,460 +1834,6 @@ f: 2568.258 - - - EOM stab. - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 20 - - - - Activate EOM stabilization - - - - 50 - 50 - - - - - - - - - - - - - 0 - 50 - - - - Select Input - - - - - - - 10 - - - - CH1 - - - true - - - - - - - - 10 - - - - CH2 - - - - - - - - 10 - - - - CH3 - - - - - - - - 10 - - - - CH4 - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - Set point - - - - - - - - - 200 - 0 - - - - Set bias voltage here! - - - V - - - 8 - - - -10.000000000000000 - - - 10.000000000000000 - - - 0.010000000000000 - - - -1.500000000000000 - - - - - - - Set probe value - - - - - - - - 100 - 0 - - - - Actual probe value - - - - - - - - 200 - 0 - - - - V - - - 8 - - - 0.010000000000000 - - - 0.550000000000000 - - - - - - - Set bias value - - - - - - - - 50 - 0 - - - - Set bias voltage here! - - - min - - - V - - - 1 - - - -100.000000000000000 - - - 100.000000000000000 - - - 0.100000000000000 - - - -10.000000000000000 - - - - - - - - 100 - 0 - - - - Range: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 50 - 0 - - - - Set bias voltage here! - - - max - - - V - - - 1 - - - -100.000000000000000 - - - 100.000000000000000 - - - 0.100000000000000 - - - 10.000000000000000 - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - Loop parameters - - - - - - - - Correction factor - - - - - - - - 200 - 0 - - - - error * correction factor + old - - - mV/V - - - -1000.000000000000000 - - - 1000.000000000000000 - - - 0.100000000000000 - - - -100.000000000000000 - - - - - - - - 200 - 0 - - - - If with in tolerance no correction will be applied - - - % - - - 1 - - - 0.100000000000000 - - - 3.000000000000000 - - - - - - - Tolerance - - - - - - - If checked no correction to bias will be applied if within +/- tolerance. - - - Use tolerance? - - - false - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - @@ -2213,7 +1843,7 @@ f: 2568.258 0 0 - 1193 + 1197 26 @@ -2221,6 +1851,8 @@ f: 2568.258 FAP + + @@ -2232,6 +1864,16 @@ f: 2568.258 + + + Save settings + + + + + Load settings + + diff --git a/niTaskUSB.py b/niTaskUSB.py deleted file mode 100644 index 01d8be4..0000000 --- a/niTaskUSB.py +++ /dev/null @@ -1,35 +0,0 @@ -import nidaqmx -import time - -times = [] -for i in range(-10,10): - times.append(time.time()) - print(times[-1]) - with nidaqmx.Task() as task: - task.ao_channels.add_ao_voltage_chan("Dev1/ao0") - task.write(i, auto_start=True) - - time.sleep(.1) - -to = times[0] -for t in times: - print(t-to) - to = t - -times = [] -with nidaqmx.Task() as task: - task.ao_channels.add_ao_voltage_chan("Dev1/ao0") - for i in range(-10,10): - times.append(time.time()) - print(times[-1]) - - - task.write(i, auto_start=True) - - time.sleep(.1) - -to = times[0] -for t in times: - print(t-to) - to = t - diff --git a/tiepieArb.py b/tiepieArb.py index c781949..df846bc 100644 --- a/tiepieArb.py +++ b/tiepieArb.py @@ -10,30 +10,25 @@ class arbGenerator: - def __init__(self, sn=None): + def __init__(self): + # Enable network search: + libtiepie.network.auto_detect_enabled = True + # Search for devices: libtiepie.device_list.update() # Try to open a generator with arbitrary support: self.gen = None for item in libtiepie.device_list: - + print(item) if item.can_open(libtiepie.DEVICETYPE_GENERATOR): - if sn is None: - self.gen = item.open_generator() - else: - if sn == item.serial_number: - self.gen = item.open_generator() - + self.gen = item.open_generator() if self.gen.signal_types & libtiepie.ST_ARBITRARY: break else: self.gen = None if self.gen is None: print("No generator detected! Connect the USB device!") - else: - #get S/N - print(item) def arbLoad(self, arb, amplitude=1, frequency=10, offset=0.0): if self.gen is None: @@ -44,11 +39,11 @@ def arbLoad(self, arb, amplitude=1, frequency=10, offset=0.0): self.gen.signal_type = libtiepie.ST_ARBITRARY # Select frequency mode: - self.gen.frequency_mode = libtiepie.FM_SIGNALFREQUENCY # libtiepie.FM_SAMPLEFREQUENCY + self.gen.frequency_mode = libtiepie.FM_SIGNALFREQUENCY # libtiepie.FM_SAMPLEFREQUENCY FM_SIGNALFREQUENCY + #print(f" gen {frequency=}") # Set sample frequency: - self.gen.frequency = frequency # 10 Hz - print(f"{frequency=}, {self.gen.frequency=}") + self.gen.frequency = frequency # 100 kHz # Set amplitude: self.gen.amplitude = amplitude # 2 V @@ -65,10 +60,11 @@ def arbLoad(self, arb, amplitude=1, frequency=10, offset=0.0): def start(self): if self.gen is None: + print("Gen is none TiePieArb.py") return # Enable output: - self.gen.output_on = True + self.gen.output_enable = True # Start signal generation: self.gen.start() print("Generator started") @@ -80,15 +76,6 @@ def stop(self): self.gen.stop() # Disable output: - self.gen.output_on = False + self.gen.output_enable = False print("Generator STOP") - -if __name__.endswith('__main__'): - gen = arbGenerator() - print(gen.gen.__dict__.keys()) - print(gen.gen._trigger_outputs) - for t in gen.gen._trigger_outputs: - print(t.name) - - #print(gen.gen.IDKIND_SERIALNUMBER) diff --git a/tiepieSCP.py b/tiepieSCP.py index de9f435..dbae850 100644 --- a/tiepieSCP.py +++ b/tiepieSCP.py @@ -19,7 +19,6 @@ class oscilloscope: } trigger_name = "Generator new period" channels = 0 - scp_list_sn =[] def __init__(self): # Search for devices: @@ -27,13 +26,6 @@ def __init__(self): # Try to open an oscilloscope with block measurement support: self.scp = None - self.scp_list_sn=[] - for item in libtiepie.device_list: - print(item.name) - print(item.serial_number) - if "Handyscope HS5" == item.name.split("-")[0]: - self.scp_list_sn.append(item.serial_number) - scps = [] for item in libtiepie.device_list: if item.can_open(libtiepie.DEVICETYPE_OSCILLOSCOPE): @@ -69,11 +61,9 @@ def __init__(self): self.channels = self.scp._channels._get_count() print(f"We have {self.channels} channels.") - - def set(self, mode="block", - sample_frequency=1e6, + sample_rate=1e6, record_length=1e5, CH_ranges=[8, 2, 2, 2], CH_couplings=["dc", "dc", "dc", "dc"], @@ -95,12 +85,9 @@ def set(self, # print("set measure_mode STREAM") self.scp.measure_mode = libtiepie.MM_STREAM - # Set sample frequency: - self.scp.sample_frequency = sample_frequency # 1 MHz - # set vertical resolution self.scp.resolution = 16 # set 16 bit vertical resolution - # print("Sample frequency SET to:", self.scp.sample_frequency) + # print("Sample frequency SET to:", self.scp.sample_rate) # Set record length: self.scp.record_length = int(record_length) # 10000 samples @@ -108,6 +95,9 @@ def set(self, # Set pre sample ratio: self.scp.pre_sample_ratio = 0 # 0 % + # Set sample frequency: + self.scp.sample_rate = sample_rate # 1 MHz + # For all channels: for i, ch in enumerate(self.scp.channels): # Enable channel to measure it: @@ -138,7 +128,7 @@ def set(self, CH2.coupling = libtiepie.CK_ACV # AC Volt """ # Set trigger timeout: - self.scp.trigger_time_out = 1000e-3 # 100 ms + self.scp.trigger.timeout = 1000e-3 # 100 ms # Disable all channel trigger sources: for ch in self.scp.channels: @@ -218,24 +208,11 @@ def set_trigger(self): try: # Locate trigger input: - tr_sn = self.scp_list_sn[0] # First SN available - """ - print("Triggers: ") - for trigger_input in self.scp.trigger_inputs: - print(trigger_input.__getattribute__("id")) - print(trigger_input.__getattribute__("name")) - print(trigger_input.name.split(".")[-1]) - """ - for trigger_input in self.scp.trigger_inputs: - #print(trigger_input.name) - if trigger_input.name.split(".")[-1] == self.trigger_name: - if str(tr_sn) in trigger_input.name.split(".")[-1]: - break - - """ trigger_input = self.scp.trigger_inputs.get_by_id( libtiepie.TIID_GENERATOR_NEW_PERIOD) # or TIID_GENERATOR_START or TIID_GENERATOR_STOP - trigger_input = self.scp.trigger_inputs.get_by_id(35651586) + # Set trigger timeout: + self.scp.trigger.timeout = 1000e-3 # 100 ms + if trigger_input is None: raise Exception('Unknown trigger input!') except Exception as e: @@ -244,14 +221,9 @@ def set_trigger(self): #print(f"{trigger_input.id=} {trigger_input.name= }") if trigger_input.name.split(".")[-1] == self.trigger_name: break - """ - except Exception as e: - print("Error finding trigger") - print(e) # Enable trigger input: trigger_input.enabled = True - # print("Trigger input enabled: "+ str( trigger_input.enabled))