- Unwrapping phase charts

- Sweeping of bands from the band list
pull/36/head
Rune Broberg 2019-10-03 14:17:04 +02:00
rodzic 8b93d3fb8d
commit 56ec60b2c9
3 zmienionych plików z 137 dodań i 34 usunięć

Wyświetl plik

@ -481,6 +481,10 @@ class PhaseChart(FrequencyChart):
self.minAngle = 0 self.minAngle = 0
self.maxAngle = 0 self.maxAngle = 0
self.span = 0 self.span = 0
self.unwrap = False
self.unwrappedData = []
self.unwrappedReference = []
self.minDisplayValue = -180 self.minDisplayValue = -180
self.maxDisplayValue = 180 self.maxDisplayValue = 180
@ -492,34 +496,22 @@ class PhaseChart(FrequencyChart):
self.setPalette(pal) self.setPalette(pal)
self.setAutoFillBackground(True) self.setAutoFillBackground(True)
self.y_menu.addSeparator()
self.action_unwrap = QtWidgets.QAction("Unwrap")
self.action_unwrap.setCheckable(True)
self.action_unwrap.triggered.connect(lambda: self.setUnwrap(self.action_unwrap.isChecked()))
self.y_menu.addAction(self.action_unwrap)
def setUnwrap(self, unwrap: bool):
self.unwrap = unwrap
self.update()
def drawChart(self, qp: QtGui.QPainter): def drawChart(self, qp: QtGui.QPainter):
qp.setPen(QtGui.QPen(self.textColor)) qp.setPen(QtGui.QPen(self.textColor))
qp.drawText(3, 15, self.name) qp.drawText(3, 15, self.name)
qp.setPen(QtGui.QPen(self.foregroundColor)) qp.setPen(QtGui.QPen(self.foregroundColor))
qp.drawLine(self.leftMargin, 20, self.leftMargin, self.topMargin+self.chartHeight+5) qp.drawLine(self.leftMargin, 20, self.leftMargin, self.topMargin+self.chartHeight+5)
qp.drawLine(self.leftMargin-5, self.topMargin+self.chartHeight, self.leftMargin+self.chartWidth, self.topMargin + self.chartHeight) qp.drawLine(self.leftMargin-5, self.topMargin+self.chartHeight, self.leftMargin+self.chartWidth, self.topMargin + self.chartHeight)
if self.fixedValues:
minAngle = self.minDisplayValue
maxAngle = self.maxDisplayValue
else:
minAngle = -180
maxAngle = 180
span = maxAngle-minAngle
self.minAngle = minAngle
self.maxAngle = maxAngle
self.span = span
step = math.floor(span/4)
for i in range(minAngle, maxAngle, step):
y = self.topMargin + round((maxAngle - i)/span*self.chartHeight)
if i != minAngle and i != maxAngle and (maxAngle - i) > step / 2:
qp.setPen(QtGui.QPen(self.textColor))
qp.drawText(3, y+3, str(i) + "°")
qp.setPen(QtGui.QPen(self.foregroundColor))
qp.drawLine(self.leftMargin - 5, y, self.leftMargin + self.chartWidth, y)
qp.drawLine(self.leftMargin - 5, self.topMargin, self.leftMargin + self.chartWidth, self.topMargin)
qp.setPen(self.textColor)
qp.drawText(3, 35, str(maxAngle) + "°")
qp.drawText(3, self.chartHeight+self.topMargin, str(minAngle) + "°")
def drawValues(self, qp: QtGui.QPainter): def drawValues(self, qp: QtGui.QPainter):
if len(self.data) == 0 and len(self.reference) == 0: if len(self.data) == 0 and len(self.reference) == 0:
@ -529,6 +521,50 @@ class PhaseChart(FrequencyChart):
line_pen = QtGui.QPen(self.sweepColor) line_pen = QtGui.QPen(self.sweepColor)
line_pen.setWidth(1) line_pen.setWidth(1)
if self.unwrap:
rawData = []
for d in self.data:
rawData.append(self.angle(d))
rawReference = []
for d in self.reference:
rawReference.append(self.angle(d))
self.unwrappedData = np.unwrap(rawData, 180)
self.unwrappedReference = np.unwrap(rawReference, 180)
if self.fixedValues:
minAngle = self.minDisplayValue
maxAngle = self.maxDisplayValue
elif self.unwrap and self.data:
minAngle = math.floor(np.min(self.unwrappedData))
maxAngle = math.ceil(np.max(self.unwrappedData))
elif self.unwrap and self.reference:
minAngle = math.floor(np.min(self.unwrappedReference))
maxAngle = math.ceil(np.max(self.unwrappedReference))
else:
minAngle = -180
maxAngle = 180
span = maxAngle - minAngle
self.minAngle = minAngle
self.maxAngle = maxAngle
self.span = span
step = math.floor(span / 4)
if step == 0:
step = 1
for i in range(minAngle, maxAngle, step):
y = self.topMargin + round((maxAngle - i) / span * self.chartHeight)
if i != minAngle and i != maxAngle and (maxAngle - i) > step / 2:
qp.setPen(QtGui.QPen(self.textColor))
qp.drawText(3, y + 3, str(i) + "°")
qp.setPen(QtGui.QPen(self.foregroundColor))
qp.drawLine(self.leftMargin - 5, y, self.leftMargin + self.chartWidth, y)
qp.drawLine(self.leftMargin - 5, self.topMargin, self.leftMargin + self.chartWidth, self.topMargin)
qp.setPen(self.textColor)
qp.drawText(3, 35, str(maxAngle) + "°")
qp.drawText(3, self.chartHeight + self.topMargin, str(minAngle) + "°")
if self.fixedSpan: if self.fixedSpan:
fstart = self.minFrequency fstart = self.minFrequency
fstop = self.maxFrequency fstop = self.maxFrequency
@ -562,7 +598,15 @@ class PhaseChart(FrequencyChart):
self.drawMarkers(qp) self.drawMarkers(qp)
def getYPosition(self, d: Datapoint) -> int: def getYPosition(self, d: Datapoint) -> int:
angle = self.angle(d) if self.unwrap:
if d in self.data:
angle = self.unwrappedData[self.data.index(d)]
elif d in self.reference:
angle = self.unwrappedReference[self.reference.index(d)]
else:
angle = self.angle(d)
else:
angle = self.angle(d)
return 30 + round((self.maxAngle - angle) / self.span * self.chartHeight) return 30 + round((self.maxAngle - angle) / self.span * self.chartHeight)
@staticmethod @staticmethod

