Min. / Max. peak hold; recalculate curves from history; separate data backend; refactoring

This commit is contained in:
Michal Krenek (Mikos) 2016-05-17 02:37:06 +02:00
parent 53f5775ae4
commit 7112ce7888
9 changed files with 695 additions and 323 deletions

View File

@ -6,6 +6,7 @@ from PyQt4 import QtCore, QtGui
from qspectrumanalyzer.version import __version__
from qspectrumanalyzer.backend import RtlPowerThread, RtlPowerFftwThread
from qspectrumanalyzer.data import DataStorage
from qspectrumanalyzer.plot import SpectrumPlotWidget, WaterfallPlotWidget
from qspectrumanalyzer.utils import color_to_str, str_to_color
@ -124,7 +125,8 @@ class QSpectrumAnalyzerColors(QtGui.QDialog, Ui_QSpectrumAnalyzerColors):
# Load settings
settings = QtCore.QSettings()
self.mainColorButton.setColor(str_to_color(settings.value("main_color", "255, 255, 0, 255")))
self.peakHoldColorButton.setColor(str_to_color(settings.value("peak_hold_color", "255, 0, 0, 255")))
self.peakHoldMaxColorButton.setColor(str_to_color(settings.value("peak_hold_max_color", "255, 0, 0, 255")))
self.peakHoldMinColorButton.setColor(str_to_color(settings.value("peak_hold_min_color", "0, 0, 255, 255")))
self.averageColorButton.setColor(str_to_color(settings.value("average_color", "0, 255, 255, 255")))
self.persistenceColorButton.setColor(str_to_color(settings.value("persistence_color", "0, 255, 0, 255")))
@ -132,7 +134,8 @@ class QSpectrumAnalyzerColors(QtGui.QDialog, Ui_QSpectrumAnalyzerColors):
"""Save settings when dialog is accepted"""
settings = QtCore.QSettings()
settings.setValue("main_color", color_to_str(self.mainColorButton.color()))
settings.setValue("peak_hold_color", color_to_str(self.peakHoldColorButton.color()))
settings.setValue("peak_hold_max_color", color_to_str(self.peakHoldMaxColorButton.color()))
settings.setValue("peak_hold_min_color", color_to_str(self.peakHoldMinColorButton.color()))
settings.setValue("average_color", color_to_str(self.averageColorButton.color()))
settings.setValue("persistence_color", color_to_str(self.persistenceColorButton.color()))
QtGui.QDialog.accept(self)
@ -145,11 +148,6 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin
super().__init__(parent)
self.setupUi(self)
# Setup rtl_power thread and connect signals
self.prev_data_timestamp = None
self.rtl_power_thread = None
self.setup_rtl_power_thread()
# Create plot widgets and update UI
self.spectrumPlotWidget = SpectrumPlotWidget(self.mainPlotLayout)
self.waterfallPlotWidget = WaterfallPlotWidget(self.waterfallPlotLayout, self.histogramPlotLayout)
@ -157,6 +155,12 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin
# Link main spectrum plot to waterfall plot
self.spectrumPlotWidget.plot.setXLink(self.waterfallPlotWidget.plot)
# Setup rtl_power thread and connect signals
self.prev_data_timestamp = None
self.data_storage = None
self.rtl_power_thread = None
self.setup_rtl_power_thread()
self.update_buttons()
self.load_settings()
@ -166,13 +170,23 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin
self.stop()
settings = QtCore.QSettings()
self.data_storage = DataStorage(max_history_size=settings.value("waterfall_history_size", 100, int))
self.data_storage.data_updated.connect(self.update_data)
self.data_storage.data_updated.connect(self.spectrumPlotWidget.update_plot)
self.data_storage.data_updated.connect(self.spectrumPlotWidget.update_persistence)
self.data_storage.data_recalculated.connect(self.spectrumPlotWidget.recalculate_plot)
self.data_storage.data_recalculated.connect(self.spectrumPlotWidget.recalculate_persistence)
self.data_storage.history_updated.connect(self.waterfallPlotWidget.update_plot)
self.data_storage.average_updated.connect(self.spectrumPlotWidget.update_average)
self.data_storage.peak_hold_max_updated.connect(self.spectrumPlotWidget.update_peak_hold_max)
self.data_storage.peak_hold_min_updated.connect(self.spectrumPlotWidget.update_peak_hold_min)
backend = settings.value("backend", "rtl_power")
if backend == "rtl_power_fftw":
self.rtl_power_thread = RtlPowerFftwThread()
self.rtl_power_thread = RtlPowerFftwThread(self.data_storage)
else:
self.rtl_power_thread = RtlPowerThread()
self.rtl_power_thread = RtlPowerThread(self.data_storage)
self.rtl_power_thread.dataUpdated.connect(self.update_data)
self.rtl_power_thread.rtlPowerStarted.connect(self.update_buttons)
self.rtl_power_thread.rtlPowerStopped.connect(self.update_buttons)
@ -212,7 +226,8 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin
self.ppmSpinBox.setValue(settings.value("ppm", 0, int))
self.cropSpinBox.setValue(settings.value("crop", 0, int))
self.mainCurveCheckBox.setChecked(settings.value("main_curve", 1, int))
self.peakHoldCheckBox.setChecked(settings.value("peak_hold", 0, int))
self.peakHoldMaxCheckBox.setChecked(settings.value("peak_hold_max", 0, int))
self.peakHoldMinCheckBox.setChecked(settings.value("peak_hold_min", 0, int))
self.averageCheckBox.setChecked(settings.value("average", 0, int))
self.smoothCheckBox.setChecked(settings.value("smooth", 0, int))
self.persistenceCheckBox.setChecked(settings.value("persistence", 0, int))
@ -250,7 +265,8 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin
settings.setValue("ppm", self.ppmSpinBox.value())
settings.setValue("crop", self.cropSpinBox.value())
settings.setValue("main_curve", int(self.mainCurveCheckBox.isChecked()))
settings.setValue("peak_hold", int(self.peakHoldCheckBox.isChecked()))
settings.setValue("peak_hold_max", int(self.peakHoldMaxCheckBox.isChecked()))
settings.setValue("peak_hold_min", int(self.peakHoldMinCheckBox.isChecked()))
settings.setValue("average", int(self.averageCheckBox.isChecked()))
settings.setValue("smooth", int(self.smoothCheckBox.isChecked()))
settings.setValue("persistence", int(self.persistenceCheckBox.isChecked()))
@ -270,45 +286,55 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin
self.singleShotButton.setEnabled(not self.rtl_power_thread.alive)
self.stopButton.setEnabled(self.rtl_power_thread.alive)
def update_data(self, data):
"""Update plots when new data is received"""
self.waterfallPlotWidget.update_plot(data)
self.spectrumPlotWidget.update_plot(data)
def update_data(self, data_storage):
"""Update GUI when new data is received"""
# Show number of hops and how much time did the sweep really take
timestamp = time.time()
self.show_status(self.tr("Frequency hops: {} Sweep time: {:.2f} s").format(
self.rtl_power_thread.params["hops"] or self.tr("N/A"),
timestamp - self.prev_data_timestamp
), timeout=0)
sweep_time = timestamp - self.prev_data_timestamp
self.prev_data_timestamp = timestamp
self.show_status(
self.tr("Frequency hops: {} | Sweep time: {:.2f} s | FPS: {:.2f}").format(
self.rtl_power_thread.params["hops"] or self.tr("N/A"),
sweep_time,
1 / sweep_time
),
timeout=0
)
def start(self, single_shot=False):
"""Start rtl_power thread"""
settings = QtCore.QSettings()
self.prev_data_timestamp = time.time()
self.waterfallPlotWidget.counter = 0
self.waterfallPlotWidget.history_size = settings.value("waterfall_history_size", 100, int)
self.data_storage.reset()
self.data_storage.set_smooth(
bool(self.smoothCheckBox.isChecked()),
settings.value("smooth_length", 11, int),
settings.value("smooth_window", "hanning"),
recalculate=False
)
self.waterfallPlotWidget.history_size = settings.value("waterfall_history_size", 100, int)
self.waterfallPlotWidget.clear_plot()
self.spectrumPlotWidget.counter = 0
self.spectrumPlotWidget.main_curve = bool(self.mainCurveCheckBox.isChecked())
self.spectrumPlotWidget.main_color = str_to_color(settings.value("main_color", "255, 255, 0, 255"))
self.spectrumPlotWidget.peak_hold = bool(self.peakHoldCheckBox.isChecked())
self.spectrumPlotWidget.peak_hold_color = str_to_color(settings.value("peak_hold_color", "255, 0, 0, 255"))
self.spectrumPlotWidget.peak_hold_max = bool(self.peakHoldMaxCheckBox.isChecked())
self.spectrumPlotWidget.peak_hold_max_color = str_to_color(settings.value("peak_hold_max_color", "255, 0, 0, 255"))
self.spectrumPlotWidget.peak_hold_min = bool(self.peakHoldMinCheckBox.isChecked())
self.spectrumPlotWidget.peak_hold_min_color = str_to_color(settings.value("peak_hold_min_color", "0, 0, 255, 255"))
self.spectrumPlotWidget.average = bool(self.averageCheckBox.isChecked())
self.spectrumPlotWidget.average_color = str_to_color(settings.value("average_color", "0, 255, 255, 255"))
self.spectrumPlotWidget.persistence = bool(self.persistenceCheckBox.isChecked())
self.spectrumPlotWidget.persistence_length = settings.value("persistence_length", 5, int)
self.spectrumPlotWidget.persistence_decay = settings.value("persistence_decay", "exponential")
self.spectrumPlotWidget.persistence_color = str_to_color(settings.value("persistence_color", "0, 255, 0, 255"))
self.spectrumPlotWidget.smooth = bool(self.smoothCheckBox.isChecked())
self.spectrumPlotWidget.smooth_length = settings.value("smooth_length", 11, int)
self.spectrumPlotWidget.smooth_window = settings.value("smooth_window", "hanning")
self.spectrumPlotWidget.main_clear()
self.spectrumPlotWidget.peak_hold_clear()
self.spectrumPlotWidget.average_clear()
self.spectrumPlotWidget.persistence_clear()
self.spectrumPlotWidget.clear_plot()
self.spectrumPlotWidget.clear_peak_hold_max()
self.spectrumPlotWidget.clear_peak_hold_min()
self.spectrumPlotWidget.clear_average()
self.spectrumPlotWidget.clear_persistence()
if not self.rtl_power_thread.alive:
self.rtl_power_thread.setup(float(self.startFreqSpinBox.value()),
@ -342,46 +368,60 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin
@QtCore.pyqtSlot(bool)
def on_mainCurveCheckBox_toggled(self, checked):
self.spectrumPlotWidget.main_curve = checked
if not checked:
self.spectrumPlotWidget.main_clear()
if self.spectrumPlotWidget.curve.xData is None:
self.spectrumPlotWidget.update_plot(self.data_storage)
self.spectrumPlotWidget.curve.setVisible(checked)
@QtCore.pyqtSlot(bool)
def on_peakHoldCheckBox_toggled(self, checked):
self.spectrumPlotWidget.peak_hold = checked
if not checked:
self.spectrumPlotWidget.peak_hold_clear()
def on_peakHoldMaxCheckBox_toggled(self, checked):
self.spectrumPlotWidget.peak_hold_max = checked
if self.spectrumPlotWidget.curve_peak_hold_max.xData is None:
self.spectrumPlotWidget.update_peak_hold_max(self.data_storage)
self.spectrumPlotWidget.curve_peak_hold_max.setVisible(checked)
@QtCore.pyqtSlot(bool)
def on_peakHoldMinCheckBox_toggled(self, checked):
self.spectrumPlotWidget.peak_hold_min = checked
if self.spectrumPlotWidget.curve_peak_hold_min.xData is None:
self.spectrumPlotWidget.update_peak_hold_min(self.data_storage)
self.spectrumPlotWidget.curve_peak_hold_min.setVisible(checked)
@QtCore.pyqtSlot(bool)
def on_averageCheckBox_toggled(self, checked):
self.spectrumPlotWidget.average = checked
if not checked:
self.spectrumPlotWidget.average_clear()
@QtCore.pyqtSlot(bool)
def on_smoothCheckBox_toggled(self, checked):
self.spectrumPlotWidget.smooth = checked
self.spectrumPlotWidget.main_clear()
self.spectrumPlotWidget.peak_hold_clear()
self.spectrumPlotWidget.average_clear()
self.spectrumPlotWidget.persistence_clear()
if self.spectrumPlotWidget.curve_average.xData is None:
self.spectrumPlotWidget.update_average(self.data_storage)
self.spectrumPlotWidget.curve_average.setVisible(checked)
@QtCore.pyqtSlot(bool)
def on_persistenceCheckBox_toggled(self, checked):
self.spectrumPlotWidget.persistence = checked
if not checked:
self.spectrumPlotWidget.persistence_clear()
if self.spectrumPlotWidget.persistence_curves[0].xData is None:
self.spectrumPlotWidget.recalculate_persistence(self.data_storage)
for curve in self.spectrumPlotWidget.persistence_curves:
curve.setVisible(checked)
@QtCore.pyqtSlot(bool)
def on_smoothCheckBox_toggled(self, checked):
settings = QtCore.QSettings()
self.data_storage.set_smooth(
checked,
settings.value("smooth_length", 11, int),
settings.value("smooth_window", "hanning"),
recalculate=True
)
@QtCore.pyqtSlot()
def on_smoothButton_clicked(self):
dialog = QSpectrumAnalyzerSmooth(self)
if dialog.exec_():
settings = QtCore.QSettings()
self.spectrumPlotWidget.smooth_length = settings.value("smooth_length", 11, int)
self.spectrumPlotWidget.smooth_window = settings.value("smooth_window", "hanning")
self.spectrumPlotWidget.main_clear()
self.spectrumPlotWidget.peak_hold_clear()
self.spectrumPlotWidget.average_clear()
self.spectrumPlotWidget.persistence_clear()
self.data_storage.set_smooth(
bool(self.smoothCheckBox.isChecked()),
settings.value("smooth_length", 11, int),
settings.value("smooth_window", "hanning"),
recalculate=True
)
@QtCore.pyqtSlot()
def on_persistenceButton_clicked(self):
@ -397,7 +437,7 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin
if persistence_length == prev_persistence_length:
self.spectrumPlotWidget.set_colors()
else:
self.spectrumPlotWidget.persistence_clear()
self.spectrumPlotWidget.recalculate_persistence(self.data_storage)
@QtCore.pyqtSlot()
def on_colorsButton_clicked(self):
@ -405,7 +445,8 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin
if dialog.exec_():
settings = QtCore.QSettings()
self.spectrumPlotWidget.main_color = str_to_color(settings.value("main_color", "255, 255, 0, 255"))
self.spectrumPlotWidget.peak_hold_color = str_to_color(settings.value("peak_hold_color", "255, 0, 0, 255"))
self.spectrumPlotWidget.peak_hold_max_color = str_to_color(settings.value("peak_hold_max_color", "255, 0, 0, 255"))
self.spectrumPlotWidget.peak_hold_min_color = str_to_color(settings.value("peak_hold_min_color", "0, 0, 255, 255"))
self.spectrumPlotWidget.average_color = str_to_color(settings.value("average_color", "0, 255, 255, 255"))
self.spectrumPlotWidget.persistence_color = str_to_color(settings.value("persistence_color", "0, 255, 0, 255"))
self.spectrumPlotWidget.set_colors()

View File

@ -6,12 +6,12 @@ from PyQt4 import QtCore
class RtlPowerBaseThread(QtCore.QThread):
"""Thread which runs rtl_power process"""
dataUpdated = QtCore.pyqtSignal(object)
rtlPowerStarted = QtCore.pyqtSignal()
rtlPowerStopped = QtCore.pyqtSignal()
def __init__(self, parent=None):
def __init__(self, data_storage, parent=None):
super().__init__(parent)
self.data_storage = data_storage
self.alive = False
self.process = None
@ -137,7 +137,7 @@ class RtlPowerThread(RtlPowerBaseThread):
# This have to be stupid like this to be compatible with old broken version of rtl_power. Right way is:
# if stop_freq == self.params["stop_freq"] * 1e6:
if stop_freq > (self.params["stop_freq"] * 1e6) - step:
self.dataUpdated.emit(self.databuffer)
self.data_storage.update(self.databuffer)
class RtlPowerFftwThread(RtlPowerBaseThread):
@ -227,7 +227,7 @@ class RtlPowerFftwThread(RtlPowerBaseThread):
# Two empty lines => new set
elif not line and not self.prev_line:
self.hop = 0
self.dataUpdated.emit(self.databuffer)
self.data_storage.update(self.databuffer)
self.databuffer = {"timestamp": [], "x": [], "y": []}
# Get timestamp for new hop and set

233
qspectrumanalyzer/data.py Normal file
View File

@ -0,0 +1,233 @@
import time, sys
from PyQt4 import QtCore
import numpy as np
from qspectrumanalyzer.utils import smooth
class HistoryBuffer:
"""Fixed-size NumPy array ring buffer"""
def __init__(self, data_size, max_history_size, dtype=float):
self.data_size = data_size
self.max_history_size = max_history_size
self.history_size = 0
self.counter = 0
self.buffer = np.empty(shape=(max_history_size, data_size), dtype=dtype)
def append(self, data):
"""Append new data to ring buffer"""
self.counter += 1
if self.history_size < self.max_history_size:
self.history_size += 1
self.buffer = np.roll(self.buffer, -1, axis=0)
self.buffer[-1] = data
def get_buffer(self):
"""Return buffer stripped to size of actual data"""
if self.history_size < self.max_history_size:
return self.buffer[-self.history_size:]
else:
return self.buffer
def __getitem__(self, key):
return self.buffer[key]
class TaskSignals(QtCore.QObject):
"""Task signals emitter"""
result = QtCore.pyqtSignal(object)
class Task(QtCore.QRunnable):
"""Threaded task (run it with QThreadPool worker threads)"""
def __init__(self, task, *args, **kwargs):
super().__init__()
self.task = task
self.args = args
self.kwargs = kwargs
self.signals = TaskSignals()
def run(self):
"""Run task in worker thread and emit signal with result"""
#print('Running', self.task, 'in thread', QtCore.QThread.currentThreadId())
result = self.task(*self.args, **self.kwargs)
self.signals.result.emit(result)
class DataStorage(QtCore.QObject):
"""Data storage for spectrum measurements"""
history_updated = QtCore.pyqtSignal(object)
data_updated = QtCore.pyqtSignal(object)
data_recalculated = QtCore.pyqtSignal(object)
average_updated = QtCore.pyqtSignal(object)
peak_hold_max_updated = QtCore.pyqtSignal(object)
peak_hold_min_updated = QtCore.pyqtSignal(object)
def __init__(self, max_history_size=100, parent=None):
super().__init__(parent)
self.max_history_size = max_history_size
self.smooth = False
self.smooth_length = 11
self.smooth_window = "hanning"
# Use only one worker thread because it is not faster
# with more threads (and memory consumption is much higher)
self.threadpool = QtCore.QThreadPool()
self.threadpool.setMaxThreadCount(1)
self.reset()
def reset(self):
"""Reset all data"""
self.wait()
self.x = None
self.history = None
self.reset_data()
def reset_data(self):
"""Reset current data"""
self.wait()
self.y = None
self.average_counter = 0
self.average = None
self.peak_hold_max = None
self.peak_hold_min = None
def start_task(self, fn, *args, **kwargs):
"""Run function asynchronously in worker thread"""
task = Task(fn, *args, **kwargs)
self.threadpool.start(task)
def wait(self):
"""Wait for worker threads to complete all running tasks"""
self.threadpool.waitForDone()
def update(self, data):
"""Update data storage"""
self.average_counter += 1
if self.x is None:
self.x = data["x"]
self.start_task(self.update_history, data.copy())
self.start_task(self.update_data, data)
def update_data(self, data):
"""Update main spectrum data (and possibly apply smoothing)"""
if self.smooth:
data["y"] = self.smooth_data(data["y"])
self.y = data["y"]
self.data_updated.emit(self)
self.start_task(self.update_average, data)
self.start_task(self.update_peak_hold_max, data)
self.start_task(self.update_peak_hold_min, data)
def update_history(self, data):
"""Update spectrum measurements history"""
if self.history is None:
self.history = HistoryBuffer(len(data["y"]), self.max_history_size)
self.history.append(data["y"])
self.history_updated.emit(self)
def update_average(self, data):
"""Update average data"""
if self.average is None:
self.average = data["y"].copy()
else:
self.average = np.average((self.average, data["y"]), axis=0, weights=(self.average_counter - 1, 1))
self.average_updated.emit(self)
def update_peak_hold_max(self, data):
"""Update max. peak hold data"""
if self.peak_hold_max is None:
self.peak_hold_max = data["y"].copy()
else:
self.peak_hold_max = np.maximum(self.peak_hold_max, data["y"])
self.peak_hold_max_updated.emit(self)
def update_peak_hold_min(self, data):
"""Update min. peak hold data"""
if self.peak_hold_min is None:
self.peak_hold_min = data["y"].copy()
else:
self.peak_hold_min = np.minimum(self.peak_hold_min, data["y"])
self.peak_hold_min_updated.emit(self)
def smooth_data(self, y):
"""Apply smoothing function to data"""
return smooth(y, window_len=self.smooth_length, window=self.smooth_window)
def set_smooth(self, toggle, length=11, window="hanning", recalculate=False):
"""Toggle smoothing and set smoothing params"""
if toggle != self.smooth or length != self.smooth_length or window != self.smooth_window:
self.smooth = toggle
self.smooth_length = length
self.smooth_window = window
if recalculate:
self.start_task(self.recalculate_data)
else:
self.reset_data()
def recalculate_data(self):
"""Recalculate current data from history"""
if self.history is None:
return
history = self.history.get_buffer()
if self.smooth:
self.y = self.smooth_data(history[-1])
self.average_counter = 0
self.average = self.y.copy()
self.peak_hold_max = self.y.copy()
self.peak_hold_min = self.y.copy()
for y in history[:-1]:
self.average_counter += 1
y = self.smooth_data(y)
self.average = np.average((self.average, y), axis=0, weights=(self.average_counter - 1, 1))
self.peak_hold_max = np.maximum(self.peak_hold_max, y)
self.peak_hold_min = np.minimum(self.peak_hold_min, y)
else:
self.y = history[-1]
self.average_counter = self.history.history_size
self.average = np.average(history, axis=0)
self.peak_hold_max = history.max(axis=0)
self.peak_hold_min = history.min(axis=0)
self.data_recalculated.emit(self)
#self.data_updated.emit({"x": self.x, "y": self.y})
#self.average_updated.emit({"x": self.x, "y": self.average})
#self.peak_hold_max_updated.emit({"x": self.x, "y": self.peak_hold_max})
#self.peak_hold_min_updated.emit({"x": self.x, "y": self.peak_hold_min})
class Test:
"""Test data storage performance"""
def __init__(self, data_size=100000, max_history_size=100):
self.data_size = data_size
self.data = {"x": np.arange(data_size),
"y": None}
self.datastorage = DataStorage(max_history_size)
def run_one(self):
"""Generate random data and update data storage"""
self.data["y"] = np.random.normal(size=self.data_size)
self.datastorage.update(self.data)
def run(self, runs=1000):
"""Run performance test"""
t = time.time()
for i in range(runs):
self.run_one()
self.datastorage.wait()
total_time = time.time() - t
print("Total time:", total_time)
print("FPS:", runs / total_time)
if __name__ == "__main__":
test = Test(int(sys.argv[1]), int(sys.argv[2]))
test.run(int(sys.argv[3]))

View File

@ -3,213 +3,223 @@
<context>
<name>QSpectrumAnalyzerColors</name>
<message>
<location filename="ui_qspectrumanalyzer_colors.py" line="100"/>
<location filename="ui_qspectrumanalyzer_colors.py" line="113"/>
<source>Colors - QSpectrumAnalyzer</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer_colors.py" line="101"/>
<location filename="ui_qspectrumanalyzer_colors.py" line="114"/>
<source>Main curve color:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer_colors.py" line="108"/>
<location filename="ui_qspectrumanalyzer_colors.py" line="123"/>
<source>...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer_colors.py" line="103"/>
<source>Peak hold color:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer_colors.py" line="105"/>
<location filename="ui_qspectrumanalyzer_colors.py" line="120"/>
<source>Average color:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer_colors.py" line="107"/>
<location filename="ui_qspectrumanalyzer_colors.py" line="122"/>
<source>Persistence color:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer_colors.py" line="116"/>
<source>Max. peak hold color:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer_colors.py" line="118"/>
<source>Min. peak hold color:</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QSpectrumAnalyzerMainWindow</name>
<message>
<location filename="ui_qspectrumanalyzer.py" line="303"/>
<location filename="ui_qspectrumanalyzer.py" line="307"/>
<source>QSpectrumAnalyzer</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="317"/>
<location filename="ui_qspectrumanalyzer.py" line="321"/>
<source>Settings</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="314"/>
<location filename="ui_qspectrumanalyzer.py" line="318"/>
<source> MHz</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="316"/>
<location filename="ui_qspectrumanalyzer.py" line="320"/>
<source> kHz</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="326"/>
<location filename="ui_qspectrumanalyzer.py" line="324"/>
<source>auto</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="310"/>
<location filename="ui_qspectrumanalyzer.py" line="314"/>
<source>Frequency</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="306"/>
<location filename="ui_qspectrumanalyzer.py" line="310"/>
<source>Controls</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="331"/>
<location filename="ui_qspectrumanalyzer.py" line="336"/>
<source>Levels</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="__main__.py" line="421"/>
<location filename="__main__.py" line="462"/>
<source>QSpectrumAnalyzer {}</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="304"/>
<location filename="ui_qspectrumanalyzer.py" line="308"/>
<source>&amp;File</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="305"/>
<location filename="ui_qspectrumanalyzer.py" line="309"/>
<source>&amp;Help</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="307"/>
<location filename="ui_qspectrumanalyzer.py" line="311"/>
<source>&amp;Start</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="308"/>
<location filename="ui_qspectrumanalyzer.py" line="312"/>
<source>S&amp;top</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="309"/>
<location filename="ui_qspectrumanalyzer.py" line="313"/>
<source>Si&amp;ngle shot</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="332"/>
<location filename="ui_qspectrumanalyzer.py" line="337"/>
<source>&amp;Settings...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="333"/>
<location filename="ui_qspectrumanalyzer.py" line="338"/>
<source>&amp;Quit</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="334"/>
<location filename="ui_qspectrumanalyzer.py" line="339"/>
<source>Ctrl+Q</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="335"/>
<location filename="ui_qspectrumanalyzer.py" line="340"/>
<source>&amp;About</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="318"/>
<location filename="ui_qspectrumanalyzer.py" line="322"/>
<source>Interval [s]:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="319"/>
<location filename="ui_qspectrumanalyzer.py" line="323"/>
<source>Gain [dB]:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="320"/>
<location filename="ui_qspectrumanalyzer.py" line="325"/>
<source>Corr. [ppm]:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="321"/>
<location filename="ui_qspectrumanalyzer.py" line="326"/>
<source>Crop [%]:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="311"/>
<location filename="ui_qspectrumanalyzer.py" line="315"/>
<source>Start:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="313"/>
<location filename="ui_qspectrumanalyzer.py" line="317"/>
<source>Stop:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="315"/>
<location filename="ui_qspectrumanalyzer.py" line="319"/>
<source>Bin size:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="323"/>
<source>Peak hold</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="324"/>
<location filename="ui_qspectrumanalyzer.py" line="332"/>
<source>Smoothing</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="329"/>
<location filename="ui_qspectrumanalyzer.py" line="335"/>
<source>...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="__main__.py" line="280"/>
<location filename="__main__.py" line="296"/>
<source>N/A</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="__main__.py" line="280"/>
<source>Frequency hops: {} Sweep time: {:.2f} s</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="__main__.py" line="421"/>
<location filename="__main__.py" line="462"/>
<source>About - QSpectrumAnalyzer</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="325"/>
<location filename="ui_qspectrumanalyzer.py" line="334"/>
<source>Persistence</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="330"/>
<location filename="ui_qspectrumanalyzer.py" line="331"/>
<source>Average</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="327"/>
<location filename="ui_qspectrumanalyzer.py" line="328"/>
<source>Colors...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="322"/>
<location filename="ui_qspectrumanalyzer.py" line="327"/>
<source>Main curve</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="__main__.py" line="296"/>
<source>Frequency hops: {} | Sweep time: {:.2f} s | FPS: {:.2f}</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="329"/>
<source>Max. hold</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="330"/>
<source>Min. hold</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QSpectrumAnalyzerPersistence</name>
@ -277,7 +287,7 @@
<translation type="unfinished"></translation>
</message>
<message>
<location filename="__main__.py" line="46"/>
<location filename="__main__.py" line="47"/>
<source>Select executable - QSpectrumAnalyzer</source>
<translation type="unfinished"></translation>
</message>

View File

@ -1,10 +1,8 @@
import collections, math
import numpy as np
from PyQt4 import QtCore
import pyqtgraph as pg
from qspectrumanalyzer.utils import smooth
# Basic PyQtGraph settings
pg.setConfigOptions(antialias=True)
@ -23,19 +21,14 @@ class SpectrumPlotWidget:
self.persistence_length = 5
self.persistence_decay = "exponential"
self.persistence_color = pg.mkColor("g")
self.peak_hold = False
self.peak_hold_color = pg.mkColor("r")
self.average = False
self.average_color = pg.mkColor("c")
self.smooth = False
self.smooth_length = 11
self.smooth_window = "hanning"
self.counter = 0
self.peak_hold_data = None
self.average_data = None
self.persistence_data = None
self.persistence_curves = None
self.peak_hold_max = False
self.peak_hold_max_color = pg.mkColor("r")
self.peak_hold_min = False
self.peak_hold_min_color = pg.mkColor("b")
self.average = False
self.average_color = pg.mkColor("c")
self.create_plot()
@ -51,8 +44,9 @@ class SpectrumPlotWidget:
self.create_persistence_curves()
self.create_average_curve()
self.create_peak_hold_min_curve()
self.create_peak_hold_max_curve()
self.create_main_curve()
self.create_peak_hold_curve()
# Create crosshair
self.vLine = pg.InfiniteLine(angle=90, movable=False)
@ -64,15 +58,20 @@ class SpectrumPlotWidget:
self.mouseProxy = pg.SignalProxy(self.plot.scene().sigMouseMoved,
rateLimit=60, slot=self.mouse_moved)
def create_peak_hold_curve(self):
"""Create peak hold curve"""
self.curve_peak_hold = self.plot.plot(pen=self.peak_hold_color)
self.curve_peak_hold.setZValue(900)
def create_main_curve(self):
"""Create main spectrum curve"""
self.curve = self.plot.plot(pen=self.main_color)
self.curve.setZValue(800)
self.curve.setZValue(900)
def create_peak_hold_max_curve(self):
"""Create max. peak hold curve"""
self.curve_peak_hold_max = self.plot.plot(pen=self.peak_hold_max_color)
self.curve_peak_hold_max.setZValue(800)
def create_peak_hold_min_curve(self):
"""Create min. peak hold curve"""
self.curve_peak_hold_min = self.plot.plot(pen=self.peak_hold_min_color)
self.curve_peak_hold_min.setZValue(800)
def create_average_curve(self):
"""Create average curve"""
@ -94,7 +93,8 @@ class SpectrumPlotWidget:
def set_colors(self):
"""Set colors of all curves"""
self.curve.setPen(self.main_color)
self.curve_peak_hold.setPen(self.peak_hold_color)
self.curve_peak_hold_max.setPen(self.peak_hold_max_color)
self.curve_peak_hold_min.setPen(self.peak_hold_min_color)
self.curve_average.setPen(self.average_color)
decay = self.get_decay()
@ -118,47 +118,85 @@ class SpectrumPlotWidget:
else:
return self.decay_linear
def update_plot(self, data):
"""Update main spectrum plot"""
self.counter += 1
def update_plot(self, data_storage, force=False):
"""Update main spectrum curve"""
if data_storage.x is None:
return
# Apply smoothing to data
if self.smooth:
data["y"] = smooth(data["y"],
window_len=self.smooth_length,
window=self.smooth_window)
if self.main_curve or force:
self.curve.setData(data_storage.x, data_storage.y)
if force:
self.curve.setVisible(self.main_curve)
# Draw main curve
if self.main_curve:
self.curve.setData(data["x"], data["y"])
def update_peak_hold_max(self, data_storage, force=False):
"""Update max. peak hold curve"""
if data_storage.x is None:
return
# Update peak hold data and draw peak hold curve
if self.peak_hold:
if self.peak_hold_data is None:
self.peak_hold_data = data["y"].copy()
else:
for i, y in enumerate(data["y"]):
if y > self.peak_hold_data[i]:
self.peak_hold_data[i] = y
self.curve_peak_hold.setData(data["x"], self.peak_hold_data)
if self.peak_hold_max or force:
self.curve_peak_hold_max.setData(data_storage.x, data_storage.peak_hold_max)
if force:
self.curve_peak_hold_max.setVisible(self.peak_hold_max)
# Update average data and draw average curve
if self.average:
if self.average_data is None:
self.average_data = data["y"].copy()
else:
for i, y in enumerate(data["y"]):
self.average_data[i] = (self.counter * self.average_data[i] + y) / (self.counter + 1)
self.curve_average.setData(data["x"], self.average_data)
def update_peak_hold_min(self, data_storage, force=False):
"""Update min. peak hold curve"""
if data_storage.x is None:
return
# Draw persistence curves
if self.persistence:
if self.peak_hold_min or force:
self.curve_peak_hold_min.setData(data_storage.x, data_storage.peak_hold_min)
if force:
self.curve_peak_hold_min.setVisible(self.peak_hold_min)
def update_average(self, data_storage, force=False):
"""Update average curve"""
if data_storage.x is None:
return
if self.average or force:
self.curve_average.setData(data_storage.x, data_storage.average)
if force:
self.curve_average.setVisible(self.average)
def update_persistence(self, data_storage, force=False):
"""Update persistence curves"""
if data_storage.x is None:
return
if self.persistence or force:
if self.persistence_data is None:
self.persistence_data = collections.deque(maxlen=self.persistence_length)
else:
for i, y in enumerate(self.persistence_data):
self.persistence_curves[i].setData(data["x"], y)
self.persistence_data.appendleft(data["y"].copy())
curve = self.persistence_curves[i]
curve.setData(data_storage.x, y)
if force:
curve.setVisible(self.persistence)
self.persistence_data.appendleft(data_storage.y)
def recalculate_plot(self, data_storage):
"""Recalculate plot from history"""
if data_storage.x is None:
return
QtCore.QTimer.singleShot(0, lambda: self.update_plot(data_storage, force=True))
QtCore.QTimer.singleShot(0, lambda: self.update_average(data_storage, force=True))
QtCore.QTimer.singleShot(0, lambda: self.update_peak_hold_max(data_storage, force=True))
QtCore.QTimer.singleShot(0, lambda: self.update_peak_hold_min(data_storage, force=True))
def recalculate_persistence(self, data_storage):
"""Recalculate persistence data and update persistence curves"""
if data_storage.x is None:
return
self.clear_persistence()
self.persistence_data = collections.deque(maxlen=self.persistence_length)
for i in range(min(self.persistence_length, data_storage.history.history_size - 1)):
data = data_storage.history[-i - 2]
if data_storage.smooth:
data = data_storage.smooth_data(data)
self.persistence_data.append(data)
QtCore.QTimer.singleShot(0, lambda: self.update_persistence(data_storage, force=True))
def mouse_moved(self, evt):
"""Update crosshair when mouse is moved"""
@ -166,34 +204,31 @@ class SpectrumPlotWidget:
if self.plot.sceneBoundingRect().contains(pos):
mousePoint = self.plot.vb.mapSceneToView(pos)
self.posLabel.setText(
"<span style='font-size: 12pt'>f={:0.3f} MHz, P={:0.3f} dBm</span>".format(mousePoint.x() / 1e6,
mousePoint.y())
"<span style='font-size: 12pt'>f={:0.3f} MHz, P={:0.3f} dBm</span>".format(
mousePoint.x() / 1e6,
mousePoint.y()
)
)
self.vLine.setPos(mousePoint.x())
self.hLine.setPos(mousePoint.y())
def main_clear(self):
def clear_plot(self):
"""Clear main spectrum curve"""
self.curve.clear()
self.plot.removeItem(self.curve)
self.create_main_curve()
def peak_hold_clear(self):
"""Clear peak hold curve"""
self.peak_hold_data = None
self.curve_peak_hold.clear()
self.plot.removeItem(self.curve_peak_hold)
self.create_peak_hold_curve()
def clear_peak_hold_max(self):
"""Clear max. peak hold curve"""
self.curve_peak_hold_max.clear()
def average_clear(self):
def clear_peak_hold_min(self):
"""Clear min. peak hold curve"""
self.curve_peak_hold_min.clear()
def clear_average(self):
"""Clear average curve"""
self.counter = 0
self.average_data = None
self.curve_average.clear()
self.plot.removeItem(self.curve_average)
self.create_average_curve()
def persistence_clear(self):
def clear_persistence(self):
"""Clear spectrum persistence curves"""
self.persistence_data = None
for curve in self.persistence_curves:
@ -201,7 +236,6 @@ class SpectrumPlotWidget:
self.plot.removeItem(curve)
self.create_persistence_curves()
class WaterfallPlotWidget:
"""Waterfall plot"""
def __init__(self, layout, histogram_layout=None):
@ -240,30 +274,32 @@ class WaterfallPlotWidget:
#self.histogram.setHistogramRange(-50, 0)
#self.histogram.setLevels(-50, 0)
def update_plot(self, data):
def update_plot(self, data_storage):
"""Update waterfall plot"""
self.counter += 1
# Create waterfall data array and waterfall image on first run
# Create waterfall image on first run
if self.counter == 1:
self.waterfallImgArray = np.zeros((self.history_size, len(data["x"])))
self.waterfallImg = pg.ImageItem()
self.waterfallImg.scale((data["x"][-1] - data["x"][0]) / len(data["x"]), 1)
self.waterfallImg.scale((data_storage.x[-1] - data_storage.x[0]) / len(data_storage.x), 1)
self.plot.clear()
self.plot.addItem(self.waterfallImg)
# Roll down one and replace leading edge with new data
self.waterfallImgArray = np.roll(self.waterfallImgArray, -1, axis=0)
self.waterfallImgArray[-1] = data["y"]
self.waterfallImg.setImage(self.waterfallImgArray[-self.counter:].T,
self.waterfallImg.setImage(data_storage.history.buffer[-self.counter:].T,
autoLevels=False, autoRange=False)
# Move waterfall image to always start at 0
self.waterfallImg.setPos(data["x"][0],
-self.counter if self.counter < self.history_size
else -self.history_size)
self.waterfallImg.setPos(
data_storage.x[0],
-self.counter if self.counter < self.history_size else -self.history_size
)
# Link histogram widget to waterfall image on first run
# (must be done after first data is received or else levels would be wrong)
if self.counter == 1 and self.histogram_layout:
self.histogram.setImageItem(self.waterfallImg)
def clear_plot(self):
"""Clear waterfall plot"""
self.counter = 0

View File

@ -82,7 +82,7 @@
</property>
<property name="minimumSize">
<size>
<width>190</width>
<width>10</width>
<height>10</height>
</size>
</property>
@ -143,7 +143,7 @@
</property>
<property name="minimumSize">
<size>
<width>225</width>
<width>10</width>
<height>10</height>
</size>
</property>
@ -339,6 +339,25 @@
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<widget class="QSpinBox" name="gainSpinBox">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="specialValueText">
<string>auto</string>
</property>
<property name="minimum">
<number>-1</number>
</property>
<property name="maximum">
<number>49</number>
</property>
<property name="value">
<number>-1</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
@ -359,19 +378,6 @@
</property>
</widget>
</item>
<item row="9" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>1</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="0">
<widget class="QSpinBox" name="ppmSpinBox">
<property name="alignment">
@ -395,10 +401,31 @@
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QCheckBox" name="peakHoldCheckBox">
<item row="4" column="1" colspan="2">
<widget class="QPushButton" name="colorsButton">
<property name="text">
<string>Peak hold</string>
<string>Colors...</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QCheckBox" name="peakHoldMaxCheckBox">
<property name="text">
<string>Max. hold</string>
</property>
</widget>
</item>
<item row="5" column="1" colspan="2">
<widget class="QCheckBox" name="peakHoldMinCheckBox">
<property name="text">
<string>Min. hold</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QCheckBox" name="averageCheckBox">
<property name="text">
<string>Average</string>
</property>
</widget>
</item>
@ -409,46 +436,6 @@
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QCheckBox" name="persistenceCheckBox">
<property name="text">
<string>Persistence</string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<widget class="QSpinBox" name="gainSpinBox">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="specialValueText">
<string>auto</string>
</property>
<property name="minimum">
<number>-1</number>
</property>
<property name="maximum">
<number>49</number>
</property>
<property name="value">
<number>-1</number>
</property>
</widget>
</item>
<item row="3" column="1" colspan="2">
<widget class="QSpinBox" name="cropSpinBox">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="4" column="1" colspan="2">
<widget class="QPushButton" name="colorsButton">
<property name="text">
<string>Colors...</string>
</property>
</widget>
</item>
<item row="7" column="2">
<widget class="QToolButton" name="smoothButton">
<property name="text">
@ -459,6 +446,13 @@
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QCheckBox" name="persistenceCheckBox">
<property name="text">
<string>Persistence</string>
</property>
</widget>
</item>
<item row="8" column="2">
<widget class="QToolButton" name="persistenceButton">
<property name="text">
@ -469,10 +463,23 @@
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QCheckBox" name="averageCheckBox">
<property name="text">
<string>Average</string>
<item row="9" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>1</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="1" colspan="2">
<widget class="QSpinBox" name="cropSpinBox">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
@ -549,7 +556,8 @@
<tabstop>cropSpinBox</tabstop>
<tabstop>mainCurveCheckBox</tabstop>
<tabstop>colorsButton</tabstop>
<tabstop>peakHoldCheckBox</tabstop>
<tabstop>peakHoldMaxCheckBox</tabstop>
<tabstop>peakHoldMinCheckBox</tabstop>
<tabstop>averageCheckBox</tabstop>
<tabstop>smoothCheckBox</tabstop>
<tabstop>smoothButton</tabstop>

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>202</width>
<height>214</height>
<width>232</width>
<height>260</height>
</rect>
</property>
<property name="windowTitle">
@ -42,15 +42,15 @@
<item row="1" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Peak hold color:</string>
<string>Max. peak hold color:</string>
</property>
<property name="buddy">
<cstring>peakHoldColorButton</cstring>
<cstring>peakHoldMaxColorButton</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="ColorButton" name="peakHoldColorButton">
<widget class="ColorButton" name="peakHoldMaxColorButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
@ -63,17 +63,17 @@
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_5">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Average color:</string>
<string>Min. peak hold color:</string>
</property>
<property name="buddy">
<cstring>averageColorButton</cstring>
<cstring>peakHoldMinColorButton</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="ColorButton" name="averageColorButton">
<widget class="ColorButton" name="peakHoldMinColorButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
@ -86,6 +86,29 @@
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Average color:</string>
</property>
<property name="buddy">
<cstring>averageColorButton</cstring>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="ColorButton" name="averageColorButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Persistence color:</string>
@ -95,7 +118,7 @@
</property>
</widget>
</item>
<item row="3" column="1">
<item row="4" column="1">
<widget class="ColorButton" name="persistenceColorButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
@ -144,7 +167,8 @@
</customwidgets>
<tabstops>
<tabstop>mainColorButton</tabstop>
<tabstop>peakHoldColorButton</tabstop>
<tabstop>peakHoldMaxColorButton</tabstop>
<tabstop>peakHoldMinColorButton</tabstop>
<tabstop>averageColorButton</tabstop>
<tabstop>persistenceColorButton</tabstop>
<tabstop>buttonBox</tabstop>

View File

@ -71,7 +71,7 @@ class Ui_QSpectrumAnalyzerMainWindow(object):
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.controlsDockWidget.sizePolicy().hasHeightForWidth())
self.controlsDockWidget.setSizePolicy(sizePolicy)
self.controlsDockWidget.setMinimumSize(QtCore.QSize(190, 10))
self.controlsDockWidget.setMinimumSize(QtCore.QSize(10, 10))
self.controlsDockWidget.setFeatures(QtGui.QDockWidget.DockWidgetFloatable|QtGui.QDockWidget.DockWidgetMovable)
self.controlsDockWidget.setObjectName(_fromUtf8("controlsDockWidget"))
self.controlsDockWidgetContents = QtGui.QWidget()
@ -97,7 +97,7 @@ class Ui_QSpectrumAnalyzerMainWindow(object):
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.frequencyDockWidget.sizePolicy().hasHeightForWidth())
self.frequencyDockWidget.setSizePolicy(sizePolicy)
self.frequencyDockWidget.setMinimumSize(QtCore.QSize(225, 10))
self.frequencyDockWidget.setMinimumSize(QtCore.QSize(10, 10))
self.frequencyDockWidget.setFeatures(QtGui.QDockWidget.DockWidgetFloatable|QtGui.QDockWidget.DockWidgetMovable)
self.frequencyDockWidget.setObjectName(_fromUtf8("frequencyDockWidget"))
self.frequencyDockWidgetContents = QtGui.QWidget()
@ -180,14 +180,19 @@ class Ui_QSpectrumAnalyzerMainWindow(object):
self.intervalSpinBox.setProperty("value", 1.0)
self.intervalSpinBox.setObjectName(_fromUtf8("intervalSpinBox"))
self.gridLayout.addWidget(self.intervalSpinBox, 1, 0, 1, 1)
self.gainSpinBox = QtGui.QSpinBox(self.settingsDockWidgetContents)
self.gainSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.gainSpinBox.setMinimum(-1)
self.gainSpinBox.setMaximum(49)
self.gainSpinBox.setProperty("value", -1)
self.gainSpinBox.setObjectName(_fromUtf8("gainSpinBox"))
self.gridLayout.addWidget(self.gainSpinBox, 1, 1, 1, 2)
self.label_5 = QtGui.QLabel(self.settingsDockWidgetContents)
self.label_5.setObjectName(_fromUtf8("label_5"))
self.gridLayout.addWidget(self.label_5, 2, 0, 1, 1)
self.label_7 = QtGui.QLabel(self.settingsDockWidgetContents)
self.label_7.setObjectName(_fromUtf8("label_7"))
self.gridLayout.addWidget(self.label_7, 2, 1, 1, 1)
spacerItem2 = QtGui.QSpacerItem(20, 1, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.gridLayout.addItem(spacerItem2, 9, 0, 1, 1)
self.ppmSpinBox = QtGui.QSpinBox(self.settingsDockWidgetContents)
self.ppmSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.ppmSpinBox.setMinimum(-999)
@ -198,40 +203,38 @@ class Ui_QSpectrumAnalyzerMainWindow(object):
self.mainCurveCheckBox.setChecked(True)
self.mainCurveCheckBox.setObjectName(_fromUtf8("mainCurveCheckBox"))
self.gridLayout.addWidget(self.mainCurveCheckBox, 4, 0, 1, 1)
self.peakHoldCheckBox = QtGui.QCheckBox(self.settingsDockWidgetContents)
self.peakHoldCheckBox.setObjectName(_fromUtf8("peakHoldCheckBox"))
self.gridLayout.addWidget(self.peakHoldCheckBox, 5, 0, 1, 1)
self.smoothCheckBox = QtGui.QCheckBox(self.settingsDockWidgetContents)
self.smoothCheckBox.setObjectName(_fromUtf8("smoothCheckBox"))
self.gridLayout.addWidget(self.smoothCheckBox, 7, 0, 1, 1)
self.persistenceCheckBox = QtGui.QCheckBox(self.settingsDockWidgetContents)
self.persistenceCheckBox.setObjectName(_fromUtf8("persistenceCheckBox"))
self.gridLayout.addWidget(self.persistenceCheckBox, 8, 0, 1, 1)
self.gainSpinBox = QtGui.QSpinBox(self.settingsDockWidgetContents)
self.gainSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.gainSpinBox.setMinimum(-1)
self.gainSpinBox.setMaximum(49)
self.gainSpinBox.setProperty("value", -1)
self.gainSpinBox.setObjectName(_fromUtf8("gainSpinBox"))
self.gridLayout.addWidget(self.gainSpinBox, 1, 1, 1, 2)
self.cropSpinBox = QtGui.QSpinBox(self.settingsDockWidgetContents)
self.cropSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.cropSpinBox.setObjectName(_fromUtf8("cropSpinBox"))
self.gridLayout.addWidget(self.cropSpinBox, 3, 1, 1, 2)
self.colorsButton = QtGui.QPushButton(self.settingsDockWidgetContents)
self.colorsButton.setObjectName(_fromUtf8("colorsButton"))
self.gridLayout.addWidget(self.colorsButton, 4, 1, 1, 2)
self.peakHoldMaxCheckBox = QtGui.QCheckBox(self.settingsDockWidgetContents)
self.peakHoldMaxCheckBox.setObjectName(_fromUtf8("peakHoldMaxCheckBox"))
self.gridLayout.addWidget(self.peakHoldMaxCheckBox, 5, 0, 1, 1)
self.peakHoldMinCheckBox = QtGui.QCheckBox(self.settingsDockWidgetContents)
self.peakHoldMinCheckBox.setObjectName(_fromUtf8("peakHoldMinCheckBox"))
self.gridLayout.addWidget(self.peakHoldMinCheckBox, 5, 1, 1, 2)
self.averageCheckBox = QtGui.QCheckBox(self.settingsDockWidgetContents)
self.averageCheckBox.setObjectName(_fromUtf8("averageCheckBox"))
self.gridLayout.addWidget(self.averageCheckBox, 6, 0, 1, 1)
self.smoothCheckBox = QtGui.QCheckBox(self.settingsDockWidgetContents)
self.smoothCheckBox.setObjectName(_fromUtf8("smoothCheckBox"))
self.gridLayout.addWidget(self.smoothCheckBox, 7, 0, 1, 1)
self.smoothButton = QtGui.QToolButton(self.settingsDockWidgetContents)
self.smoothButton.setAutoRaise(False)
self.smoothButton.setObjectName(_fromUtf8("smoothButton"))
self.gridLayout.addWidget(self.smoothButton, 7, 2, 1, 1)
self.persistenceCheckBox = QtGui.QCheckBox(self.settingsDockWidgetContents)
self.persistenceCheckBox.setObjectName(_fromUtf8("persistenceCheckBox"))
self.gridLayout.addWidget(self.persistenceCheckBox, 8, 0, 1, 1)
self.persistenceButton = QtGui.QToolButton(self.settingsDockWidgetContents)
self.persistenceButton.setAutoRaise(False)
self.persistenceButton.setObjectName(_fromUtf8("persistenceButton"))
self.gridLayout.addWidget(self.persistenceButton, 8, 2, 1, 1)
self.averageCheckBox = QtGui.QCheckBox(self.settingsDockWidgetContents)
self.averageCheckBox.setObjectName(_fromUtf8("averageCheckBox"))
self.gridLayout.addWidget(self.averageCheckBox, 6, 0, 1, 1)
spacerItem2 = QtGui.QSpacerItem(20, 1, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.gridLayout.addItem(spacerItem2, 9, 0, 1, 1)
self.cropSpinBox = QtGui.QSpinBox(self.settingsDockWidgetContents)
self.cropSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.cropSpinBox.setObjectName(_fromUtf8("cropSpinBox"))
self.gridLayout.addWidget(self.cropSpinBox, 3, 1, 1, 2)
self.settingsDockWidget.setWidget(self.settingsDockWidgetContents)
QSpectrumAnalyzerMainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.settingsDockWidget)
self.levelsDockWidget = QtGui.QDockWidget(QSpectrumAnalyzerMainWindow)
@ -289,8 +292,9 @@ class Ui_QSpectrumAnalyzerMainWindow(object):
QSpectrumAnalyzerMainWindow.setTabOrder(self.ppmSpinBox, self.cropSpinBox)
QSpectrumAnalyzerMainWindow.setTabOrder(self.cropSpinBox, self.mainCurveCheckBox)
QSpectrumAnalyzerMainWindow.setTabOrder(self.mainCurveCheckBox, self.colorsButton)
QSpectrumAnalyzerMainWindow.setTabOrder(self.colorsButton, self.peakHoldCheckBox)
QSpectrumAnalyzerMainWindow.setTabOrder(self.peakHoldCheckBox, self.averageCheckBox)
QSpectrumAnalyzerMainWindow.setTabOrder(self.colorsButton, self.peakHoldMaxCheckBox)
QSpectrumAnalyzerMainWindow.setTabOrder(self.peakHoldMaxCheckBox, self.peakHoldMinCheckBox)
QSpectrumAnalyzerMainWindow.setTabOrder(self.peakHoldMinCheckBox, self.averageCheckBox)
QSpectrumAnalyzerMainWindow.setTabOrder(self.averageCheckBox, self.smoothCheckBox)
QSpectrumAnalyzerMainWindow.setTabOrder(self.smoothCheckBox, self.smoothButton)
QSpectrumAnalyzerMainWindow.setTabOrder(self.smoothButton, self.persistenceCheckBox)
@ -317,17 +321,18 @@ class Ui_QSpectrumAnalyzerMainWindow(object):
self.settingsDockWidget.setWindowTitle(_translate("QSpectrumAnalyzerMainWindow", "Settings", None))
self.label_4.setText(_translate("QSpectrumAnalyzerMainWindow", "Interval [s]:", None))
self.label_6.setText(_translate("QSpectrumAnalyzerMainWindow", "Gain [dB]:", None))
self.gainSpinBox.setSpecialValueText(_translate("QSpectrumAnalyzerMainWindow", "auto", None))
self.label_5.setText(_translate("QSpectrumAnalyzerMainWindow", "Corr. [ppm]:", None))
self.label_7.setText(_translate("QSpectrumAnalyzerMainWindow", "Crop [%]:", None))
self.mainCurveCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Main curve", None))
self.peakHoldCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Peak hold", None))
self.smoothCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Smoothing", None))
self.persistenceCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Persistence", None))
self.gainSpinBox.setSpecialValueText(_translate("QSpectrumAnalyzerMainWindow", "auto", None))
self.colorsButton.setText(_translate("QSpectrumAnalyzerMainWindow", "Colors...", None))
self.smoothButton.setText(_translate("QSpectrumAnalyzerMainWindow", "...", None))
self.persistenceButton.setText(_translate("QSpectrumAnalyzerMainWindow", "...", None))
self.peakHoldMaxCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Max. hold", None))
self.peakHoldMinCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Min. hold", None))
self.averageCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Average", None))
self.smoothCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Smoothing", None))
self.smoothButton.setText(_translate("QSpectrumAnalyzerMainWindow", "...", None))
self.persistenceCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Persistence", None))
self.persistenceButton.setText(_translate("QSpectrumAnalyzerMainWindow", "...", None))
self.levelsDockWidget.setWindowTitle(_translate("QSpectrumAnalyzerMainWindow", "Levels", None))
self.action_Settings.setText(_translate("QSpectrumAnalyzerMainWindow", "&Settings...", None))
self.action_Quit.setText(_translate("QSpectrumAnalyzerMainWindow", "&Quit", None))

View File

@ -25,7 +25,7 @@ except AttributeError:
class Ui_QSpectrumAnalyzerColors(object):
def setupUi(self, QSpectrumAnalyzerColors):
QSpectrumAnalyzerColors.setObjectName(_fromUtf8("QSpectrumAnalyzerColors"))
QSpectrumAnalyzerColors.resize(202, 214)
QSpectrumAnalyzerColors.resize(232, 260)
self.verticalLayout = QtGui.QVBoxLayout(QSpectrumAnalyzerColors)
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
self.formLayout = QtGui.QFormLayout()
@ -44,17 +44,28 @@ class Ui_QSpectrumAnalyzerColors(object):
self.label_4 = QtGui.QLabel(QSpectrumAnalyzerColors)
self.label_4.setObjectName(_fromUtf8("label_4"))
self.formLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.label_4)
self.peakHoldColorButton = ColorButton(QSpectrumAnalyzerColors)
self.peakHoldMaxColorButton = ColorButton(QSpectrumAnalyzerColors)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.peakHoldColorButton.sizePolicy().hasHeightForWidth())
self.peakHoldColorButton.setSizePolicy(sizePolicy)
self.peakHoldColorButton.setObjectName(_fromUtf8("peakHoldColorButton"))
self.formLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.peakHoldColorButton)
sizePolicy.setHeightForWidth(self.peakHoldMaxColorButton.sizePolicy().hasHeightForWidth())
self.peakHoldMaxColorButton.setSizePolicy(sizePolicy)
self.peakHoldMaxColorButton.setObjectName(_fromUtf8("peakHoldMaxColorButton"))
self.formLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.peakHoldMaxColorButton)
self.label_6 = QtGui.QLabel(QSpectrumAnalyzerColors)
self.label_6.setObjectName(_fromUtf8("label_6"))
self.formLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.label_6)
self.peakHoldMinColorButton = ColorButton(QSpectrumAnalyzerColors)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.peakHoldMinColorButton.sizePolicy().hasHeightForWidth())
self.peakHoldMinColorButton.setSizePolicy(sizePolicy)
self.peakHoldMinColorButton.setObjectName(_fromUtf8("peakHoldMinColorButton"))
self.formLayout.setWidget(2, QtGui.QFormLayout.FieldRole, self.peakHoldMinColorButton)
self.label_5 = QtGui.QLabel(QSpectrumAnalyzerColors)
self.label_5.setObjectName(_fromUtf8("label_5"))
self.formLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.label_5)
self.formLayout.setWidget(3, QtGui.QFormLayout.LabelRole, self.label_5)
self.averageColorButton = ColorButton(QSpectrumAnalyzerColors)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
@ -62,10 +73,10 @@ class Ui_QSpectrumAnalyzerColors(object):
sizePolicy.setHeightForWidth(self.averageColorButton.sizePolicy().hasHeightForWidth())
self.averageColorButton.setSizePolicy(sizePolicy)
self.averageColorButton.setObjectName(_fromUtf8("averageColorButton"))
self.formLayout.setWidget(2, QtGui.QFormLayout.FieldRole, self.averageColorButton)
self.formLayout.setWidget(3, QtGui.QFormLayout.FieldRole, self.averageColorButton)
self.label_3 = QtGui.QLabel(QSpectrumAnalyzerColors)
self.label_3.setObjectName(_fromUtf8("label_3"))
self.formLayout.setWidget(3, QtGui.QFormLayout.LabelRole, self.label_3)
self.formLayout.setWidget(4, QtGui.QFormLayout.LabelRole, self.label_3)
self.persistenceColorButton = ColorButton(QSpectrumAnalyzerColors)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
@ -73,7 +84,7 @@ class Ui_QSpectrumAnalyzerColors(object):
sizePolicy.setHeightForWidth(self.persistenceColorButton.sizePolicy().hasHeightForWidth())
self.persistenceColorButton.setSizePolicy(sizePolicy)
self.persistenceColorButton.setObjectName(_fromUtf8("persistenceColorButton"))
self.formLayout.setWidget(3, QtGui.QFormLayout.FieldRole, self.persistenceColorButton)
self.formLayout.setWidget(4, QtGui.QFormLayout.FieldRole, self.persistenceColorButton)
self.verticalLayout.addLayout(self.formLayout)
spacerItem = QtGui.QSpacerItem(20, 2, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.verticalLayout.addItem(spacerItem)
@ -83,7 +94,8 @@ class Ui_QSpectrumAnalyzerColors(object):
self.buttonBox.setObjectName(_fromUtf8("buttonBox"))
self.verticalLayout.addWidget(self.buttonBox)
self.label_2.setBuddy(self.mainColorButton)
self.label_4.setBuddy(self.peakHoldColorButton)
self.label_4.setBuddy(self.peakHoldMaxColorButton)
self.label_6.setBuddy(self.peakHoldMinColorButton)
self.label_5.setBuddy(self.averageColorButton)
self.label_3.setBuddy(self.persistenceColorButton)
@ -91,8 +103,9 @@ class Ui_QSpectrumAnalyzerColors(object):
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), QSpectrumAnalyzerColors.accept)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), QSpectrumAnalyzerColors.reject)
QtCore.QMetaObject.connectSlotsByName(QSpectrumAnalyzerColors)
QSpectrumAnalyzerColors.setTabOrder(self.mainColorButton, self.peakHoldColorButton)
QSpectrumAnalyzerColors.setTabOrder(self.peakHoldColorButton, self.averageColorButton)
QSpectrumAnalyzerColors.setTabOrder(self.mainColorButton, self.peakHoldMaxColorButton)
QSpectrumAnalyzerColors.setTabOrder(self.peakHoldMaxColorButton, self.peakHoldMinColorButton)
QSpectrumAnalyzerColors.setTabOrder(self.peakHoldMinColorButton, self.averageColorButton)
QSpectrumAnalyzerColors.setTabOrder(self.averageColorButton, self.persistenceColorButton)
QSpectrumAnalyzerColors.setTabOrder(self.persistenceColorButton, self.buttonBox)
@ -100,8 +113,10 @@ class Ui_QSpectrumAnalyzerColors(object):
QSpectrumAnalyzerColors.setWindowTitle(_translate("QSpectrumAnalyzerColors", "Colors - QSpectrumAnalyzer", None))
self.label_2.setText(_translate("QSpectrumAnalyzerColors", "Main curve color:", None))
self.mainColorButton.setText(_translate("QSpectrumAnalyzerColors", "...", None))
self.label_4.setText(_translate("QSpectrumAnalyzerColors", "Peak hold color:", None))
self.peakHoldColorButton.setText(_translate("QSpectrumAnalyzerColors", "...", None))
self.label_4.setText(_translate("QSpectrumAnalyzerColors", "Max. peak hold color:", None))
self.peakHoldMaxColorButton.setText(_translate("QSpectrumAnalyzerColors", "...", None))
self.label_6.setText(_translate("QSpectrumAnalyzerColors", "Min. peak hold color:", None))
self.peakHoldMinColorButton.setText(_translate("QSpectrumAnalyzerColors", "...", None))
self.label_5.setText(_translate("QSpectrumAnalyzerColors", "Average color:", None))
self.averageColorButton.setText(_translate("QSpectrumAnalyzerColors", "...", None))
self.label_3.setText(_translate("QSpectrumAnalyzerColors", "Persistence color:", None))