From b70048bc1fd8f161d5b9b91eed69d7f196f4952d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zoran=20D=2E=20Gruji=C4=87?= Date: Wed, 28 Jun 2023 13:58:42 +0200 Subject: [PATCH] Bias stabilisation in stream mode --- app.pyw | 21 +++++-- gui.py | 122 ++++++++++++++++++++----------------- gui.ui | 165 +++++++++++++++++++++++++++++---------------------- tiepieArb.py | 3 +- 4 files changed, 180 insertions(+), 131 deletions(-) diff --git a/app.pyw b/app.pyw index fe46200..0da2414 100644 --- a/app.pyw +++ b/app.pyw @@ -60,7 +60,7 @@ class MyUi(Ui_MainWindow): 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]) # 5,2 + decimationArr = np.array([5, 4]) # 5,2 countRemainingToSave = 0 @@ -289,7 +289,7 @@ class MyUi(Ui_MainWindow): def stabilizeProbeLevel(self): - print("Stab now!") + # print("Stab now!") # get current probe level if self.radioButton_PrStabSourceCH1.isChecked(): pos = 0 @@ -678,7 +678,7 @@ class MyUi(Ui_MainWindow): # drop = int((filterLength - 1) / 2) tstart = time.perf_counter() - fltr = signal.firwin(filterLength, filRange, pass_zero=pass_zero, fs=self.FITSampleRate / np.prod(self.decimationArr)) + fltr = signal.firwin(filterLength, filRange, window='hamming', 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') @@ -786,17 +786,23 @@ class MyUi(Ui_MainWindow): 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 + 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 += "C = {:.3e}\n".format(C) text += "cr = {:.1e} Hz\n".format(CramerRao) - 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 ({CramerRao_sh * 1e6/3.5:.1f})\n" + text += f"dB(FAP) = {CramerRao * 1e6/7.0:.1f} fT ({CramerRao_sh * 1e6/7.0:.1f})\n" self.plainTextEdit_SensitivityFFT.setPlainText(text) @@ -839,6 +845,11 @@ class MyUi(Ui_MainWindow): ) 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), frequency=1000 / float(self.doubleSpinBox_TotalTime_ms.value())): diff --git a/gui.py b/gui.py index 28d78ec..2386848 100644 --- a/gui.py +++ b/gui.py @@ -179,7 +179,7 @@ def setupUi(self, MainWindow): 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.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) @@ -244,7 +244,7 @@ def setupUi(self, MainWindow): self.doubleSpinBox_PumpLevel.setMinimum(-10.0) self.doubleSpinBox_PumpLevel.setMaximum(10.0) self.doubleSpinBox_PumpLevel.setSingleStep(0.01) - self.doubleSpinBox_PumpLevel.setProperty("value", 5.0) + self.doubleSpinBox_PumpLevel.setProperty("value", 4.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) @@ -368,26 +368,14 @@ def setupUi(self, MainWindow): self.verticalLayout_10.setObjectName("verticalLayout_10") self.gridLayout_9 = QtWidgets.QGridLayout() self.gridLayout_9.setObjectName("gridLayout_9") - 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.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_18 = QtWidgets.QLabel(self.groupBox_7) + 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_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_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.comboBox_FilterType = QtWidgets.QComboBox(self.groupBox_7) self.comboBox_FilterType.setObjectName("comboBox_FilterType") self.comboBox_FilterType.addItem("") @@ -396,14 +384,30 @@ def setupUi(self, MainWindow): self.comboBox_FilterType.addItem("") self.comboBox_FilterType.addItem("") self.gridLayout_9.addWidget(self.comboBox_FilterType, 0, 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.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_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) @@ -412,12 +416,22 @@ def setupUi(self, MainWindow): 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.label_25 = QtWidgets.QLabel(self.groupBox_7) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.label_25.sizePolicy().hasHeightForWidth()) + 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) + 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) self.label_24 = QtWidgets.QLabel(self.groupBox_7) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) @@ -426,20 +440,17 @@ 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_25 = 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_25.sizePolicy().hasHeightForWidth()) - self.label_25.setSizePolicy(sizePolicy) - self.label_25.setObjectName("label_25") - self.gridLayout_9.addWidget(self.label_25, 4, 0, 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) + 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) self.verticalLayout_10.addLayout(self.gridLayout_9) self.horizontalLayout_2.addWidget(self.groupBox_7) self.groupBox_8 = QtWidgets.QGroupBox(self.tab_FIT) @@ -764,7 +775,7 @@ def setupUi(self, MainWindow): self.doubleSpinBox_setBiasValue.setMinimum(-10.0) self.doubleSpinBox_setBiasValue.setMaximum(10.0) self.doubleSpinBox_setBiasValue.setSingleStep(0.01) - self.doubleSpinBox_setBiasValue.setProperty("value", 1.0) + self.doubleSpinBox_setBiasValue.setProperty("value", -1.0) 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) @@ -778,7 +789,7 @@ def setupUi(self, MainWindow): self.doubleSpinBox_setProbeValue.setMinimumSize(QtCore.QSize(200, 0)) self.doubleSpinBox_setProbeValue.setDecimals(3) self.doubleSpinBox_setProbeValue.setSingleStep(0.01) - self.doubleSpinBox_setProbeValue.setProperty("value", 0.7) + 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) @@ -868,7 +879,7 @@ def setupUi(self, MainWindow): self.menubar.addAction(self.menuFAP.menuAction()) self.retranslateUi(MainWindow) - self.tabWidget.setCurrentIndex(3) + self.tabWidget.setCurrentIndex(1) self.comboBox_SampleRate.setCurrentIndex(1) self.comboBox_CH2Range.setCurrentIndex(3) self.comboBox_CH1Range.setCurrentIndex(5) @@ -963,20 +974,23 @@ 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.doubleSpinBox_FilterStart_ms.setSuffix(_translate("MainWindow", " ms")) - self.doubleSpinBox_FilterStop_ms.setSuffix(_translate("MainWindow", " ms")) - self.label_18.setText(_translate("MainWindow", "Data start")) + self.label_17.setText(_translate("MainWindow", "Type")) 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.label_17.setText(_translate("MainWindow", "Type")) - self.label_19.setText(_translate("MainWindow", "Data stop")) + 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.label_24.setText(_translate("MainWindow", "FIT start")) + 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.doubleSpinBox_FITStop_ms.setSuffix(_translate("MainWindow", " ms")) + 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.groupBox_8.setTitle(_translate("MainWindow", "FIT initial parameters")) self.label_27.setText(_translate("MainWindow", "Fit src:")) self.radioButton_FITSource_CH1.setText(_translate("MainWindow", "CH1")) diff --git a/gui.ui b/gui.ui index ab4d773..4db97e2 100644 --- a/gui.ui +++ b/gui.ui @@ -22,7 +22,7 @@ - 3 + 0 @@ -410,7 +410,7 @@ 0.100000000000000 - 0.500000000000000 + 0.300000000000000 @@ -579,7 +579,7 @@ 0.010000000000000 - 5.000000000000000 + 4.000000000000000 @@ -884,40 +884,8 @@ - - - - ms - - - 1000.000000000000000 - - - 0.100000000000000 - - - 30.000000000000000 - - - - - - - ms - - - 1000.000000000000000 - - - 0.100000000000000 - - - 100.000000000000000 - - - - - + + 0 @@ -925,7 +893,7 @@ - Data start + Type @@ -961,29 +929,35 @@ - - - - - 0 - 0 - + + + + ms - - Type + + 1000.000000000000000 + + + 0.100000000000000 + + + 100.000000000000000 - - - - - 0 - 0 - + + + + ms - - Data stop + + 1000.000000000000000 + + + 0.100000000000000 + + + 100.000000000000000 @@ -1003,8 +977,24 @@ - - + + + + ms + + + 1000.000000000000000 + + + 0.100000000000000 + + + 30.000000000000000 + + + + + 0 @@ -1012,7 +1002,7 @@ - FIT start + Data stop @@ -1029,19 +1019,52 @@ - - - - ms + + + + + 0 + 0 + - - 1000.000000000000000 + + Data start - - 0.100000000000000 + + + + + + + 0 + 0 + - - 100.000000000000000 + + FIT start + + + + + + + + 0 + 0 + + + + Transimp. gain + + + + + + + Transimpedance gain [V/A] in scientific format. + + + 1e6 @@ -1851,7 +1874,7 @@ f: 2568.258 0.010000000000000 - 1.000000000000000 + -1.000000000000000 @@ -1893,7 +1916,7 @@ f: 2568.258 0.010000000000000 - 0.700000000000000 + 0.550000000000000 diff --git a/tiepieArb.py b/tiepieArb.py index d7d3de2..4cbba19 100644 --- a/tiepieArb.py +++ b/tiepieArb.py @@ -38,7 +38,8 @@ def arbLoad(self, arb, amplitude=1, frequency=10, offset=0.0): self.gen.frequency_mode = libtiepie.FM_SIGNALFREQUENCY # libtiepie.FM_SAMPLEFREQUENCY # Set sample frequency: - self.gen.frequency = frequency # 100 kHz + self.gen.frequency = frequency # 10 Hz + print(f"{frequency=}, {self.gen.frequency=}") # Set amplitude: self.gen.amplitude = amplitude # 2 V