Wyświetl plik

@ -207,7 +207,7 @@ class NanoVNASaver(QtWidgets.QWidget):
sweep_control_layout.addRow(QtWidgets.QLabel("Segments"), segment_layout) sweep_control_layout.addRow(QtWidgets.QLabel("Segments"), segment_layout)
self.sweepSettingsWindow = SweepSettingsWindow(self) self.sweepSettingsWindow = SweepSettingsWindow(self)
btn_sweep_settings_window = QtWidgets.QPushButton("Sweep settings") btn_sweep_settings_window = QtWidgets.QPushButton("Sweep settings ...")
btn_sweep_settings_window.clicked.connect(self.displaySweepSettingsWindow) btn_sweep_settings_window.clicked.connect(self.displaySweepSettingsWindow)
sweep_control_layout.addRow(btn_sweep_settings_window) sweep_control_layout.addRow(btn_sweep_settings_window)
@ -1562,31 +1562,90 @@ class SweepSettingsWindow(QtWidgets.QWidget):
shortcut = QtWidgets.QShortcut(QtCore.Qt.Key_Escape, self, self.hide) shortcut = QtWidgets.QShortcut(QtCore.Qt.Key_Escape, self, self.hide)
layout = QtWidgets.QFormLayout() layout = QtWidgets.QVBoxLayout()
self.setLayout(layout) self.setLayout(layout)
settings_box = QtWidgets.QGroupBox("Settings")
settings_layout = QtWidgets.QFormLayout(settings_box)
self.single_sweep_radiobutton = QtWidgets.QRadioButton("Single sweep") self.single_sweep_radiobutton = QtWidgets.QRadioButton("Single sweep")
self.continuous_sweep_radiobutton = QtWidgets.QRadioButton("Continuous sweep") self.continuous_sweep_radiobutton = QtWidgets.QRadioButton("Continuous sweep")
self.averaged_sweep_radiobutton = QtWidgets.QRadioButton("Averaged sweep") self.averaged_sweep_radiobutton = QtWidgets.QRadioButton("Averaged sweep")
layout.addWidget(self.single_sweep_radiobutton) settings_layout.addWidget(self.single_sweep_radiobutton)
self.single_sweep_radiobutton.setChecked(True) self.single_sweep_radiobutton.setChecked(True)
layout.addWidget(self.continuous_sweep_radiobutton) settings_layout.addWidget(self.continuous_sweep_radiobutton)
layout.addWidget(self.averaged_sweep_radiobutton) settings_layout.addWidget(self.averaged_sweep_radiobutton)
self.averages = QtWidgets.QLineEdit("3") self.averages = QtWidgets.QLineEdit("3")
self.truncates = QtWidgets.QLineEdit("0") self.truncates = QtWidgets.QLineEdit("0")
layout.addRow("Number of measurements to average", self.averages) settings_layout.addRow("Number of measurements to average", self.averages)
layout.addRow("Number to discard", self.truncates) settings_layout.addRow("Number to discard", self.truncates)
layout.addRow(QtWidgets.QLabel("Averaging allows discarding outlying samples to get better averages.")) settings_layout.addRow(QtWidgets.QLabel("Averaging allows discarding outlying samples to get better averages."))
layout.addRow(QtWidgets.QLabel("Common values are 3/0, 5/2, 9/4 and 25/6.")) settings_layout.addRow(QtWidgets.QLabel("Common values are 3/0, 5/2, 9/4 and 25/6."))
self.continuous_sweep_radiobutton.toggled.connect(lambda: self.app.worker.setContinuousSweep(self.continuous_sweep_radiobutton.isChecked())) self.continuous_sweep_radiobutton.toggled.connect(lambda: self.app.worker.setContinuousSweep(self.continuous_sweep_radiobutton.isChecked()))
self.averaged_sweep_radiobutton.toggled.connect(self.updateAveraging) self.averaged_sweep_radiobutton.toggled.connect(self.updateAveraging)
self.averages.textEdited.connect(self.updateAveraging) self.averages.textEdited.connect(self.updateAveraging)
self.truncates.textEdited.connect(self.updateAveraging) self.truncates.textEdited.connect(self.updateAveraging)
layout.addWidget(settings_box)
band_sweep_box = QtWidgets.QGroupBox("Sweep band")
band_sweep_layout = QtWidgets.QFormLayout(band_sweep_box)
self.band_list = QtWidgets.QComboBox()
self.band_list.setModel(self.app.bands)
self.band_list.currentIndexChanged.connect(self.updateCurrentBand)
band_sweep_layout.addRow("Select band", self.band_list)
self.band_pad_limits = QtWidgets.QCheckBox("Pad band limits (10%)")
self.band_pad_limits.stateChanged.connect(self.updateCurrentBand)
band_sweep_layout.addRow(self.band_pad_limits)
self.band_limit_label = QtWidgets.QLabel()
band_sweep_layout.addRow(self.band_limit_label)
btn_set_band_sweep = QtWidgets.QPushButton("Set band sweep")
btn_set_band_sweep.clicked.connect(self.setBandSweep)
band_sweep_layout.addRow(btn_set_band_sweep)
self.updateCurrentBand()
layout.addWidget(band_sweep_box)
def updateCurrentBand(self):
index_start = self.band_list.model().index(self.band_list.currentIndex(), 1)
index_stop = self.band_list.model().index(self.band_list.currentIndex(), 2)
start = int(self.band_list.model().data(index_start, QtCore.Qt.ItemDataRole).value())
stop = int(self.band_list.model().data(index_stop, QtCore.Qt.ItemDataRole).value())
if self.band_pad_limits.isChecked():
span = stop - start
start -= round(span / 10)
stop += round(span / 10)
self.band_limit_label.setText("Sweep span: " + NanoVNASaver.formatShortFrequency(start) + " to " +
NanoVNASaver.formatShortFrequency(stop))
def setBandSweep(self):
index_start = self.band_list.model().index(self.band_list.currentIndex(), 1)
index_stop = self.band_list.model().index(self.band_list.currentIndex(), 2)
start = int(self.band_list.model().data(index_start, QtCore.Qt.ItemDataRole).value())
stop = int(self.band_list.model().data(index_stop, QtCore.Qt.ItemDataRole).value())
if self.band_pad_limits.isChecked():
span = stop - start
start -= round(span / 10)
stop += round(span / 10)
self.app.sweepStartInput.setText(str(start))
self.app.sweepEndInput.setText(str(stop))
self.app.sweepEndInput.textEdited.emit(self.app.sweepEndInput.text())
def updateAveraging(self): def updateAveraging(self):
self.app.worker.setAveraging(self.averaged_sweep_radiobutton.isChecked(), self.app.worker.setAveraging(self.averaged_sweep_radiobutton.isChecked(),
self.averages.text(), self.averages.text(),

Wyświetl plik

@ -14,5 +14,5 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
version = '0.1.0' version = '0.1.1alpha'
debug = False debug = True