Compare commits

..

No commits in common. "master" and "hackrf_sweep" have entirely different histories.

42 changed files with 1679 additions and 3404 deletions

View File

@ -2,3 +2,4 @@ include LICENSE
include README.rst include README.rst
include qspectrumanalyzer.desktop include qspectrumanalyzer.desktop
include qspectrumanalyzer.png include qspectrumanalyzer.png
include qspectrumanalyzer.svg

View File

@ -1,20 +1,14 @@
# Maintainer: Michal Krenek (Mikos) <m.krenek@gmail.com> # Maintainer: Michal Krenek (Mikos) <m.krenek@gmail.com>
pkgname=qspectrumanalyzer pkgname=qspectrumanalyzer
pkgver=2.2.0 pkgver=1.4.0
pkgrel=1 pkgrel=1
pkgdesc="Spectrum analyzer for multiple SDR platforms (PyQtGraph based GUI for soapy_power, hackrf_sweep, rtl_power, rx_power and other backends)" pkgdesc="Spectrum analyzer for RTL-SDR (GUI for rtl_power based on PyQtGraph)"
arch=('any') arch=('any')
url="https://github.com/xmikos/qspectrumanalyzer" url="https://github.com/xmikos/qspectrumanalyzer"
license=('GPL3') license=('GPL3')
depends=('python-qt.py' 'python-pyqt5' 'python-pyqtgraph' 'soapy_power>=1.6.0') depends=('python-pyqt4' 'python-pyqtgraph' 'rtl-sdr')
makedepends=('python-setuptools') makedepends=('python-setuptools')
optdepends=( optdepends=('rtl_power_fftw-git: alternative rtl_power implementation using FFTW library')
'hackrf: hackrf_sweep backend (wideband spectrum monitoring with sweep rate of 8 GHz/s)'
'rtl_power_fftw-git: alternative RTL-SDR backend using FFTW library (much faster than rtl_power)'
'rtl-sdr-keenerd-git: better version of rtl_power backend'
'rtl-sdr: original rtl_power backend (slightly broken, use rtl-sdr-keenerd-git instead)'
'rx_tools: rx_power backend (universal SoapySDR based backend, but seems slow and buggy)'
)
source=(https://github.com/xmikos/qspectrumanalyzer/archive/v$pkgver.tar.gz) source=(https://github.com/xmikos/qspectrumanalyzer/archive/v$pkgver.tar.gz)
build() { build() {

View File

@ -1,8 +1,7 @@
QSpectrumAnalyzer QSpectrumAnalyzer
================= =================
Spectrum analyzer for multiple SDR platforms (PyQtGraph based GUI for soapy_power, Spectrum analyzer for RTL-SDR (GUI for rtl_power based on PyQtGraph)
hackrf_sweep, rtl_power, rx_power and other backends)
Screenshots Screenshots
----------- -----------
@ -15,73 +14,37 @@ Requirements
------------ ------------
- Python >= 3.3 - Python >= 3.3
- PyQt4 / PyQt5 / PySide / PySide2 - PyQt >= 4.5
- Qt.py (https://github.com/mottosso/Qt.py)
- PyQtGraph (http://www.pyqtgraph.org) - PyQtGraph (http://www.pyqtgraph.org)
- soapy_power (https://github.com/xmikos/soapy_power) - rtl-sdr (https://github.com/keenerd/rtl-sdr)
- Optional: hackrf / rtl-sdr / rtl_power_fftw / rx_tools - Optional: rtl_power_fftw (https://github.com/AD-Vega/rtl-power-fftw)
Backends You should use `Keenerds fork of rtl-sdr <https://github.com/keenerd/rtl-sdr>`_
-------- (latest Git revision), because ``rtl_power`` in original rtl-sdr (from osmocom.org)
Default backend
***************
- **soapy_power** (https://github.com/xmikos/soapy_power)
``soapy_power`` is the default and recommended universal SDR backend in QSpectrumAnalyzer.
It is based on `SoapySDR <https://github.com/pothosware/SoapySDR>`_ and supports
nearly all SDR platforms (RTL-SDR, HackRF, Airspy, SDRplay, LimeSDR, bladeRF,
USRP and some other SDR devices). It is highly configurable (see additional parameters
help in *Settings* menu) and supports short acquisition time for
near real-time continuous measurement.
Other backends
**************
- **hackrf_sweep** (https://github.com/mossmann/hackrf)
``hackrf_sweep`` backend enables wideband spectrum monitoring by rapidly retuning the radio
without requiring individual tuning requests from the host computer. This allows unprecedented
sweep rate of 8 GHz per second. Only HackRF is supported.
- **rtl_power_fftw** (https://github.com/AD-Vega/rtl-power-fftw)
``rtl_power_fftw`` is alternative backend for RTL-SDR devices and has various
benefits over ``rtl_power``. E.g. better FFT performance (thanks to
use of ``fftw`` library) and possibility to use short acquisition time
for near real-time continuous measurement (minimum interval in original
``rtl_power`` is 1 second).
- **rtl_power** (https://github.com/keenerd/rtl-sdr)
``rtl_power`` is original backend for RTL-SDR devices. There are better alternatives now, but
if you want to use it, you should use `Keenerds fork of rtl-sdr <https://github.com/keenerd/rtl-sdr>`_
(latest Git revision), because ``rtl_power`` in original rtl-sdr package (from osmocom.org)
is broken (especially when used with cropping). is broken (especially when used with cropping).
- **rx_power** (https://github.com/rxseger/rx_tools) *[unsupported]* Another alternative is
`rtl_power_fftw <https://github.com/AD-Vega/rtl-power-fftw>`_ which has various
``rx_power`` (part of ``rx_tools``) is also based on SoapySDR (like default ``soapy_power`` backend) benefits over ``rtl_power``. E.g. better FFT performance (thanks to
and therefore supports nearly all SDR platforms. But it is much slower than soapy_power, doesn't support use of ``fftw`` library) and possibility to use much shorter acquisition time
near real-time continuous measurement (minimum interval is 1 second, same as ``rtl_power``) for more real-time continuous measurement (minimum interval in original
and is buggy. Backend is currently unsupported, if you want to fix it, patches are welcome. ``rtl_power`` is 1 second, but in ``rtl_power_fftw`` you are only limited
by number of frequency hops).
Usage Usage
----- -----
Start QSpectrumAnalyzer by running ``qspectrumanalyzer``. Start QSpectrumAnalyzer by running ``qspectrumanalyzer``.
You can choose which backend you want to use in *File* -> *Settings* You can choose if you want to use ``rtl_power`` or ``rtl_power_fftw`` backend in
(or *Application menu* -> *Preferences* on Mac OS X), default is *File* -> *Settings* (default is ``rtl_power``). Path to ``rtl_power``
``soapy_power``. Device, sample rate, bandwidth, LNB LO, path to backend executable (or ``rtl_power_fftw``) executable can be also manually specified there. You can also
and additional backend parameters can be also manually specified there. You can set waterfall plot history size in there. Default is 100 lines, be aware that
also set waterfall plot history size. Default is 100 lines, be aware that really large sweeps (with a lot of bins) would require a lot of system memory, so
really large sweeps (with a lot of bins) would require a lot of system don't make this number too big.
memory, so don't make this number too big.
Controls should be intuitive, but if you want consistent results, you should Controls should be intuitive, but if you want consistent results, you should
turn off automatic gain control (set gain to some fixed number) and also set turn off automatic gain control (set it to some fixed number) and also set
crop to 20% or more. For finding out ppm correction factor for your rtl-sdr crop to 20% or more. For finding out ppm correction factor for your rtl-sdr
stick, use `kalibrate-rtl <https://github.com/steve-m/kalibrate-rtl>`_. stick, use `kalibrate-rtl <https://github.com/steve-m/kalibrate-rtl>`_.
@ -92,93 +55,39 @@ table can be changed in mini-histogram widget (on *Levels* tab).
Installation Installation
------------ ------------
Arch Linux: **Arch Linux:**
***********
Stable version:
:: ::
git clone https://aur.archlinux.org/qspectrumanalyzer.git git clone https://aur.archlinux.org/qspectrumanalyzer.git
cd qspectrumanalyzer cd qspectrumanalyzer
makepkg -sri makepkg -sri
Git master branch: Or simply use `pacaur <https://aur.archlinux.org/packages/pacaur>`_ (or any other AUR helper):
::
git clone https://aur.archlinux.org/qspectrumanalyzer-git.git
cd qspectrumanalyzer-git
makepkg -sri
Or simply use `pacaur <https://aur.archlinux.org/packages/pacaur>`_ (or any other AUR helper)
which will also automatically install all QSpectrumAnalyzer dependencies:
:: ::
pacaur -S qspectrumanalyzer pacaur -S qspectrumanalyzer
pacaur -S qspectrumanalyzer-git
Ubuntu: **Debian / Ubuntu:**
*******
:: ::
# Add SoapySDR PPA to your system sudo apt-get install python3-pip python3-pyqt4 python3-numpy
sudo add-apt-repository -y ppa:myriadrf/drivers sudo pip3 install qspectrumanalyzer
# Update list of packages Warning! ``pip`` will install packages system-wide by default, but you
sudo apt-get update should always use your distribution package manager for this.
# Install basic dependencies You can install it locally only for your current user by running this (without ``sudo``):
sudo apt-get install python3-pip python3-pyqt5 python3-numpy python3-scipy soapysdr python3-soapysdr ::
# Install SoapySDR drivers for your hardware (e.g. RTL-SDR, Airspy, HackRF, LimeSDR, etc.)
sudo apt-get install soapysdr-module-rtlsdr soapysdr-module-airspy soapysdr-module-hackrf soapysdr-module-lms7
# Install QSpectrumAnalyzer locally for your current user
pip3 install --user qspectrumanalyzer pip3 install --user qspectrumanalyzer
``qspectrumanalyzer`` and ``soapy_power`` executables will be then placed in Executables will be then placed in ``~/.local/bin`` directory, you can add it to your
``~/.local/bin`` directory, you can add it to your PATH in ``~/.bashrc``. PATH in ``~/.bashrc``.
If you want to install QSpectrumAnalyzer directly from Git master branch, you can use this procedure:
::
git clone https://github.com/xmikos/qspectrumanalyzer.git
cd qspectrumanalyzer
pip3 install --user .
Windows:
********
*Only 64-bit Windows are supported (there are no public 32-bit builds of SoapySDR
libraries and drivers).*
1. install `SoapySDR <https://github.com/pothosware/SoapySDR/wiki>`_ libraries and drivers
(bundled as part of Pothos SDR installer: `download <http://downloads.myriadrf.org/builds/PothosSDR/?C=M;O=D>`_).
This bundle also includes other great SDR apps like `CubicSDR <http://cubicsdr.com>`_, `GQRX <http://gqrx.dk>`_,
`GNU Radio Companion <https://gnuradio.org>`_, `Pothos GUI <https://github.com/pothosware/pothos/wiki>`_,
`Lime Suite <https://github.com/myriadrf/LimeSuite>`_ and `Zadig <http://zadig.akeo.ie>`_.
Utilities like ``hackrf_sweep`` and ``rtl_power`` are also included.
2. download QSpectrumAnalyzer installer or portable zip archive from GitHub
`releases <https://github.com/xmikos/qspectrumanalyzer/releases>`_ page
3. after you connect your SDR device, you have to run `Zadig <http://zadig.akeo.ie>`_ to install USB drivers
You can also install QSpectrumAnalyzer manually from `PyPI <https://pypi.python.org>`_:
1. install Python 3.6.x (64-bit) from `python.org <https://www.python.org>`_ and add Python to PATH
2. install `SoapySDR <https://github.com/pothosware/SoapySDR/wiki>`_ libraries and drivers
(bundled as part of Pothos SDR installer: `download <http://downloads.myriadrf.org/builds/PothosSDR/?C=M;O=D>`_)
3. Open ``cmd.exe`` and run::
pip install PyQt5
pip install QSpectrumAnalyzer
You should then be able to run it with ``qspectrumanalyzer`` (or ``python -m qspectrumanalyzer``
if it doesn't work for you).
Todo: Todo:
----- -----
- save FFT history (allow big waterfall plot saved to file)
- automatic peak detection / highlighting - automatic peak detection / highlighting
- display average noise level - display average noise level
- frequency markers / bookmarks with notes (even importing and exporting .csv file with - frequency markers / bookmarks with notes (even importing / exporting .csv file with
predefined channels, etc.) predefined channels, etc.)

View File

@ -1,7 +1,7 @@
[Desktop Entry] [Desktop Entry]
Name=QSpectrumAnalyzer Name=QSpectrumAnalyzer
GenericName=Spectrum analyzer GenericName=Spectrum analyzer
Comment=Spectrum analyzer for multiple SDR platforms (PyQtGraph based GUI for soapy_power, hackrf_sweep, rtl_power, rx_power and other backends) Comment=Spectrum analyzer for RTL-SDR (GUI for rtl_power based on PyQtGraph)
Exec=qspectrumanalyzer Exec=qspectrumanalyzer
Icon=qspectrumanalyzer Icon=qspectrumanalyzer
StartupNotify=true StartupNotify=true

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

479
qspectrumanalyzer/__main__.py Normal file → Executable file
View File

@ -1,46 +1,166 @@
#!/usr/bin/env python #!/usr/bin/env python
import sys, os, signal, time, argparse import sys, signal, time
from Qt import QtCore, QtGui, QtWidgets from PyQt4 import QtCore, QtGui
from qspectrumanalyzer import backends
from qspectrumanalyzer.version import __version__ from qspectrumanalyzer.version import __version__
from qspectrumanalyzer.backend import RtlPowerThread, RtlPowerFftwThread, SoapyPowerThread, RxPowerThread, HackRFSweepThread
from qspectrumanalyzer.data import DataStorage from qspectrumanalyzer.data import DataStorage
from qspectrumanalyzer.plot import SpectrumPlotWidget, WaterfallPlotWidget from qspectrumanalyzer.plot import SpectrumPlotWidget, WaterfallPlotWidget
from qspectrumanalyzer.utils import str_to_color, human_time from qspectrumanalyzer.utils import color_to_str, str_to_color
from qspectrumanalyzer.settings import QSpectrumAnalyzerSettings
from qspectrumanalyzer.smoothing import QSpectrumAnalyzerSmoothing
from qspectrumanalyzer.persistence import QSpectrumAnalyzerPersistence
from qspectrumanalyzer.colors import QSpectrumAnalyzerColors
from qspectrumanalyzer.baseline import QSpectrumAnalyzerBaseline
from qspectrumanalyzer.ui_qspectrumanalyzer_settings import Ui_QSpectrumAnalyzerSettings
from qspectrumanalyzer.ui_qspectrumanalyzer_smooth import Ui_QSpectrumAnalyzerSmooth
from qspectrumanalyzer.ui_qspectrumanalyzer_persistence import Ui_QSpectrumAnalyzerPersistence
from qspectrumanalyzer.ui_qspectrumanalyzer_colors import Ui_QSpectrumAnalyzerColors
from qspectrumanalyzer.ui_qspectrumanalyzer import Ui_QSpectrumAnalyzerMainWindow from qspectrumanalyzer.ui_qspectrumanalyzer import Ui_QSpectrumAnalyzerMainWindow
debug = False
# Allow CTRL+C and/or SIGTERM to kill us (PyQt blocks it otherwise) # Allow CTRL+C and/or SIGTERM to kill us (PyQt blocks it otherwise)
signal.signal(signal.SIGINT, signal.SIG_DFL) signal.signal(signal.SIGINT, signal.SIG_DFL)
signal.signal(signal.SIGTERM, signal.SIG_DFL) signal.signal(signal.SIGTERM, signal.SIG_DFL)
class QSpectrumAnalyzerMainWindow(QtWidgets.QMainWindow, Ui_QSpectrumAnalyzerMainWindow): class QSpectrumAnalyzerSettings(QtGui.QDialog, Ui_QSpectrumAnalyzerSettings):
"""QSpectrumAnalyzer main window""" """QSpectrumAnalyzer settings dialog"""
def __init__(self, parent=None): def __init__(self, parent=None):
# Initialize UI # Initialize UI
super().__init__(parent) super().__init__(parent)
self.setupUi(self) self.setupUi(self)
# Set window icon # Load settings
icon_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "qspectrumanalyzer.svg") settings = QtCore.QSettings()
self.setWindowIcon(QtGui.QIcon(icon_path)) self.executableEdit.setText(settings.value("executable", "soapy_power"))
self.waterfallHistorySizeSpinBox.setValue(settings.value("waterfall_history_size", 100, int))
self.deviceEdit.setText(settings.value("device", ""))
self.sampleRateSpinBox.setValue(settings.value("sample_rate", 2560000, int))
# Create progress bar backend = settings.value("backend", "soapy_power")
self.progressbar = QtWidgets.QProgressBar() self.backendComboBox.blockSignals(True)
self.progressbar.setMaximumWidth(250) i = self.backendComboBox.findText(backend)
self.progressbar.setVisible(False) if i == -1:
self.statusbar.addPermanentWidget(self.progressbar) self.backendComboBox.setCurrentIndex(0)
else:
self.backendComboBox.setCurrentIndex(i)
self.backendComboBox.blockSignals(False)
@QtCore.pyqtSlot()
def on_executableButton_clicked(self):
"""Open file dialog when button is clicked"""
filename = QtGui.QFileDialog.getOpenFileName(self, self.tr("Select executable - QSpectrumAnalyzer"))
if filename:
self.executableEdit.setText(filename)
@QtCore.pyqtSlot(str)
def on_backendComboBox_currentIndexChanged(self, text):
"""Change executable when backend is changed"""
self.executableEdit.setText(text)
self.deviceEdit.setText("")
if text == "hackrf_sweep":
self.sampleRateSpinBox.setMinimum(20000000)
self.sampleRateSpinBox.setMaximum(20000000)
self.sampleRateSpinBox.setValue(20000000)
else:
self.sampleRateSpinBox.setMinimum(0)
self.sampleRateSpinBox.setMaximum(25000000)
self.sampleRateSpinBox.setValue(2560000)
def accept(self):
"""Save settings when dialog is accepted"""
settings = QtCore.QSettings()
settings.setValue("executable", self.executableEdit.text())
settings.setValue("waterfall_history_size", self.waterfallHistorySizeSpinBox.value())
settings.setValue("device", self.deviceEdit.text())
settings.setValue("sample_rate", self.sampleRateSpinBox.value())
settings.setValue("backend", self.backendComboBox.currentText())
QtGui.QDialog.accept(self)
class QSpectrumAnalyzerSmooth(QtGui.QDialog, Ui_QSpectrumAnalyzerSmooth):
"""QSpectrumAnalyzer spectrum smoothing dialog"""
def __init__(self, parent=None):
# Initialize UI
super().__init__(parent)
self.setupUi(self)
# Load settings
settings = QtCore.QSettings()
self.windowLengthSpinBox.setValue(settings.value("smooth_length", 11, int))
window_function = settings.value("smooth_window", "hanning")
i = self.windowFunctionComboBox.findText(window_function)
if i == -1:
self.windowFunctionComboBox.setCurrentIndex(0)
else:
self.windowFunctionComboBox.setCurrentIndex(i)
def accept(self):
"""Save settings when dialog is accepted"""
settings = QtCore.QSettings()
settings.setValue("smooth_length", self.windowLengthSpinBox.value())
settings.setValue("smooth_window", self.windowFunctionComboBox.currentText())
QtGui.QDialog.accept(self)
class QSpectrumAnalyzerPersistence(QtGui.QDialog, Ui_QSpectrumAnalyzerPersistence):
"""QSpectrumAnalyzer spectrum persistence dialog"""
def __init__(self, parent=None):
# Initialize UI
super().__init__(parent)
self.setupUi(self)
# Load settings
settings = QtCore.QSettings()
self.persistenceLengthSpinBox.setValue(settings.value("persistence_length", 5, int))
decay_function = settings.value("persistence_decay", "exponential")
i = self.decayFunctionComboBox.findText(decay_function)
if i == -1:
self.decayFunctionComboBox.setCurrentIndex(0)
else:
self.decayFunctionComboBox.setCurrentIndex(i)
def accept(self):
"""Save settings when dialog is accepted"""
settings = QtCore.QSettings()
settings.setValue("persistence_length", self.persistenceLengthSpinBox.value())
settings.setValue("persistence_decay", self.decayFunctionComboBox.currentText())
QtGui.QDialog.accept(self)
class QSpectrumAnalyzerColors(QtGui.QDialog, Ui_QSpectrumAnalyzerColors):
"""QSpectrumAnalyzer colors dialog"""
def __init__(self, parent=None):
# Initialize UI
super().__init__(parent)
self.setupUi(self)
# Load settings
settings = QtCore.QSettings()
self.mainColorButton.setColor(str_to_color(settings.value("main_color", "255, 255, 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")))
def accept(self):
"""Save settings when dialog is accepted"""
settings = QtCore.QSettings()
settings.setValue("main_color", color_to_str(self.mainColorButton.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)
class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWindow):
"""QSpectrumAnalyzer main window"""
def __init__(self, parent=None):
# Initialize UI
super().__init__(parent)
self.setupUi(self)
# Create plot widgets and update UI # Create plot widgets and update UI
self.spectrumPlotWidget = SpectrumPlotWidget(self.mainPlotLayout) self.spectrumPlotWidget = SpectrumPlotWidget(self.mainPlotLayout)
@ -50,14 +170,9 @@ class QSpectrumAnalyzerMainWindow(QtWidgets.QMainWindow, Ui_QSpectrumAnalyzerMai
self.spectrumPlotWidget.plot.setXLink(self.waterfallPlotWidget.plot) self.spectrumPlotWidget.plot.setXLink(self.waterfallPlotWidget.plot)
# Setup power thread and connect signals # Setup power thread and connect signals
self.update_status_timer = QtCore.QTimer()
self.update_status_timer.timeout.connect(self.update_status)
self.prev_sweep_time = None
self.prev_data_timestamp = None self.prev_data_timestamp = None
self.start_timestamp = None
self.data_storage = None self.data_storage = None
self.power_thread = None self.power_thread = None
self.backend = None
self.setup_power_thread() self.setup_power_thread()
self.update_buttons() self.update_buttons()
@ -76,66 +191,45 @@ class QSpectrumAnalyzerMainWindow(QtWidgets.QMainWindow, Ui_QSpectrumAnalyzerMai
self.data_storage.data_recalculated.connect(self.spectrumPlotWidget.recalculate_plot) self.data_storage.data_recalculated.connect(self.spectrumPlotWidget.recalculate_plot)
self.data_storage.data_recalculated.connect(self.spectrumPlotWidget.recalculate_persistence) self.data_storage.data_recalculated.connect(self.spectrumPlotWidget.recalculate_persistence)
self.data_storage.history_updated.connect(self.waterfallPlotWidget.update_plot) self.data_storage.history_updated.connect(self.waterfallPlotWidget.update_plot)
self.data_storage.history_recalculated.connect(self.waterfallPlotWidget.recalculate_plot)
self.data_storage.average_updated.connect(self.spectrumPlotWidget.update_average) self.data_storage.average_updated.connect(self.spectrumPlotWidget.update_average)
self.data_storage.baseline_updated.connect(self.spectrumPlotWidget.update_baseline)
self.data_storage.peak_hold_max_updated.connect(self.spectrumPlotWidget.update_peak_hold_max) 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) self.data_storage.peak_hold_min_updated.connect(self.spectrumPlotWidget.update_peak_hold_min)
# Setup default values and limits in case that backend is changed
backend = settings.value("backend", "soapy_power") backend = settings.value("backend", "soapy_power")
try: if backend == "soapy_power":
backend_module = getattr(backends, backend) self.power_thread = SoapyPowerThread(self.data_storage)
except AttributeError: elif backend == "rx_power":
backend_module = backends.soapy_power self.power_thread = RxPowerThread(self.data_storage)
elif backend == "rtl_power_fftw":
self.power_thread = RtlPowerFftwThread(self.data_storage)
elif backend == "hackrf_sweep":
self.gainSpinBox.setMinimum(0)
self.gainSpinBox.setMaximum(102)
self.gainSpinBox.setValue(40)
self.startFreqSpinBox.setMinimum(0)
self.startFreqSpinBox.setMaximum(7230)
self.startFreqSpinBox.setValue(0)
self.stopFreqSpinBox.setMinimum(0)
self.stopFreqSpinBox.setMaximum(7250)
self.stopFreqSpinBox.setValue(6000)
self.binSizeSpinBox.setMinimum(40)
self.binSizeSpinBox.setMaximum(5000)
self.binSizeSpinBox.setValue(1000)
self.intervalSpinBox.setMinimum(0)
self.intervalSpinBox.setMaximum(0)
self.intervalSpinBox.setValue(0)
self.ppmSpinBox.setMinimum(0)
self.ppmSpinBox.setMaximum(0)
self.ppmSpinBox.setValue(0)
self.cropSpinBox.setMinimum(0)
self.cropSpinBox.setMaximum(0)
self.cropSpinBox.setValue(0)
self.power_thread = HackRFSweepThread(self.data_storage)
else:
self.power_thread = RtlPowerThread(self.data_storage)
if self.backend is None or backend != self.backend: self.power_thread.powerThreadStarted.connect(self.update_buttons)
self.backend = backend self.power_thread.powerThreadStopped.connect(self.update_buttons)
self.gainSpinBox.setMinimum(backend_module.Info.gain_min)
self.gainSpinBox.setMaximum(backend_module.Info.gain_max)
self.gainSpinBox.setValue(backend_module.Info.gain)
self.startFreqSpinBox.setMinimum(backend_module.Info.start_freq_min)
self.startFreqSpinBox.setMaximum(backend_module.Info.start_freq_max)
self.startFreqSpinBox.setValue(backend_module.Info.start_freq)
self.stopFreqSpinBox.setMinimum(backend_module.Info.stop_freq_min)
self.stopFreqSpinBox.setMaximum(backend_module.Info.stop_freq_max)
self.stopFreqSpinBox.setValue(backend_module.Info.stop_freq)
self.binSizeSpinBox.setMinimum(backend_module.Info.bin_size_min)
self.binSizeSpinBox.setMaximum(backend_module.Info.bin_size_max)
self.binSizeSpinBox.setValue(backend_module.Info.bin_size)
self.intervalSpinBox.setMinimum(backend_module.Info.interval_min)
self.intervalSpinBox.setMaximum(backend_module.Info.interval_max)
self.intervalSpinBox.setValue(backend_module.Info.interval)
self.ppmSpinBox.setMinimum(backend_module.Info.ppm_min)
self.ppmSpinBox.setMaximum(backend_module.Info.ppm_max)
self.ppmSpinBox.setValue(backend_module.Info.ppm)
self.cropSpinBox.setMinimum(backend_module.Info.crop_min)
self.cropSpinBox.setMaximum(backend_module.Info.crop_max)
self.cropSpinBox.setValue(backend_module.Info.crop)
# Setup default values and limits in case that LNB LO is changed
lnb_lo = settings.value("lnb_lo", 0, float) / 1e6
start_freq_min = backend_module.Info.start_freq_min + lnb_lo
start_freq_max = backend_module.Info.start_freq_max + lnb_lo
start_freq = self.startFreqSpinBox.value()
stop_freq_min = backend_module.Info.stop_freq_min + lnb_lo
stop_freq_max = backend_module.Info.stop_freq_max + lnb_lo
stop_freq = self.stopFreqSpinBox.value()
self.startFreqSpinBox.setMinimum(start_freq_min if start_freq_min > 0 else 0)
self.startFreqSpinBox.setMaximum(start_freq_max)
if start_freq < start_freq_min or start_freq > start_freq_max:
self.startFreqSpinBox.setValue(start_freq_min)
self.stopFreqSpinBox.setMinimum(stop_freq_min if stop_freq_min > 0 else 0)
self.stopFreqSpinBox.setMaximum(stop_freq_max)
if stop_freq < stop_freq_min or stop_freq > stop_freq_max:
self.stopFreqSpinBox.setValue(stop_freq_max)
self.power_thread = backend_module.PowerThread(self.data_storage)
self.power_thread.powerThreadStarted.connect(self.on_power_thread_started)
self.power_thread.powerThreadStopped.connect(self.on_power_thread_stopped)
def set_dock_size(self, dock, width, height): def set_dock_size(self, dock, width, height):
"""Ugly hack for resizing QDockWidget (because it doesn't respect minimumSize / sizePolicy set in Designer) """Ugly hack for resizing QDockWidget (because it doesn't respect minimumSize / sizePolicy set in Designer)
@ -169,7 +263,7 @@ class QSpectrumAnalyzerMainWindow(QtWidgets.QMainWindow, Ui_QSpectrumAnalyzerMai
self.stopFreqSpinBox.setValue(settings.value("stop_freq", 108.0, float)) self.stopFreqSpinBox.setValue(settings.value("stop_freq", 108.0, float))
self.binSizeSpinBox.setValue(settings.value("bin_size", 10.0, float)) self.binSizeSpinBox.setValue(settings.value("bin_size", 10.0, float))
self.intervalSpinBox.setValue(settings.value("interval", 10.0, float)) self.intervalSpinBox.setValue(settings.value("interval", 10.0, float))
self.gainSpinBox.setValue(settings.value("gain", 0, float)) self.gainSpinBox.setValue(settings.value("gain", 0, int))
self.ppmSpinBox.setValue(settings.value("ppm", 0, int)) self.ppmSpinBox.setValue(settings.value("ppm", 0, int))
self.cropSpinBox.setValue(settings.value("crop", 0, int)) self.cropSpinBox.setValue(settings.value("crop", 0, int))
self.mainCurveCheckBox.setChecked(settings.value("main_curve", 1, int)) self.mainCurveCheckBox.setChecked(settings.value("main_curve", 1, int))
@ -178,8 +272,6 @@ class QSpectrumAnalyzerMainWindow(QtWidgets.QMainWindow, Ui_QSpectrumAnalyzerMai
self.averageCheckBox.setChecked(settings.value("average", 0, int)) self.averageCheckBox.setChecked(settings.value("average", 0, int))
self.smoothCheckBox.setChecked(settings.value("smooth", 0, int)) self.smoothCheckBox.setChecked(settings.value("smooth", 0, int))
self.persistenceCheckBox.setChecked(settings.value("persistence", 0, int)) self.persistenceCheckBox.setChecked(settings.value("persistence", 0, int))
self.baselineCheckBox.setChecked(settings.value("baseline", 0, int))
self.subtractBaselineCheckBox.setChecked(settings.value("subtract_baseline", 0, int))
# Restore window state # Restore window state
if settings.value("window_state"): if settings.value("window_state"):
@ -219,8 +311,6 @@ class QSpectrumAnalyzerMainWindow(QtWidgets.QMainWindow, Ui_QSpectrumAnalyzerMai
settings.setValue("average", int(self.averageCheckBox.isChecked())) settings.setValue("average", int(self.averageCheckBox.isChecked()))
settings.setValue("smooth", int(self.smoothCheckBox.isChecked())) settings.setValue("smooth", int(self.smoothCheckBox.isChecked()))
settings.setValue("persistence", int(self.persistenceCheckBox.isChecked())) settings.setValue("persistence", int(self.persistenceCheckBox.isChecked()))
settings.setValue("baseline", int(self.baselineCheckBox.isChecked()))
settings.setValue("subtract_baseline", int(self.subtractBaselineCheckBox.isChecked()))
# Save window state and geometry # Save window state and geometry
settings.setValue("window_geometry", self.saveGeometry()) settings.setValue("window_geometry", self.saveGeometry())
@ -239,72 +329,32 @@ class QSpectrumAnalyzerMainWindow(QtWidgets.QMainWindow, Ui_QSpectrumAnalyzerMai
def update_data(self, data_storage): def update_data(self, data_storage):
"""Update GUI when new data is received""" """Update GUI when new data is received"""
# Show number of hops and how much time did the sweep really take
timestamp = time.time() timestamp = time.time()
self.prev_sweep_time = timestamp - self.prev_data_timestamp sweep_time = timestamp - self.prev_data_timestamp
self.prev_data_timestamp = timestamp self.prev_data_timestamp = timestamp
self.update_status()
def update_status(self): self.show_status(
"""Update status bar""" self.tr("Frequency hops: {} | Sweep time: {:.2f} s | FPS: {:.2f}").format(
timestamp = time.time() self.power_thread.params["hops"] or self.tr("N/A"),
status = [] sweep_time,
1 / sweep_time
if self.power_thread.params["hops"]: ),
status.append(self.tr("Frequency hops: {}").format(self.power_thread.params["hops"])) timeout=0
)
status.append(self.tr("Total time: {} | Sweep time: {:.2f} s ({:.2f} FPS)").format(
human_time(timestamp - self.start_timestamp),
self.prev_sweep_time,
(1 / self.prev_sweep_time) if self.prev_sweep_time else 0
))
self.show_status(" | ".join(status), timeout=0)
self.update_progress(timestamp - self.prev_data_timestamp)
def update_progress(self, value):
"""Update progress bar"""
value *= 1000
value_max = self.intervalSpinBox.value() * 1000
if value_max < 1000:
return
if value > value_max + 1000:
self.progressbar.setRange(0, 0)
value = value_max
elif value > value_max:
value = value_max
else:
self.progressbar.setRange(0, value_max)
self.progressbar.setValue(value)
def on_power_thread_started(self):
"""Update buttons state when power thread is started"""
self.update_buttons()
self.progressbar.setVisible(True)
def on_power_thread_stopped(self):
"""Update buttons state and status bar when power thread is stopped"""
self.update_buttons()
self.update_status_timer.stop()
self.update_status()
self.progressbar.setVisible(False)
def start(self, single_shot=False): def start(self, single_shot=False):
"""Start power thread""" """Start power thread"""
settings = QtCore.QSettings() settings = QtCore.QSettings()
self.prev_sweep_time = 0
self.prev_data_timestamp = time.time() self.prev_data_timestamp = time.time()
self.start_timestamp = self.prev_data_timestamp
if self.intervalSpinBox.value() >= 1: self.data_storage.reset()
self.progressbar.setRange(0, self.intervalSpinBox.value() * 1000) self.data_storage.set_smooth(
else: bool(self.smoothCheckBox.isChecked()),
self.progressbar.setRange(0, 0) settings.value("smooth_length", 11, int),
self.update_progress(0) settings.value("smooth_window", "hanning"),
self.update_status_timer.start(100) recalculate=False
)
self.waterfallPlotWidget.history_size = settings.value("waterfall_history_size", 100, int) self.waterfallPlotWidget.history_size = settings.value("waterfall_history_size", 100, int)
self.waterfallPlotWidget.clear_plot() self.waterfallPlotWidget.clear_plot()
@ -317,8 +367,6 @@ class QSpectrumAnalyzerMainWindow(QtWidgets.QMainWindow, Ui_QSpectrumAnalyzerMai
self.spectrumPlotWidget.peak_hold_min_color = str_to_color(settings.value("peak_hold_min_color", "0, 0, 255, 255")) 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 = bool(self.averageCheckBox.isChecked())
self.spectrumPlotWidget.average_color = str_to_color(settings.value("average_color", "0, 255, 255, 255")) self.spectrumPlotWidget.average_color = str_to_color(settings.value("average_color", "0, 255, 255, 255"))
self.spectrumPlotWidget.baseline = bool(self.baselineCheckBox.isChecked())
self.spectrumPlotWidget.baseline_color = str_to_color(settings.value("baseline_color", "255, 0, 255, 255"))
self.spectrumPlotWidget.persistence = bool(self.persistenceCheckBox.isChecked()) self.spectrumPlotWidget.persistence = bool(self.persistenceCheckBox.isChecked())
self.spectrumPlotWidget.persistence_length = settings.value("persistence_length", 5, int) self.spectrumPlotWidget.persistence_length = settings.value("persistence_length", 5, int)
self.spectrumPlotWidget.persistence_decay = settings.value("persistence_decay", "exponential") self.spectrumPlotWidget.persistence_decay = settings.value("persistence_decay", "exponential")
@ -327,35 +375,19 @@ class QSpectrumAnalyzerMainWindow(QtWidgets.QMainWindow, Ui_QSpectrumAnalyzerMai
self.spectrumPlotWidget.clear_peak_hold_max() self.spectrumPlotWidget.clear_peak_hold_max()
self.spectrumPlotWidget.clear_peak_hold_min() self.spectrumPlotWidget.clear_peak_hold_min()
self.spectrumPlotWidget.clear_average() self.spectrumPlotWidget.clear_average()
self.spectrumPlotWidget.clear_baseline()
self.spectrumPlotWidget.clear_persistence() self.spectrumPlotWidget.clear_persistence()
self.data_storage.reset()
self.data_storage.set_smooth(
bool(self.smoothCheckBox.isChecked()),
settings.value("smooth_length", 11, int),
settings.value("smooth_window", "hanning")
)
self.data_storage.set_subtract_baseline(
bool(self.subtractBaselineCheckBox.isChecked()),
settings.value("baseline_file", None)
)
if not self.power_thread.alive: if not self.power_thread.alive:
self.power_thread.setup( self.power_thread.setup(float(self.startFreqSpinBox.value()),
float(self.startFreqSpinBox.value()), float(self.stopFreqSpinBox.value()),
float(self.stopFreqSpinBox.value()), float(self.binSizeSpinBox.value()),
float(self.binSizeSpinBox.value()), interval=float(self.intervalSpinBox.value()),
interval=float(self.intervalSpinBox.value()), gain=int(self.gainSpinBox.value()),
gain=float(self.gainSpinBox.value()), ppm=int(self.ppmSpinBox.value()),
ppm=int(self.ppmSpinBox.value()), crop=int(self.cropSpinBox.value()) / 100.0,
crop=int(self.cropSpinBox.value()) / 100.0, single_shot=single_shot,
single_shot=single_shot, device=settings.value("device", ""),
device=settings.value("device", ""), sample_rate=settings.value("sample_rate", 2560000, int))
sample_rate=settings.value("sample_rate", 2560000, float),
bandwidth=settings.value("bandwidth", 0, float),
lnb_lo=settings.value("lnb_lo", 0, float)
)
self.power_thread.start() self.power_thread.start()
def stop(self): def stop(self):
@ -363,47 +395,47 @@ class QSpectrumAnalyzerMainWindow(QtWidgets.QMainWindow, Ui_QSpectrumAnalyzerMai
if self.power_thread.alive: if self.power_thread.alive:
self.power_thread.stop() self.power_thread.stop()
@QtCore.Slot() @QtCore.pyqtSlot()
def on_startButton_clicked(self): def on_startButton_clicked(self):
self.start() self.start()
@QtCore.Slot() @QtCore.pyqtSlot()
def on_singleShotButton_clicked(self): def on_singleShotButton_clicked(self):
self.start(single_shot=True) self.start(single_shot=True)
@QtCore.Slot() @QtCore.pyqtSlot()
def on_stopButton_clicked(self): def on_stopButton_clicked(self):
self.stop() self.stop()
@QtCore.Slot(bool) @QtCore.pyqtSlot(bool)
def on_mainCurveCheckBox_toggled(self, checked): def on_mainCurveCheckBox_toggled(self, checked):
self.spectrumPlotWidget.main_curve = checked self.spectrumPlotWidget.main_curve = checked
if self.spectrumPlotWidget.curve.xData is None: if self.spectrumPlotWidget.curve.xData is None:
self.spectrumPlotWidget.update_plot(self.data_storage) self.spectrumPlotWidget.update_plot(self.data_storage)
self.spectrumPlotWidget.curve.setVisible(checked) self.spectrumPlotWidget.curve.setVisible(checked)
@QtCore.Slot(bool) @QtCore.pyqtSlot(bool)
def on_peakHoldMaxCheckBox_toggled(self, checked): def on_peakHoldMaxCheckBox_toggled(self, checked):
self.spectrumPlotWidget.peak_hold_max = checked self.spectrumPlotWidget.peak_hold_max = checked
if self.spectrumPlotWidget.curve_peak_hold_max.xData is None: if self.spectrumPlotWidget.curve_peak_hold_max.xData is None:
self.spectrumPlotWidget.update_peak_hold_max(self.data_storage) self.spectrumPlotWidget.update_peak_hold_max(self.data_storage)
self.spectrumPlotWidget.curve_peak_hold_max.setVisible(checked) self.spectrumPlotWidget.curve_peak_hold_max.setVisible(checked)
@QtCore.Slot(bool) @QtCore.pyqtSlot(bool)
def on_peakHoldMinCheckBox_toggled(self, checked): def on_peakHoldMinCheckBox_toggled(self, checked):
self.spectrumPlotWidget.peak_hold_min = checked self.spectrumPlotWidget.peak_hold_min = checked
if self.spectrumPlotWidget.curve_peak_hold_min.xData is None: if self.spectrumPlotWidget.curve_peak_hold_min.xData is None:
self.spectrumPlotWidget.update_peak_hold_min(self.data_storage) self.spectrumPlotWidget.update_peak_hold_min(self.data_storage)
self.spectrumPlotWidget.curve_peak_hold_min.setVisible(checked) self.spectrumPlotWidget.curve_peak_hold_min.setVisible(checked)
@QtCore.Slot(bool) @QtCore.pyqtSlot(bool)
def on_averageCheckBox_toggled(self, checked): def on_averageCheckBox_toggled(self, checked):
self.spectrumPlotWidget.average = checked self.spectrumPlotWidget.average = checked
if self.spectrumPlotWidget.curve_average.xData is None: if self.spectrumPlotWidget.curve_average.xData is None:
self.spectrumPlotWidget.update_average(self.data_storage) self.spectrumPlotWidget.update_average(self.data_storage)
self.spectrumPlotWidget.curve_average.setVisible(checked) self.spectrumPlotWidget.curve_average.setVisible(checked)
@QtCore.Slot(bool) @QtCore.pyqtSlot(bool)
def on_persistenceCheckBox_toggled(self, checked): def on_persistenceCheckBox_toggled(self, checked):
self.spectrumPlotWidget.persistence = checked self.spectrumPlotWidget.persistence = checked
if self.spectrumPlotWidget.persistence_curves[0].xData is None: if self.spectrumPlotWidget.persistence_curves[0].xData is None:
@ -411,52 +443,29 @@ class QSpectrumAnalyzerMainWindow(QtWidgets.QMainWindow, Ui_QSpectrumAnalyzerMai
for curve in self.spectrumPlotWidget.persistence_curves: for curve in self.spectrumPlotWidget.persistence_curves:
curve.setVisible(checked) curve.setVisible(checked)
@QtCore.Slot(bool) @QtCore.pyqtSlot(bool)
def on_smoothCheckBox_toggled(self, checked): def on_smoothCheckBox_toggled(self, checked):
settings = QtCore.QSettings() settings = QtCore.QSettings()
self.data_storage.set_smooth( self.data_storage.set_smooth(
checked, checked,
settings.value("smooth_length", 11, int), settings.value("smooth_length", 11, int),
settings.value("smooth_window", "hanning") settings.value("smooth_window", "hanning"),
recalculate=True
) )
@QtCore.Slot(bool) @QtCore.pyqtSlot()
def on_baselineCheckBox_toggled(self, checked):
self.spectrumPlotWidget.baseline = checked
if self.spectrumPlotWidget.curve_baseline.xData is None:
self.spectrumPlotWidget.update_baseline(self.data_storage)
self.spectrumPlotWidget.curve_baseline.setVisible(checked)
@QtCore.Slot(bool)
def on_subtractBaselineCheckBox_toggled(self, checked):
settings = QtCore.QSettings()
self.data_storage.set_subtract_baseline(
checked,
settings.value("baseline_file", None)
)
@QtCore.Slot()
def on_baselineButton_clicked(self):
dialog = QSpectrumAnalyzerBaseline(self)
if dialog.exec_():
settings = QtCore.QSettings()
self.data_storage.set_subtract_baseline(
bool(self.subtractBaselineCheckBox.isChecked()),
settings.value("baseline_file", None)
)
@QtCore.Slot()
def on_smoothButton_clicked(self): def on_smoothButton_clicked(self):
dialog = QSpectrumAnalyzerSmoothing(self) dialog = QSpectrumAnalyzerSmooth(self)
if dialog.exec_(): if dialog.exec_():
settings = QtCore.QSettings() settings = QtCore.QSettings()
self.data_storage.set_smooth( self.data_storage.set_smooth(
bool(self.smoothCheckBox.isChecked()), bool(self.smoothCheckBox.isChecked()),
settings.value("smooth_length", 11, int), settings.value("smooth_length", 11, int),
settings.value("smooth_window", "hanning") settings.value("smooth_window", "hanning"),
recalculate=True
) )
@QtCore.Slot() @QtCore.pyqtSlot()
def on_persistenceButton_clicked(self): def on_persistenceButton_clicked(self):
prev_persistence_length = self.spectrumPlotWidget.persistence_length prev_persistence_length = self.spectrumPlotWidget.persistence_length
dialog = QSpectrumAnalyzerPersistence(self) dialog = QSpectrumAnalyzerPersistence(self)
@ -472,7 +481,7 @@ class QSpectrumAnalyzerMainWindow(QtWidgets.QMainWindow, Ui_QSpectrumAnalyzerMai
else: else:
self.spectrumPlotWidget.recalculate_persistence(self.data_storage) self.spectrumPlotWidget.recalculate_persistence(self.data_storage)
@QtCore.Slot() @QtCore.pyqtSlot()
def on_colorsButton_clicked(self): def on_colorsButton_clicked(self):
dialog = QSpectrumAnalyzerColors(self) dialog = QSpectrumAnalyzerColors(self)
if dialog.exec_(): if dialog.exec_():
@ -482,21 +491,20 @@ class QSpectrumAnalyzerMainWindow(QtWidgets.QMainWindow, Ui_QSpectrumAnalyzerMai
self.spectrumPlotWidget.peak_hold_min_color = str_to_color(settings.value("peak_hold_min_color", "0, 0, 255, 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.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.persistence_color = str_to_color(settings.value("persistence_color", "0, 255, 0, 255"))
self.spectrumPlotWidget.baseline_color = str_to_color(settings.value("baseline_color", "255, 0, 255, 255"))
self.spectrumPlotWidget.set_colors() self.spectrumPlotWidget.set_colors()
@QtCore.Slot() @QtCore.pyqtSlot()
def on_action_Settings_triggered(self): def on_action_Settings_triggered(self):
dialog = QSpectrumAnalyzerSettings(self) dialog = QSpectrumAnalyzerSettings(self)
if dialog.exec_(): if dialog.exec_():
self.setup_power_thread() self.setup_power_thread()
@QtCore.Slot() @QtCore.pyqtSlot()
def on_action_About_triggered(self): def on_action_About_triggered(self):
QtWidgets.QMessageBox.information(self, self.tr("About - QSpectrumAnalyzer"), QtGui.QMessageBox.information(self, self.tr("About - QSpectrumAnalyzer"),
self.tr("QSpectrumAnalyzer {}").format(__version__)) self.tr("QSpectrumAnalyzer {}").format(__version__))
@QtCore.Slot() @QtCore.pyqtSlot()
def on_action_Quit_triggered(self): def on_action_Quit_triggered(self):
self.close() self.close()
@ -507,37 +515,12 @@ class QSpectrumAnalyzerMainWindow(QtWidgets.QMainWindow, Ui_QSpectrumAnalyzerMai
def main(): def main():
global debug app = QtGui.QApplication(sys.argv)
app.setOrganizationName("QSpectrumAnalyzer")
# Parse command line arguments app.setOrganizationDomain("qspectrumanalyzer.eutopia.cz")
parser = argparse.ArgumentParser( app.setApplicationName("QSpectrumAnalyzer")
prog="qspectrumanalyzer", window = QSpectrumAnalyzerMainWindow()
description="Spectrum analyzer for multiple SDR platforms", sys.exit(app.exec_())
)
parser.add_argument("--debug", action="store_true",
help="detailed debugging messages")
parser.add_argument("--version", action="version",
version="%(prog)s {}".format(__version__))
args, unparsed_args = parser.parse_known_args()
debug = args.debug
try:
# Hide console window on Windows
if sys.platform == 'win32' and not debug:
from qspectrumanalyzer import windows
windows.set_attached_console_visible(False)
# Start PyQt application
app = QtWidgets.QApplication(sys.argv[:1] + unparsed_args)
app.setOrganizationName("QSpectrumAnalyzer")
app.setOrganizationDomain("qspectrumanalyzer.eutopia.cz")
app.setApplicationName("QSpectrumAnalyzer")
window = QSpectrumAnalyzerMainWindow()
sys.exit(app.exec_())
finally:
# Unhide console window on Windows (we don't want to leave zombies behind)
if sys.platform == 'win32' and not debug:
windows.set_attached_console_visible(True)
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -0,0 +1,566 @@
import subprocess, math, pprint, re
import numpy as np
from PyQt4 import QtCore
import struct
class BasePowerThread(QtCore.QThread):
"""Thread which runs Power Spectral Density acquisition and calculation process"""
powerThreadStarted = QtCore.pyqtSignal()
powerThreadStopped = QtCore.pyqtSignal()
def __init__(self, data_storage, parent=None):
super().__init__(parent)
self.data_storage = data_storage
self.alive = False
self.process = None
def stop(self):
"""Stop power process thread"""
self.process_stop()
self.alive = False
self.wait()
def setup(self, start_freq, stop_freq, bin_size, interval=10.0, gain=-1,
ppm=0, crop=0, single_shot=False, device=0, sample_rate=2560000):
"""Setup power process params"""
raise NotImplementedError
def process_start(self):
"""Start power process"""
raise NotImplementedError
def process_stop(self):
"""Terminate power process"""
if self.process:
try:
self.process.terminate()
except ProcessLookupError:
pass
self.process.wait()
self.process = None
def parse_output(self, line):
"""Parse one line of output from power process"""
raise NotImplementedError
def run(self):
"""Power process thread main loop"""
self.process_start()
self.alive = True
self.powerThreadStarted.emit()
for line in self.process.stdout:
if not self.alive:
break
self.parse_output(line)
self.process_stop()
self.alive = False
self.powerThreadStopped.emit()
class RxPowerThread(BasePowerThread):
"""Thread which runs rx_power process"""
def setup(self, start_freq, stop_freq, bin_size, interval=10.0, gain=-1,
ppm=0, crop=0, single_shot=False, device=0, sample_rate=2560000):
"""Setup rx_power params"""
self.params = {
"start_freq": start_freq,
"stop_freq": stop_freq,
"bin_size": bin_size,
"interval": interval,
"device": device,
"hops": 0,
"gain": gain,
"ppm": ppm,
"crop": crop,
"single_shot": single_shot
}
self.databuffer = {}
self.last_timestamp = ""
print("rx_power params:")
pprint.pprint(self.params)
print()
def process_start(self):
"""Start rx_power process"""
if not self.process and self.params:
settings = QtCore.QSettings()
cmdline = [
settings.value("executable", "rx_power"),
"-f", "{}M:{}M:{}k".format(self.params["start_freq"],
self.params["stop_freq"],
self.params["bin_size"]),
"-i", "{}".format(self.params["interval"]),
"-d", "{}".format(self.params["device"]),
"-p", "{}".format(self.params["ppm"]),
"-c", "{}".format(self.params["crop"])
]
if self.params["gain"] >= 0:
cmdline.extend(["-g", "{}".format(self.params["gain"])])
if self.params["single_shot"]:
cmdline.append("-1")
self.process = subprocess.Popen(cmdline, stdout=subprocess.PIPE,
universal_newlines=True)
def parse_output(self, line):
"""Parse one line of output from rx_power"""
line = [col.strip() for col in line.split(",")]
timestamp = " ".join(line[:2])
start_freq = int(line[2])
stop_freq = int(line[3])
step = float(line[4])
samples = float(line[5])
x_axis = list(np.arange(start_freq, stop_freq, step))
y_axis = [float(y) for y in line[6:]]
if len(x_axis) != len(y_axis):
print("ERROR: len(x_axis) != len(y_axis), use newer version of rx_power!")
if len(x_axis) > len(y_axis):
print("Trimming x_axis...")
x_axis = x_axis[:len(y_axis)]
else:
print("Trimming y_axis...")
y_axis = y_axis[:len(x_axis)]
if timestamp != self.last_timestamp:
self.last_timestamp = timestamp
self.databuffer = {"timestamp": timestamp,
"x": x_axis,
"y": y_axis}
else:
self.databuffer["x"].extend(x_axis)
self.databuffer["y"].extend(y_axis)
# This have to be stupid like this to be compatible with old broken version of rx_power. Right way is:
# if stop_freq == self.params["stop_freq"] * 1e6:
if stop_freq > (self.params["stop_freq"] * 1e6) - step:
self.data_storage.update(self.databuffer)
class RtlPowerThread(BasePowerThread):
"""Thread which runs rtl_power process"""
def setup(self, start_freq, stop_freq, bin_size, interval=10.0, gain=-1,
ppm=0, crop=0, single_shot=False, device=0, sample_rate=2560000):
"""Setup rtl_power params"""
if bin_size > 2800:
bin_size = 2800
self.params = {
"start_freq": start_freq,
"stop_freq": stop_freq,
"bin_size": bin_size,
"interval": interval,
"device": device,
"hops": 0,
"gain": gain,
"ppm": ppm,
"crop": crop,
"single_shot": single_shot
}
self.databuffer = {}
self.last_timestamp = ""
print("rtl_power params:")
pprint.pprint(self.params)
print()
def process_start(self):
"""Start rtl_power process"""
if not self.process and self.params:
settings = QtCore.QSettings()
cmdline = [
settings.value("executable", "rtl_power"),
"-f", "{}M:{}M:{}k".format(self.params["start_freq"],
self.params["stop_freq"],
self.params["bin_size"]),
"-i", "{}".format(self.params["interval"]),
"-d", "{}".format(self.params["device"]),
"-p", "{}".format(self.params["ppm"]),
"-c", "{}".format(self.params["crop"])
]
if self.params["gain"] >= 0:
cmdline.extend(["-g", "{}".format(self.params["gain"])])
if self.params["single_shot"]:
cmdline.append("-1")
self.process = subprocess.Popen(cmdline, stdout=subprocess.PIPE,
universal_newlines=True)
def parse_output(self, line):
"""Parse one line of output from rtl_power"""
line = [col.strip() for col in line.split(",")]
timestamp = " ".join(line[:2])
start_freq = int(line[2])
stop_freq = int(line[3])
step = float(line[4])
samples = float(line[5])
x_axis = list(np.arange(start_freq, stop_freq, step))
y_axis = [float(y) for y in line[6:]]
if len(x_axis) != len(y_axis):
print("ERROR: len(x_axis) != len(y_axis), use newer version of rtl_power!")
if len(x_axis) > len(y_axis):
print("Trimming x_axis...")
x_axis = x_axis[:len(y_axis)]
else:
print("Trimming y_axis...")
y_axis = y_axis[:len(x_axis)]
if timestamp != self.last_timestamp:
self.last_timestamp = timestamp
self.databuffer = {"timestamp": timestamp,
"x": x_axis,
"y": y_axis}
else:
self.databuffer["x"].extend(x_axis)
self.databuffer["y"].extend(y_axis)
# 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.data_storage.update(self.databuffer)
class RtlPowerFftwThread(BasePowerThread):
"""Thread which runs rtl_power_fftw process"""
def setup(self, start_freq, stop_freq, bin_size, interval=10.0, gain=-1,
ppm=0, crop=0, single_shot=False, device=0, sample_rate=2560000):
"""Setup rtl_power_fftw params"""
crop = crop * 100
overlap = crop * 2
freq_range = stop_freq * 1e6 - start_freq * 1e6
min_overhang = sample_rate * overlap * 0.01
hops = math.ceil((freq_range - min_overhang) / (sample_rate - min_overhang))
overhang = (hops * sample_rate - freq_range) / (hops - 1) if hops > 1 else 0
if bin_size > 2800:
bin_size = 2800
bins = math.ceil(sample_rate / (bin_size * 1e3))
crop_freq = sample_rate * crop * 0.01
self.params = {
"start_freq": start_freq,
"stop_freq": stop_freq,
"freq_range": freq_range,
"device": device,
"sample_rate": sample_rate,
"bin_size": bin_size,
"bins": bins,
"interval": interval,
"hops": hops,
"time": interval / hops,
"gain": gain * 10,
"ppm": ppm,
"crop": crop,
"overlap": overlap,
"min_overhang": min_overhang,
"overhang": overhang,
"single_shot": single_shot
}
self.freqs = [self.get_hop_freq(hop) for hop in range(hops)]
self.freqs_crop = [(f[0] + crop_freq, f[1] - crop_freq) for f in self.freqs]
self.databuffer = {"timestamp": [], "x": [], "y": []}
self.databuffer_hop = {"timestamp": [], "x": [], "y": []}
self.hop = 0
self.prev_line = ""
print("rtl_power_fftw params:")
pprint.pprint(self.params)
print()
def get_hop_freq(self, hop):
"""Get start and stop frequency for particular hop"""
start_freq = self.params["start_freq"] * 1e6 + (self.params["sample_rate"] - self.params["overhang"]) * hop
stop_freq = start_freq + self.params["sample_rate"] - (self.params["sample_rate"] / self.params["bins"])
return (start_freq, stop_freq)
def process_start(self):
"""Start rtl_power_fftw process"""
if not self.process and self.params:
settings = QtCore.QSettings()
cmdline = [
settings.value("executable", "rtl_power_fftw"),
"-f", "{}M:{}M".format(self.params["start_freq"],
self.params["stop_freq"]),
"-b", "{}".format(self.params["bins"]),
"-t", "{}".format(self.params["time"]),
"-d", "{}".format(self.params["device"]),
"-r", "{}".format(self.params["sample_rate"]),
"-p", "{}".format(self.params["ppm"]),
]
if self.params["gain"] >= 0:
cmdline.extend(["-g", "{}".format(self.params["gain"])])
if self.params["overlap"] > 0:
cmdline.extend(["-o", "{}".format(self.params["overlap"])])
if not self.params["single_shot"]:
cmdline.append("-c")
self.process = subprocess.Popen(cmdline, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL,
universal_newlines=True)
def parse_output(self, line):
"""Parse one line of output from rtl_power_fftw"""
line = line.strip()
# One empty line => new hop
if not line and self.prev_line:
self.hop += 1
self.databuffer["x"].extend(self.databuffer_hop["x"])
self.databuffer["y"].extend(self.databuffer_hop["y"])
self.databuffer_hop = {"timestamp": [], "x": [], "y": []}
# Two empty lines => new set
elif not line and not self.prev_line:
self.hop = 0
self.data_storage.update(self.databuffer)
self.databuffer = {"timestamp": [], "x": [], "y": []}
# Get timestamp for new hop and set
elif line.startswith("# Acquisition start:"):
timestamp = line.split(":", 1)[1].strip()
if not self.databuffer_hop["timestamp"]:
self.databuffer_hop["timestamp"] = timestamp
if not self.databuffer["timestamp"]:
self.databuffer["timestamp"] = timestamp
# Skip other comments
elif line.startswith("#"):
pass
# Parse frequency and power
elif line[0].isdigit():
freq, power = line.split()
freq, power = float(freq), float(power)
start_freq, stop_freq = self.freqs_crop[self.hop]
# Apply cropping
if freq >= start_freq and freq <= stop_freq:
# Skip overlapping frequencies
if not self.databuffer["x"] or freq > self.databuffer["x"][-1]:
#print(" {:.3f} MHz".format(freq / 1e6))
self.databuffer_hop["x"].append(freq)
self.databuffer_hop["y"].append(power)
else:
#print(" Overlapping {:.3f} MHz".format(freq / 1e6))
pass
else:
#print(" Cropping {:.3f} MHz".format(freq / 1e6))
pass
self.prev_line = line
class SoapyPowerThread(BasePowerThread):
"""Thread which runs soapy_power process"""
re_two_floats = re.compile(r'^[-+\d.eE]+\s+[-+\d.eE]+$')
def setup(self, start_freq, stop_freq, bin_size, interval=10.0, gain=-1,
ppm=0, crop=0, single_shot=False, device="", sample_rate=2560000):
"""Setup soapy_power params"""
self.params = {
"start_freq": start_freq,
"stop_freq": stop_freq,
"device": device,
"sample_rate": sample_rate,
"bin_size": bin_size,
"interval": interval,
"hops": 0,
"gain": gain * 10,
"ppm": ppm,
"crop": crop * 100,
"single_shot": single_shot
}
self.databuffer = {"timestamp": [], "x": [], "y": []}
self.databuffer_hop = {"timestamp": [], "x": [], "y": []}
self.hop = 0
self.run = 0
self.prev_line = ""
print("soapy_power params:")
pprint.pprint(self.params)
print()
def process_start(self):
"""Start soapy_power process"""
if not self.process and self.params:
settings = QtCore.QSettings()
cmdline = [
settings.value("executable", "soapy_power"),
"-f", "{}M:{}M".format(self.params["start_freq"],
self.params["stop_freq"]),
"-B", "{}k".format(self.params["bin_size"]),
"-T", "{}".format(self.params["interval"]),
"-d", "{}".format(self.params["device"]),
"-r", "{}".format(self.params["sample_rate"]),
"-p", "{}".format(self.params["ppm"]),
]
if self.params["gain"] >= 0:
cmdline.extend(["-g", "{}".format(self.params["gain"])])
if self.params["crop"] > 0:
cmdline.extend(["-k", "{}".format(self.params["crop"])])
if not self.params["single_shot"]:
cmdline.append("-c")
self.process = subprocess.Popen(cmdline, stdout=subprocess.PIPE,
universal_newlines=True)
def parse_output(self, line):
"""Parse one line of output from soapy_power"""
line = line.strip()
# One empty line => new hop
if not line and self.prev_line:
self.hop += 1
print(' => HOP:', self.hop)
self.databuffer["x"].extend(self.databuffer_hop["x"])
self.databuffer["y"].extend(self.databuffer_hop["y"])
self.databuffer_hop = {"timestamp": [], "x": [], "y": []}
# Two empty lines => new set
elif not line and not self.prev_line:
self.hop = 0
self.run += 1
print(' * RUN:', self.run)
self.data_storage.update(self.databuffer)
self.databuffer = {"timestamp": [], "x": [], "y": []}
# Get timestamp for new hop and set
elif line.startswith("# Acquisition start:"):
timestamp = line.split(":", 1)[1].strip()
if not self.databuffer_hop["timestamp"]:
self.databuffer_hop["timestamp"] = timestamp
if not self.databuffer["timestamp"]:
self.databuffer["timestamp"] = timestamp
# Skip other comments
elif line.startswith("#"):
pass
# Parse frequency and power
elif self.re_two_floats.match(line):
try:
freq, power = line.split()
except ValueError:
return
freq, power = float(freq), float(power)
self.databuffer_hop["x"].append(freq)
self.databuffer_hop["y"].append(power)
self.prev_line = line
class HackRFSweepThread(BasePowerThread):
"""Thread which runs hackrf_sweep process"""
def setup(self, start_freq=0, stop_freq=6000, bin_size=1000,
interval=0.0, gain=40, ppm=0, crop=0, single_shot=False,
device_index=0, sample_rate=20000000):
"""Setup hackrf_sweep params"""
# theoretically we can support bins smaller than 40 kHz, but it is
# unlikely to result in acceptable performance
if bin_size < 40:
bin_size = 40
if bin_size > 5000:
bin_size = 5000
# We only support whole numbers of steps with bandwidth equal to the
# sample rate.
step_bandwidth = sample_rate / 1000000
total_bandwidth = stop_freq - start_freq
step_count = 1 + (total_bandwidth - 1) // step_bandwidth
total_bandwidth = step_count * step_bandwidth
stop_freq = start_freq + total_bandwidth
# distribute gain between two analog gain stages
if gain < 0:
gain = 0
if gain > 102:
gain = 102
lna_gain = 8 * (gain // 18)
vga_gain = 2 * ((gain - lna_gain) // 2)
self.params = {
"start_freq": start_freq, # MHz
"stop_freq": stop_freq, # MHz
"hops": 0,
"device_index": 0,
"sample_rate": 20e6, # sps
"bin_size": bin_size, # kHz
"interval": 0, # seconds
"gain": gain,
"lna_gain": lna_gain,
"vga_gain": vga_gain,
"ppm": 0,
"crop": 0,
"single_shot": single_shot
}
self.databuffer = {"timestamp": [], "x": [], "y": []}
print("hackrf_sweep params:")
pprint.pprint(self.params)
print()
def process_start(self):
"""Start hackrf_sweep process"""
if not self.process and self.params:
settings = QtCore.QSettings()
cmdline = [
settings.value("executable", "hackrf_sweep"),
"-f", "{}:{}".format(int(self.params["start_freq"]),
int(self.params["stop_freq"])),
"-B",
"-w", "{}".format(int(self.params["bin_size"]*1000)),
"-l", "{}".format(int(self.params["lna_gain"])),
"-g", "{}".format(int(self.params["vga_gain"])),
]
if self.params["single_shot"]:
cmdline.append("-1")
self.process = subprocess.Popen(cmdline, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL,
universal_newlines=False)
def parse_output(self, buf):
"""Parse one buf of output from hackrf_sweep"""
(low_edge, high_edge) = struct.unpack('QQ', buf[:16])
data = np.fromstring(buf[16:], dtype='<f4')
step = (high_edge - low_edge) / len(data)
if (low_edge//1000000) <= (self.params["start_freq"]):
# Reset databuffer at the start of each sweep even if we somehow
# did not complete the previous sweep.
self.databuffer = {"timestamp": [], "x": [], "y": []}
x_axis = list(np.arange(low_edge + step/2, high_edge, step))
self.databuffer["x"].extend(x_axis)
for i in range(len(data)):
self.databuffer["y"].append(data[i])
if (high_edge / 1e6) >= (self.params["stop_freq"]):
# We've reached the end of a pass, so sort and display it.
sorted_data = sorted(zip(self.databuffer["x"], self.databuffer["y"]))
self.databuffer["x"], self.databuffer["y"] = [list(x) for x in zip(*sorted_data)]
self.data_storage.update(self.databuffer)
def run(self):
"""hackrf_sweep thread main loop"""
self.process_start()
self.alive = True
self.powerThreadStarted.emit()
while self.alive:
buf = self.process.stdout.read(4)
if buf:
(record_length,) = struct.unpack('I', buf)
buf = self.process.stdout.read(record_length)
if buf:
self.parse_output(buf)
self.process_stop()
self.alive = False
self.powerThreadStopped.emit()

View File

@ -1,117 +0,0 @@
import os, threading, shlex
from Qt import QtCore
from qspectrumanalyzer import subprocess
class BaseInfo:
"""Default device metadata"""
sample_rate_min = 0
sample_rate_max = 3200000
sample_rate = 2560000
bandwidth_min = 0
bandwidth_max = 0
bandwidth = 0
gain_min = -1
gain_max = 49.6
gain = 37
start_freq_min = 0
start_freq_max = 2200
start_freq = 87
stop_freq_min = 0
stop_freq_max = 2200
stop_freq = 108
bin_size_min = 0
bin_size_max = 2800
bin_size = 10
interval_min = 0
interval_max = 3600
interval = 1
ppm_min = -999
ppm_max = 999
ppm = 0
crop_min = 0
crop_max = 99
crop = 0
additional_params = ''
help_device = None
@classmethod
def help_params(cls, executable):
cmdline = shlex.split(executable)
try:
text = subprocess.check_output(cmdline + ['-h'], universal_newlines=True,
stderr=subprocess.STDOUT, env=dict(os.environ, COLUMNS='125'),
console=False)
except subprocess.CalledProcessError as e:
text = e.output
except OSError:
text = '{} executable not found!'.format(executable)
return text
class BasePowerThread(QtCore.QThread):
"""Thread which runs Power Spectral Density acquisition and calculation process"""
powerThreadStarted = QtCore.Signal()
powerThreadStopped = QtCore.Signal()
def __init__(self, data_storage, parent=None):
super().__init__(parent)
self.data_storage = data_storage
self.alive = False
self.process = None
self._shutdown_lock = threading.Lock()
def stop(self):
"""Stop power process thread"""
self.process_stop()
self.alive = False
self.wait()
def setup(self, start_freq, stop_freq, bin_size, interval=10.0, gain=-1, ppm=0, crop=0,
single_shot=False, device=0, sample_rate=2560000, bandwidth=0, lnb_lo=0):
"""Setup power process params"""
raise NotImplementedError
def process_start(self):
"""Start power process"""
raise NotImplementedError
def process_stop(self):
"""Terminate power process"""
with self._shutdown_lock:
if self.process:
if self.process.poll() is None:
try:
self.process.terminate()
except ProcessLookupError:
pass
self.process.wait()
self.process = None
def parse_output(self, line):
"""Parse one line of output from power process"""
raise NotImplementedError
def run(self):
"""Power process thread main loop"""
self.process_start()
self.alive = True
self.powerThreadStarted.emit()
for line in self.process.stdout:
if not self.alive:
break
self.parse_output(line)
self.process_stop()
self.alive = False
self.powerThreadStopped.emit()
# Build list of all backends
__all__ = ['soapy_power', 'hackrf_sweep', 'rtl_power', 'rtl_power_fftw', 'rx_power']
# Import all backends
from qspectrumanalyzer.backends import soapy_power, hackrf_sweep, rtl_power, rtl_power_fftw, rx_power

View File

@ -1,171 +0,0 @@
import struct, shlex, sys, time
import numpy as np
from Qt import QtCore
from qspectrumanalyzer import subprocess
from qspectrumanalyzer.backends import BaseInfo, BasePowerThread
class Info(BaseInfo):
"""hackrf_sweep device metadata"""
sample_rate_min = 20000000
sample_rate_max = 20000000
sample_rate = 20000000
gain_min = -1
gain_max = 102
gain = 40
start_freq_min = 0
start_freq_max = 7230
start_freq = 0
stop_freq_min = 0
stop_freq_max = 7250
stop_freq = 6000
bin_size_min = 3
bin_size_max = 5000
bin_size = 1000
interval = 0
ppm_min = 0
ppm_max = 0
ppm = 0
crop_min = 0
crop_max = 0
crop = 0
class PowerThread(BasePowerThread):
"""Thread which runs hackrf_sweep process"""
def setup(self, start_freq=0, stop_freq=6000, bin_size=1000,
interval=0.0, gain=40, ppm=0, crop=0, single_shot=False,
device=0, sample_rate=20000000, bandwidth=0, lnb_lo=0):
"""Setup hackrf_sweep params"""
# Small bin sizes (<40 kHz) are only suitable with an arbitrarily
# reduced sweep interval. Bin sizes smaller than 3 kHz showed to be
# infeasible also in these cases.
if bin_size < 3:
bin_size = 3
if bin_size > 5000:
bin_size = 5000
# We only support whole numbers of steps with bandwidth equal to the
# sample rate.
step_bandwidth = sample_rate / 1000000
total_bandwidth = stop_freq - start_freq
step_count = 1 + (total_bandwidth - 1) // step_bandwidth
total_bandwidth = step_count * step_bandwidth
stop_freq = start_freq + total_bandwidth
# distribute gain between two analog gain stages
if gain > 102:
gain = 102
lna_gain = 8 * (gain // 18) if gain >= 0 else 0
vga_gain = 2 * ((gain - lna_gain) // 2) if gain >= 0 else 0
self.params = {
"start_freq": start_freq, # MHz
"stop_freq": stop_freq, # MHz
"hops": 0,
"device": 0,
"sample_rate": 20e6, # sps
"bin_size": bin_size, # kHz
"interval": interval, # seconds
"gain": gain,
"lna_gain": lna_gain,
"vga_gain": vga_gain,
"ppm": 0,
"crop": 0,
"single_shot": single_shot
}
self.lnb_lo = lnb_lo
self.databuffer = {"timestamp": [], "x": [], "y": []}
self.lastsweep = 0
self.interval = interval
def process_start(self):
"""Start hackrf_sweep process"""
if not self.process and self.params:
settings = QtCore.QSettings()
cmdline = shlex.split(settings.value("executable", "hackrf_sweep"))
cmdline.extend([
"-f", "{}:{}".format(int(self.params["start_freq"] - self.lnb_lo / 1e6),
int(self.params["stop_freq"] - self.lnb_lo / 1e6)),
"-B",
"-w", "{}".format(int(self.params["bin_size"] * 1000)),
])
if self.params["gain"] >= 0:
cmdline.extend([
"-l", "{}".format(int(self.params["lna_gain"])),
"-g", "{}".format(int(self.params["vga_gain"])),
])
if self.params["single_shot"]:
cmdline.append("-1")
additional_params = settings.value("params", Info.additional_params)
if additional_params:
cmdline.extend(shlex.split(additional_params))
print('Starting backend:')
print(' '.join(cmdline))
print()
self.process = subprocess.Popen(cmdline, stdout=subprocess.PIPE,
universal_newlines=False, console=False)
def parse_output(self, buf):
"""Parse one buf of output from hackrf_sweep"""
(low_edge, high_edge) = struct.unpack('QQ', buf[:16])
data = np.fromstring(buf[16:], dtype='<f4')
step = (high_edge - low_edge) / len(data)
if (low_edge // 1000000) <= (self.params["start_freq"] - self.lnb_lo / 1e6):
# Reset databuffer at the start of each sweep even if we somehow
# did not complete the previous sweep.
self.databuffer = {"timestamp": [], "x": [], "y": []}
x_axis = list(np.arange(low_edge + self.lnb_lo + step / 2, high_edge + self.lnb_lo, step))
self.databuffer["x"].extend(x_axis)
for i in range(len(data)):
self.databuffer["y"].append(data[i])
if (high_edge / 1e6) >= (self.params["stop_freq"] - self.lnb_lo / 1e6):
# We've reached the end of a pass. If it went too fast for our sweep interval, ignore it
t_finish = time.time()
if (t_finish < self.lastsweep + self.interval):
return
self.lastsweep = t_finish
# otherwise sort and display the data.
sorted_data = sorted(zip(self.databuffer["x"], self.databuffer["y"]))
self.databuffer["x"], self.databuffer["y"] = [list(x) for x in zip(*sorted_data)]
self.data_storage.update(self.databuffer)
def run(self):
"""hackrf_sweep thread main loop"""
self.process_start()
self.alive = True
self.powerThreadStarted.emit()
while self.alive:
try:
buf = self.process.stdout.read(4)
except AttributeError as e:
print(e, file=sys.stderr)
continue
if buf:
(record_length,) = struct.unpack('I', buf)
try:
buf = self.process.stdout.read(record_length)
except AttributeError as e:
print(e, file=sys.stderr)
continue
if buf:
self.parse_output(buf)
else:
break
else:
break
self.process_stop()
self.alive = False
self.powerThreadStopped.emit()

View File

@ -1,104 +0,0 @@
import shlex
import numpy as np
from Qt import QtCore
from qspectrumanalyzer import subprocess
from qspectrumanalyzer.backends import BaseInfo, BasePowerThread
class Info(BaseInfo):
"""rtl_power device metadata"""
pass
class PowerThread(BasePowerThread):
"""Thread which runs rtl_power process"""
def setup(self, start_freq, stop_freq, bin_size, interval=10.0, gain=-1, ppm=0, crop=0,
single_shot=False, device=0, sample_rate=2560000, bandwidth=0, lnb_lo=0):
"""Setup rtl_power params"""
if bin_size > 2800:
bin_size = 2800
self.params = {
"start_freq": start_freq,
"stop_freq": stop_freq,
"bin_size": bin_size,
"interval": interval,
"device": device,
"sample_rate": sample_rate,
"hops": 0,
"gain": gain,
"ppm": ppm,
"crop": crop,
"single_shot": single_shot
}
self.lnb_lo = lnb_lo
self.databuffer = {}
self.last_timestamp = ""
def process_start(self):
"""Start rtl_power process"""
if not self.process and self.params:
settings = QtCore.QSettings()
cmdline = shlex.split(settings.value("executable", "rtl_power"))
cmdline.extend([
"-f", "{}M:{}M:{}k".format(self.params["start_freq"] - self.lnb_lo / 1e6,
self.params["stop_freq"] - self.lnb_lo / 1e6,
self.params["bin_size"]),
"-i", "{}".format(self.params["interval"]),
"-d", "{}".format(self.params["device"]),
"-p", "{}".format(self.params["ppm"]),
"-c", "{}".format(self.params["crop"])
])
if self.params["sample_rate"] > 0:
cmdline.extend(["-r", "{}M".format(self.params["sample_rate"] / 1e6)])
if self.params["gain"] >= 0:
cmdline.extend(["-g", "{}".format(self.params["gain"])])
if self.params["single_shot"]:
cmdline.append("-1")
additional_params = settings.value("params", Info.additional_params)
if additional_params:
cmdline.extend(shlex.split(additional_params))
print('Starting backend:')
print(' '.join(cmdline))
print()
self.process = subprocess.Popen(cmdline, stdout=subprocess.PIPE,
universal_newlines=True, console=False)
def parse_output(self, line):
"""Parse one line of output from rtl_power"""
line = [col.strip() for col in line.split(",")]
timestamp = " ".join(line[:2])
start_freq = int(line[2])
stop_freq = int(line[3])
step = float(line[4])
samples = float(line[5])
x_axis = list(np.linspace(start_freq + self.lnb_lo, stop_freq + self.lnb_lo,
round((stop_freq - start_freq) / step)))
y_axis = [float(y) for y in line[6:]]
if len(x_axis) != len(y_axis):
print("ERROR: len(x_axis) != len(y_axis), use newer version of rtl_power!")
if len(x_axis) > len(y_axis):
print("Trimming x_axis...")
x_axis = x_axis[:len(y_axis)]
else:
print("Trimming y_axis...")
y_axis = y_axis[:len(x_axis)]
if timestamp != self.last_timestamp:
self.last_timestamp = timestamp
self.databuffer = {"timestamp": timestamp,
"x": x_axis,
"y": y_axis}
else:
self.databuffer["x"].extend(x_axis)
self.databuffer["y"].extend(y_axis)
# 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"] - self.lnb_lo / 1e6) * 1e6:
if stop_freq > ((self.params["stop_freq"] - self.lnb_lo / 1e6) * 1e6) - step:
self.data_storage.update(self.databuffer)

View File

@ -1,145 +0,0 @@
import math, shlex
from Qt import QtCore
from qspectrumanalyzer import subprocess
from qspectrumanalyzer.backends import BaseInfo, BasePowerThread
class Info(BaseInfo):
"""rtl_power_fftw device metadata"""
pass
class PowerThread(BasePowerThread):
"""Thread which runs rtl_power_fftw process"""
def setup(self, start_freq, stop_freq, bin_size, interval=10.0, gain=-1, ppm=0, crop=0,
single_shot=False, device=0, sample_rate=2560000, bandwidth=0, lnb_lo=0):
"""Setup rtl_power_fftw params"""
crop = crop * 100
overlap = crop * 2
freq_range = stop_freq * 1e6 - start_freq * 1e6
min_overhang = sample_rate * overlap * 0.01
hops = math.ceil((freq_range - min_overhang) / (sample_rate - min_overhang))
overhang = (hops * sample_rate - freq_range) / (hops - 1) if hops > 1 else 0
if bin_size > 2800:
bin_size = 2800
bins = math.ceil(sample_rate / (bin_size * 1e3))
crop_freq = sample_rate * crop * 0.01
self.params = {
"start_freq": start_freq,
"stop_freq": stop_freq,
"freq_range": freq_range,
"device": device,
"sample_rate": int(sample_rate),
"bin_size": bin_size,
"bins": bins,
"interval": interval,
"hops": hops,
"time": interval / hops,
"gain": int(gain * 10),
"ppm": ppm,
"crop": crop,
"overlap": overlap,
"min_overhang": min_overhang,
"overhang": overhang,
"single_shot": single_shot
}
self.lnb_lo = lnb_lo
self.freqs = [self.get_hop_freq(hop) for hop in range(hops)]
self.freqs_crop = [(f[0] + crop_freq, f[1] - crop_freq) for f in self.freqs]
self.databuffer = {"timestamp": [], "x": [], "y": []}
self.databuffer_hop = {"timestamp": [], "x": [], "y": []}
self.hop = 0
self.prev_line = ""
def get_hop_freq(self, hop):
"""Get start and stop frequency for particular hop"""
start_freq = self.params["start_freq"] * 1e6 + (self.params["sample_rate"] - self.params["overhang"]) * hop
stop_freq = start_freq + self.params["sample_rate"] - (self.params["sample_rate"] / self.params["bins"])
return (start_freq, stop_freq)
def process_start(self):
"""Start rtl_power_fftw process"""
if not self.process and self.params:
settings = QtCore.QSettings()
cmdline = shlex.split(settings.value("executable", "rtl_power_fftw"))
cmdline.extend([
"-f", "{}M:{}M".format(self.params["start_freq"] - self.lnb_lo / 1e6,
self.params["stop_freq"] - self.lnb_lo / 1e6),
"-b", "{}".format(self.params["bins"]),
"-t", "{}".format(self.params["time"]),
"-d", "{}".format(self.params["device"]),
"-r", "{}".format(self.params["sample_rate"]),
"-p", "{}".format(self.params["ppm"]),
"-q",
])
if self.params["gain"] >= 0:
cmdline.extend(["-g", "{}".format(self.params["gain"])])
if self.params["overlap"] > 0:
cmdline.extend(["-o", "{}".format(self.params["overlap"])])
if not self.params["single_shot"]:
cmdline.append("-c")
additional_params = settings.value("params", Info.additional_params)
if additional_params:
cmdline.extend(shlex.split(additional_params))
print('Starting backend:')
print(' '.join(cmdline))
print()
self.process = subprocess.Popen(cmdline, stdout=subprocess.PIPE,
universal_newlines=True, console=False)
def parse_output(self, line):
"""Parse one line of output from rtl_power_fftw"""
line = line.strip()
# One empty line => new hop
if not line and self.prev_line:
self.hop += 1
self.databuffer["x"].extend(self.databuffer_hop["x"])
self.databuffer["y"].extend(self.databuffer_hop["y"])
self.databuffer_hop = {"timestamp": [], "x": [], "y": []}
# Two empty lines => new set
elif not line and not self.prev_line:
self.hop = 0
self.data_storage.update(self.databuffer)
self.databuffer = {"timestamp": [], "x": [], "y": []}
# Get timestamp for new hop and set
elif line.startswith("# Acquisition start:"):
timestamp = line.split(":", 1)[1].strip()
if not self.databuffer_hop["timestamp"]:
self.databuffer_hop["timestamp"] = timestamp
if not self.databuffer["timestamp"]:
self.databuffer["timestamp"] = timestamp
# Skip other comments
elif line.startswith("#"):
pass
# Parse frequency and power
elif line[0].isdigit():
freq, power = line.split()
freq, power = float(freq) + self.lnb_lo, float(power)
start_freq, stop_freq = self.freqs_crop[self.hop]
# Apply cropping
if freq >= start_freq and freq <= stop_freq:
# Skip overlapping frequencies
if not self.databuffer["x"] or freq > self.databuffer["x"][-1]:
#print(" {:.3f} MHz".format(freq / 1e6))
self.databuffer_hop["x"].append(freq)
self.databuffer_hop["y"].append(power)
else:
#print(" Overlapping {:.3f} MHz".format(freq / 1e6))
pass
else:
#print(" Cropping {:.3f} MHz".format(freq / 1e6))
pass
self.prev_line = line

View File

@ -1,109 +0,0 @@
import shlex
import numpy as np
from Qt import QtCore
from qspectrumanalyzer import subprocess
from qspectrumanalyzer.backends import BaseInfo, BasePowerThread
class Info(BaseInfo):
"""rx_power device metadata"""
sample_rate_min = 0
sample_rate_max = 0
sample_rate = 0
start_freq_min = 0
start_freq_max = 7250
stop_freq_min = 0
stop_freq_max = 7250
gain_min = -1
gain_max = 999
bin_size_min = 0
bin_size_max = 2800
class PowerThread(BasePowerThread):
"""Thread which runs rx_power process"""
def setup(self, start_freq, stop_freq, bin_size, interval=10.0, gain=-1, ppm=0, crop=0,
single_shot=False, device=0, sample_rate=2560000, bandwidth=0, lnb_lo=0):
"""Setup rx_power params"""
self.params = {
"start_freq": start_freq,
"stop_freq": stop_freq,
"bin_size": bin_size,
"interval": interval,
"device": device,
"hops": 0,
"gain": gain,
"ppm": ppm,
"crop": crop,
"single_shot": single_shot
}
self.lnb_lo = lnb_lo
self.databuffer = {}
self.last_timestamp = ""
def process_start(self):
"""Start rx_power process"""
if not self.process and self.params:
settings = QtCore.QSettings()
cmdline = shlex.split(settings.value("executable", "rx_power"))
cmdline.extend([
"-f", "{}M:{}M:{}k".format(self.params["start_freq"] - self.lnb_lo / 1e6,
self.params["stop_freq"] - self.lnb_lo / 1e6,
self.params["bin_size"]),
"-i", "{}".format(self.params["interval"]),
"-d", "{}".format(self.params["device"]),
"-p", "{}".format(self.params["ppm"]),
"-c", "{}".format(self.params["crop"])
])
if self.params["gain"] >= 0:
cmdline.extend(["-g", "{}".format(self.params["gain"])])
if self.params["single_shot"]:
cmdline.append("-1")
additional_params = settings.value("params", Info.additional_params)
if additional_params:
cmdline.extend(shlex.split(additional_params))
print('Starting backend:')
print(' '.join(cmdline))
print()
self.process = subprocess.Popen(cmdline, stdout=subprocess.PIPE,
universal_newlines=True, console=False)
def parse_output(self, line):
"""Parse one line of output from rx_power"""
line = [col.strip() for col in line.split(",")]
timestamp = " ".join(line[:2])
start_freq = int(line[2])
stop_freq = int(line[3])
step = float(line[4])
samples = float(line[5])
x_axis = list(np.linspace(start_freq + self.lnb_lo, stop_freq + self.lnb_lo,
round((stop_freq - start_freq) / step)))
y_axis = [float(y) for y in line[6:]]
if len(x_axis) != len(y_axis):
print("ERROR: len(x_axis) != len(y_axis)!")
if len(x_axis) > len(y_axis):
print("Trimming x_axis...")
x_axis = x_axis[:len(y_axis)]
else:
print("Trimming y_axis...")
y_axis = y_axis[:len(x_axis)]
if timestamp != self.last_timestamp:
self.last_timestamp = timestamp
self.databuffer = {"timestamp": timestamp,
"x": x_axis,
"y": y_axis}
else:
self.databuffer["x"].extend(x_axis)
self.databuffer["y"].extend(y_axis)
# 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"] - self.lnb_lo / 1e6) * 1e6:
if stop_freq > ((self.params["stop_freq"] - self.lnb_lo / 1e6) * 1e6) - step:
self.data_storage.update(self.databuffer)

View File

@ -1,254 +0,0 @@
import os, sys, shlex, signal
import numpy as np
from Qt import QtCore
from qspectrumanalyzer import subprocess
from qspectrumanalyzer.backends import BaseInfo, BasePowerThread
try:
from soapypower.writer import SoapyPowerBinFormat
formatter = SoapyPowerBinFormat()
except ImportError:
print('soapy_power module not found!')
formatter = None
class Info(BaseInfo):
"""soapy_power device metadata"""
sample_rate_min = 0
sample_rate_max = 61440000
bandwidth_min = 0
bandwidth_max = 61440000
start_freq_min = 0
start_freq_max = 7250
stop_freq_min = 0
stop_freq_max = 7250
gain_min = -1
gain_max = 999
bin_size_min = 0
bin_size_max = 10000
additional_params = '--even --fft-window boxcar --remove-dc'
@classmethod
def help_device(cls, executable, device):
cmdline = shlex.split(executable)
try:
text = subprocess.check_output(cmdline + ['--detect'], universal_newlines=True,
stderr=subprocess.DEVNULL, env=dict(os.environ, COLUMNS='125'),
console=False)
text += '\n'
text += subprocess.check_output(cmdline + ['--device', device, '--info'], universal_newlines=True,
stderr=subprocess.DEVNULL, env=dict(os.environ, COLUMNS='125'),
console=False)
except subprocess.CalledProcessError as e:
text = e.output
except OSError:
text = '{} executable not found!'.format(executable)
return text
class PowerThread(BasePowerThread):
"""Thread which runs soapy_power process"""
def setup(self, start_freq, stop_freq, bin_size, interval=10.0, gain=-1, ppm=0, crop=0,
single_shot=False, device="", sample_rate=2560000, bandwidth=0, lnb_lo=0):
"""Setup soapy_power params"""
self.params = {
"start_freq": start_freq,
"stop_freq": stop_freq,
"device": device,
"sample_rate": sample_rate,
"bandwidth": bandwidth,
"bin_size": bin_size,
"interval": interval,
"hops": 0,
"gain": gain,
"ppm": ppm,
"crop": crop * 100,
"single_shot": single_shot
}
self.lnb_lo = lnb_lo
self.databuffer = {"timestamp": [], "x": [], "y": []}
self.min_freq = None
self.pipe_read = None
self.pipe_read_fd = None
self.pipe_write_fd = None
self.pipe_write_handle = None
def process_start(self):
"""Start soapy_power process"""
if not self.process and self.params:
# Create pipe used for communication with soapy_power process
self.pipe_read_fd, self.pipe_write_fd = os.pipe()
self.pipe_read = open(self.pipe_read_fd, 'rb')
os.set_inheritable(self.pipe_write_fd, True)
if sys.platform == 'win32':
self.pipe_write_handle = subprocess.make_inheritable_handle(self.pipe_write_fd)
# Prepare soapy_power cmdline parameters
settings = QtCore.QSettings()
cmdline = shlex.split(settings.value("executable", "soapy_power"))
cmdline.extend([
"-f", "{}M:{}M".format(self.params["start_freq"],
self.params["stop_freq"]),
"-B", "{}k".format(self.params["bin_size"]),
"-T", "{}".format(self.params["interval"]),
"-d", "{}".format(self.params["device"]),
"-r", "{}".format(self.params["sample_rate"]),
"-p", "{}".format(self.params["ppm"]),
"-F", "soapy_power_bin",
"--output-fd", "{}".format(
int(self.pipe_write_handle) if sys.platform == 'win32' else self.pipe_write_fd
),
])
if self.lnb_lo != 0:
cmdline.extend(["--lnb-lo", "{}".format(self.lnb_lo)])
if self.params["bandwidth"] > 0:
cmdline.extend(["-w", "{}".format(self.params["bandwidth"])])
if self.params["gain"] >= 0:
cmdline.extend(["-g", "{}".format(self.params["gain"])])
if self.params["crop"] > 0:
cmdline.extend(["-k", "{}".format(self.params["crop"])])
if not self.params["single_shot"]:
cmdline.append("-c")
additional_params = settings.value("params", Info.additional_params)
if additional_params:
cmdline.extend(shlex.split(additional_params))
# Start soapy_power process and close write part of pipe
if sys.platform == 'win32':
creationflags = subprocess.CREATE_NEW_PROCESS_GROUP
else:
creationflags = 0
print('Starting backend:')
print(' '.join(cmdline))
print()
self.process = subprocess.Popen(cmdline, close_fds=False, universal_newlines=False,
creationflags=creationflags, console=False)
os.close(self.pipe_write_fd)
if sys.platform == 'win32':
self.pipe_write_handle.Close()
def process_stop(self):
"""Stop soapy_power process"""
with self._shutdown_lock:
if self.process:
if self.process.poll() is None:
try:
if sys.platform == 'win32':
self.process.send_signal(signal.CTRL_BREAK_EVENT)
else:
self.process.terminate()
except ProcessLookupError:
pass
self.process.wait()
self.process = None
# Close pipe used for communication with soapy_power process
self.pipe_read.close()
self.pipe_read = None
self.pipe_read_fd = None
self.pipe_write_fd = None
self.pipe_write_handle = None
def parse_output(self, data):
"""Parse data from soapy_power"""
header, y_axis = data
time_start = header.time_start
time_stop = header.time_stop
start_freq = header.start
stop_freq = header.stop
step = header.step
samples = header.samples
x_axis = np.linspace(start_freq, stop_freq, round((stop_freq - start_freq) / step))
if len(x_axis) != len(y_axis):
print("ERROR: len(x_axis) != len(y_axis)")
return
if self.min_freq is None:
self.min_freq = start_freq
if start_freq == self.min_freq:
self.databuffer = {"timestamp": time_stop,
"x": list(x_axis),
"y": list(y_axis)}
else:
self.databuffer["x"].extend(x_axis)
self.databuffer["y"].extend(y_axis)
if stop_freq > (self.params["stop_freq"] * 1e6) - step:
self.data_storage.update(self.databuffer)
def run(self):
"""soapy_power thread main loop"""
if not formatter:
return
self.process_start()
self.alive = True
self.powerThreadStarted.emit()
while self.alive:
try:
data = formatter.read(self.pipe_read)
except ValueError as e:
print(e, file=sys.stderr)
continue
if data:
self.parse_output(data)
else:
break
self.process_stop()
self.alive = False
self.powerThreadStopped.emit()
def read_from_file(f):
"""Generator for reading data from soapy_power binary files"""
if not formatter:
return
min_freq = None
databuffer = None
while True:
try:
data = formatter.read(f)
except ValueError as e:
print(e, file=sys.stderr)
continue
if not data:
if min_freq is not None:
yield databuffer
return
header, y_axis = data
x_axis = np.linspace(header.start, header.stop, round((header.stop - header.start) / header.step))
if len(x_axis) != len(y_axis):
print("ERROR: len(x_axis) != len(y_axis)")
continue
if min_freq is None:
min_freq = header.start
elif header.start == min_freq:
yield databuffer
if header.start == min_freq:
databuffer = {"timestamp": header.time_stop,
"x": list(x_axis),
"y": list(y_axis)}
else:
databuffer["x"].extend(x_axis)
databuffer["y"].extend(y_axis)

View File

@ -1,28 +0,0 @@
from Qt import QtCore, QtWidgets
from qspectrumanalyzer.ui_qspectrumanalyzer_baseline import Ui_QSpectrumAnalyzerBaseline
class QSpectrumAnalyzerBaseline(QtWidgets.QDialog, Ui_QSpectrumAnalyzerBaseline):
"""QSpectrumAnalyzer baseline dialog"""
def __init__(self, parent=None):
# Initialize UI
super().__init__(parent)
self.setupUi(self)
# Load settings
settings = QtCore.QSettings()
self.baselineFileEdit.setText(settings.value("baseline_file", ""))
@QtCore.Slot()
def on_baselineFileButton_clicked(self):
"""Open file dialog when button is clicked"""
filename = QtWidgets.QFileDialog.getOpenFileName(self, self.tr("Select baseline file - QSpectrumAnalyzer"))[0]
if filename:
self.baselineFileEdit.setText(filename)
def accept(self):
"""Save settings when dialog is accepted"""
settings = QtCore.QSettings()
settings.setValue("baseline_file", self.baselineFileEdit.text())
QtWidgets.QDialog.accept(self)

View File

@ -1,33 +0,0 @@
from Qt import QtCore, QtWidgets
from qspectrumanalyzer.utils import color_to_str, str_to_color
from qspectrumanalyzer.ui_qspectrumanalyzer_colors import Ui_QSpectrumAnalyzerColors
class QSpectrumAnalyzerColors(QtWidgets.QDialog, Ui_QSpectrumAnalyzerColors):
"""QSpectrumAnalyzer colors dialog"""
def __init__(self, parent=None):
# Initialize UI
super().__init__(parent)
self.setupUi(self)
# Load settings
settings = QtCore.QSettings()
self.mainColorButton.setColor(str_to_color(settings.value("main_color", "255, 255, 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")))
self.baselineColorButton.setColor(str_to_color(settings.value("baseline_color", "255, 0, 255, 255")))
def accept(self):
"""Save settings when dialog is accepted"""
settings = QtCore.QSettings()
settings.setValue("main_color", color_to_str(self.mainColorButton.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()))
settings.setValue("baseline_color", color_to_str(self.baselineColorButton.color()))
QtWidgets.QDialog.accept(self)

View File

@ -1,10 +1,9 @@
import time, sys, os import time, sys
from Qt import QtCore from PyQt4 import QtCore
import numpy as np import numpy as np
from qspectrumanalyzer.utils import smooth from qspectrumanalyzer.utils import smooth
from qspectrumanalyzer.backends import soapy_power
class HistoryBuffer: class HistoryBuffer:
@ -37,7 +36,7 @@ class HistoryBuffer:
class TaskSignals(QtCore.QObject): class TaskSignals(QtCore.QObject):
"""Task signals emitter""" """Task signals emitter"""
result = QtCore.Signal(object) result = QtCore.pyqtSignal(object)
class Task(QtCore.QRunnable): class Task(QtCore.QRunnable):
@ -58,14 +57,12 @@ class Task(QtCore.QRunnable):
class DataStorage(QtCore.QObject): class DataStorage(QtCore.QObject):
"""Data storage for spectrum measurements""" """Data storage for spectrum measurements"""
history_updated = QtCore.Signal(object) history_updated = QtCore.pyqtSignal(object)
data_updated = QtCore.Signal(object) data_updated = QtCore.pyqtSignal(object)
history_recalculated = QtCore.Signal(object) data_recalculated = QtCore.pyqtSignal(object)
data_recalculated = QtCore.Signal(object) average_updated = QtCore.pyqtSignal(object)
average_updated = QtCore.Signal(object) peak_hold_max_updated = QtCore.pyqtSignal(object)
baseline_updated = QtCore.Signal(object) peak_hold_min_updated = QtCore.pyqtSignal(object)
peak_hold_max_updated = QtCore.Signal(object)
peak_hold_min_updated = QtCore.Signal(object)
def __init__(self, max_history_size=100, parent=None): def __init__(self, max_history_size=100, parent=None):
super().__init__(parent) super().__init__(parent)
@ -73,10 +70,6 @@ class DataStorage(QtCore.QObject):
self.smooth = False self.smooth = False
self.smooth_length = 11 self.smooth_length = 11
self.smooth_window = "hanning" self.smooth_window = "hanning"
self.subtract_baseline = False
self.prev_baseline = None
self.baseline = None
self.baseline_x = None
# Use only one worker thread because it is not faster # Use only one worker thread because it is not faster
# with more threads (and memory consumption is much higher) # with more threads (and memory consumption is much higher)
@ -112,20 +105,11 @@ class DataStorage(QtCore.QObject):
def update(self, data): def update(self, data):
"""Update data storage""" """Update data storage"""
if self.y is not None and len(data["y"]) != len(self.y):
print("{:d} bins coming from backend, expected {:d}".format(len(data["y"]), len(self.y)))
return
self.average_counter += 1 self.average_counter += 1
if self.x is None: if self.x is None:
self.x = data["x"] self.x = data["x"]
# Subtract baseline from data
data["y"] = np.asarray(data["y"])
if self.subtract_baseline and self.baseline is not None and len(data["y"]) == len(self.baseline):
data["y"] -= self.baseline
self.start_task(self.update_history, data.copy()) self.start_task(self.update_history, data.copy())
self.start_task(self.update_data, data) self.start_task(self.update_data, data)
@ -177,63 +161,16 @@ class DataStorage(QtCore.QObject):
"""Apply smoothing function to data""" """Apply smoothing function to data"""
return smooth(y, window_len=self.smooth_length, window=self.smooth_window) return smooth(y, window_len=self.smooth_length, window=self.smooth_window)
def set_smooth(self, toggle, length=11, window="hanning"): def set_smooth(self, toggle, length=11, window="hanning", recalculate=False):
"""Toggle smoothing and set smoothing params""" """Toggle smoothing and set smoothing params"""
if toggle != self.smooth or length != self.smooth_length or window != self.smooth_window: if toggle != self.smooth or length != self.smooth_length or window != self.smooth_window:
self.smooth = toggle self.smooth = toggle
self.smooth_length = length self.smooth_length = length
self.smooth_window = window self.smooth_window = window
self.start_task(self.recalculate_data) if recalculate:
self.start_task(self.recalculate_data)
def set_subtract_baseline(self, toggle, baseline_file=None): else:
"""Toggle baseline subtraction and set baseline""" self.reset_data()
baseline = None
baseline_x = None
# Load baseline from file (compute average if there are multiple PSD data in file)
if baseline_file and os.path.isfile(baseline_file):
average_counter = 0
with open(baseline_file, 'rb') as f:
for data in soapy_power.read_from_file(f):
average_counter += 1
if baseline is None:
baseline = data['y'].copy()
baseline_x = data['x'].copy()
else:
baseline = np.average((baseline, data['y']), axis=0, weights=(average_counter - 1, 1))
# Don't subtract baseline if number of bins in baseline differs from number of bins in data
if self.y is not None and baseline is not None and len(self.y) != len(baseline):
print("Can't subtract baseline (expected {:d} bins, but baseline has {:d} bins)".format(
len(self.y), len(baseline)
))
#baseline = None
if self.subtract_baseline:
self.prev_baseline = self.baseline
#if not np.array_equal(baseline, self.baseline):
self.baseline = baseline
self.baseline_x = baseline_x
self.baseline_updated.emit(self)
self.subtract_baseline = toggle
self.start_task(self.recalculate_history)
self.start_task(self.recalculate_data)
def recalculate_history(self):
"""Recalculate spectrum measurements history"""
if self.history is None:
return
history = self.history.get_buffer()
if self.prev_baseline is not None and len(history[-1]) == len(self.prev_baseline):
history += self.prev_baseline
self.prev_baseline = None
if self.subtract_baseline and self.baseline is not None and len(history[-1]) == len(self.baseline):
history -= self.baseline
self.history_recalculated.emit(self)
def recalculate_data(self): def recalculate_data(self):
"""Recalculate current data from history""" """Recalculate current data from history"""

View File

@ -1,288 +1,250 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS><TS version="2.0"> <!DOCTYPE TS><TS version="2.0">
<context>
<name>QSpectrumAnalyzerBaseline</name>
<message>
<location filename="../baseline.py" line="20"/>
<source>Select baseline file - QSpectrumAnalyzer</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer_baseline.py" line="50"/>
<source>Baseline - QSpectrumAnalyzer</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer_baseline.py" line="51"/>
<source>Baseline &amp;file:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer_baseline.py" line="52"/>
<source>...</source>
<translation type="unfinished"></translation>
</message>
</context>
<context> <context>
<name>QSpectrumAnalyzerColors</name> <name>QSpectrumAnalyzerColors</name>
<message> <message>
<location filename="../ui_qspectrumanalyzer_colors.py" line="112"/> <location filename="../ui_qspectrumanalyzer_colors.py" line="113"/>
<source>Colors - QSpectrumAnalyzer</source> <source>Colors - QSpectrumAnalyzer</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui_qspectrumanalyzer_colors.py" line="124"/> <location filename="../ui_qspectrumanalyzer_colors.py" line="114"/>
<source>...</source> <source>Main curve color:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer_colors.py" line="113"/>
<source>&amp;Main curve color:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer_colors.py" line="115"/>
<source>Max. peak &amp;hold color:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer_colors.py" line="117"/>
<source>M&amp;in. peak hold color:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer_colors.py" line="119"/>
<source>Average &amp;color:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer_colors.py" line="121"/>
<source>Persistence co&amp;lor:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui_qspectrumanalyzer_colors.py" line="123"/> <location filename="../ui_qspectrumanalyzer_colors.py" line="123"/>
<source>&amp;Baseline color:</source> <source>...</source>
<translation type="unfinished"></translation>
</message>
<message>
<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="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> <translation type="unfinished"></translation>
</message> </message>
</context> </context>
<context> <context>
<name>QSpectrumAnalyzerMainWindow</name> <name>QSpectrumAnalyzerMainWindow</name>
<message> <message>
<location filename="../ui_qspectrumanalyzer.py" line="317"/> <location filename="../ui_qspectrumanalyzer.py" line="311"/>
<source>QSpectrumAnalyzer</source> <source>QSpectrumAnalyzer</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<location filename="../__main__.py" line="496"/>
<source>About - QSpectrumAnalyzer</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../__main__.py" line="496"/>
<source>QSpectrumAnalyzer {}</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="318"/>
<source>&amp;File</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="319"/>
<source>&amp;Help</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="350"/>
<source>&amp;Settings...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="351"/>
<source>&amp;Quit</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="352"/>
<source>Ctrl+Q</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="353"/>
<source>&amp;About</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../__main__.py" line="253"/>
<source>Frequency hops: {}</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../__main__.py" line="255"/>
<source>Total time: {} | Sweep time: {:.2f} s ({:.2f} FPS)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="321"/>
<source>&amp;Start</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="322"/>
<source>S&amp;top</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="323"/>
<source>Si&amp;ngle shot</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<location filename="../ui_qspectrumanalyzer.py" line="325"/> <location filename="../ui_qspectrumanalyzer.py" line="325"/>
<source>Start:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="328"/>
<source> MHz</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="327"/>
<source>Stop:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="329"/>
<source>&amp;Bin size:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="330"/>
<source> kHz</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="332"/>
<source>&amp;Interval [s]:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="333"/>
<source>&amp;Gain [dB]:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="334"/>
<source>Corr. [ppm]:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="335"/>
<source>Crop [%]:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="336"/>
<source>Main curve</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="337"/>
<source>Colors...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="338"/>
<source>Max. hold</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="339"/>
<source>Min. hold</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="340"/>
<source>Average</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="341"/>
<source>Smoothing</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="347"/>
<source>...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="343"/>
<source>Persistence</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="345"/>
<source>auto</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="348"/>
<source>Subtract baseline</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="346"/>
<source>Baseline</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="320"/>
<source>Controls</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="324"/>
<source>Frequency</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="331"/>
<source>Settings</source> <source>Settings</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui_qspectrumanalyzer.py" line="349"/> <location filename="../ui_qspectrumanalyzer.py" line="322"/>
<source> MHz</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="324"/>
<source> kHz</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="328"/>
<source>auto</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="318"/>
<source>Frequency</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="314"/>
<source>Controls</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="340"/>
<source>Levels</source> <source>Levels</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<location filename="../__main__.py" line="337"/>
<source>Frequency hops: {} | Sweep time: {:.2f} s | FPS: {:.2f}</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../__main__.py" line="337"/>
<source>N/A</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../__main__.py" line="504"/>
<source>About - QSpectrumAnalyzer</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../__main__.py" line="504"/>
<source>QSpectrumAnalyzer {}</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="312"/>
<source>&amp;File</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="313"/>
<source>&amp;Help</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="315"/>
<source>&amp;Start</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="316"/>
<source>S&amp;top</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="317"/>
<source>Si&amp;ngle shot</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="319"/>
<source>Start:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="321"/>
<source>Stop:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="323"/>
<source>Bin size:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="326"/>
<source>Interval [s]:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="327"/>
<source>Gain [dB]:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="329"/>
<source>Corr. [ppm]:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="330"/>
<source>Crop [%]:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="331"/>
<source>Main curve</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="332"/>
<source>Colors...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="333"/>
<source>Max. hold</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="334"/>
<source>Min. hold</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="335"/>
<source>Average</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="336"/>
<source>Smoothing</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="339"/>
<source>...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="338"/>
<source>Persistence</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="341"/>
<source>&amp;Settings...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="342"/>
<source>&amp;Quit</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="343"/>
<source>Ctrl+Q</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer.py" line="344"/>
<source>&amp;About</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>QSpectrumAnalyzerPersistence</name> <name>QSpectrumAnalyzerPersistence</name>
<message> <message>
<location filename="../ui_qspectrumanalyzer_persistence.py" line="55"/> <location filename="../ui_qspectrumanalyzer_persistence.py" line="68"/>
<source>Persistence - QSpectrumAnalyzer</source> <source>Persistence - QSpectrumAnalyzer</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui_qspectrumanalyzer_persistence.py" line="56"/> <location filename="../ui_qspectrumanalyzer_persistence.py" line="69"/>
<source>Decay function:</source> <source>Decay function:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui_qspectrumanalyzer_persistence.py" line="57"/> <location filename="../ui_qspectrumanalyzer_persistence.py" line="70"/>
<source>linear</source> <source>linear</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui_qspectrumanalyzer_persistence.py" line="58"/> <location filename="../ui_qspectrumanalyzer_persistence.py" line="71"/>
<source>exponential</source> <source>exponential</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui_qspectrumanalyzer_persistence.py" line="59"/> <location filename="../ui_qspectrumanalyzer_persistence.py" line="72"/>
<source>Persistence length:</source> <source>Persistence length:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -290,148 +252,110 @@
<context> <context>
<name>QSpectrumAnalyzerSettings</name> <name>QSpectrumAnalyzerSettings</name>
<message> <message>
<location filename="../settings.py" line="57"/> <location filename="../__main__.py" line="50"/>
<source>Select executable - QSpectrumAnalyzer</source> <source>Select executable - QSpectrumAnalyzer</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui_qspectrumanalyzer_settings.py" line="148"/> <location filename="../ui_qspectrumanalyzer_settings.py" line="107"/>
<source>Settings - QSpectrumAnalyzer</source> <source>Settings - QSpectrumAnalyzer</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui_qspectrumanalyzer_settings.py" line="149"/> <location filename="../ui_qspectrumanalyzer_settings.py" line="108"/>
<source>&amp;Backend:</source> <source>&amp;Backend:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui_qspectrumanalyzer_settings.py" line="156"/> <location filename="../ui_qspectrumanalyzer_settings.py" line="115"/>
<source>soapy_power</source> <source>soapy_power</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui_qspectrumanalyzer_settings.py" line="151"/> <location filename="../ui_qspectrumanalyzer_settings.py" line="110"/>
<source>rx_power</source> <source>rx_power</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui_qspectrumanalyzer_settings.py" line="152"/> <location filename="../ui_qspectrumanalyzer_settings.py" line="111"/>
<source>rtl_power_fftw</source> <source>rtl_power_fftw</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui_qspectrumanalyzer_settings.py" line="153"/> <location filename="../ui_qspectrumanalyzer_settings.py" line="112"/>
<source>rtl_power</source> <source>rtl_power</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui_qspectrumanalyzer_settings.py" line="154"/> <location filename="../ui_qspectrumanalyzer_settings.py" line="113"/>
<source>hackrf_sweep</source> <source>hackrf_sweep</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui_qspectrumanalyzer_settings.py" line="155"/> <location filename="../ui_qspectrumanalyzer_settings.py" line="114"/>
<source>E&amp;xecutable:</source> <source>E&amp;xecutable:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui_qspectrumanalyzer_settings.py" line="157"/> <location filename="../ui_qspectrumanalyzer_settings.py" line="116"/>
<source>...</source> <source>...</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui_qspectrumanalyzer_settings.py" line="159"/> <location filename="../ui_qspectrumanalyzer_settings.py" line="117"/>
<source>Device:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer_settings.py" line="118"/>
<source>Sa&amp;mple rate:</source> <source>Sa&amp;mple rate:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui_qspectrumanalyzer_settings.py" line="160"/> <location filename="../ui_qspectrumanalyzer_settings.py" line="119"/>
<source>&amp;Waterfall history size:</source> <source>&amp;Waterfall history size:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<location filename="../ui_qspectrumanalyzer_settings.py" line="158"/>
<source>&amp;Device:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer_settings.py" line="161"/>
<source>Bandwidt&amp;h:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer_settings.py" line="163"/>
<source>&amp;LNB LO:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer_settings.py" line="166"/>
<source> ? </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer_settings.py" line="169"/>
<source>Negative frequency for upconverters, positive frequency for downconverters.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer_settings.py" line="164"/>
<source>Add&amp;itional parameters:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui_qspectrumanalyzer_settings.py" line="170"/>
<source> MHz</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>QSpectrumAnalyzerSettingsHelp</name> <name>QSpectrumAnalyzerSmooth</name>
<message> <message>
<location filename="../ui_qspectrumanalyzer_settings_help.py" line="36"/> <location filename="../ui_qspectrumanalyzer_smooth.py" line="73"/>
<source>Help - QSpectrumAnalyzer</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QSpectrumAnalyzerSmoothing</name>
<message>
<location filename="../ui_qspectrumanalyzer_smoothing.py" line="60"/>
<source>Smoothing - QSpectrumAnalyzer</source> <source>Smoothing - QSpectrumAnalyzer</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui_qspectrumanalyzer_smoothing.py" line="61"/> <location filename="../ui_qspectrumanalyzer_smooth.py" line="74"/>
<source>&amp;Window function:</source> <source>&amp;Window function:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui_qspectrumanalyzer_smoothing.py" line="62"/> <location filename="../ui_qspectrumanalyzer_smooth.py" line="75"/>
<source>rectangular</source> <source>rectangular</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui_qspectrumanalyzer_smoothing.py" line="63"/> <location filename="../ui_qspectrumanalyzer_smooth.py" line="76"/>
<source>hanning</source> <source>hanning</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui_qspectrumanalyzer_smoothing.py" line="64"/> <location filename="../ui_qspectrumanalyzer_smooth.py" line="77"/>
<source>hamming</source> <source>hamming</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui_qspectrumanalyzer_smoothing.py" line="65"/> <location filename="../ui_qspectrumanalyzer_smooth.py" line="78"/>
<source>bartlett</source> <source>bartlett</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui_qspectrumanalyzer_smoothing.py" line="66"/> <location filename="../ui_qspectrumanalyzer_smooth.py" line="79"/>
<source>blackman</source> <source>blackman</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui_qspectrumanalyzer_smoothing.py" line="67"/> <location filename="../ui_qspectrumanalyzer_smooth.py" line="80"/>
<source>Window len&amp;gth:</source> <source>Window len&amp;gth:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>

View File

@ -1,29 +0,0 @@
from Qt import QtCore, QtWidgets
from qspectrumanalyzer.ui_qspectrumanalyzer_persistence import Ui_QSpectrumAnalyzerPersistence
class QSpectrumAnalyzerPersistence(QtWidgets.QDialog, Ui_QSpectrumAnalyzerPersistence):
"""QSpectrumAnalyzer spectrum persistence dialog"""
def __init__(self, parent=None):
# Initialize UI
super().__init__(parent)
self.setupUi(self)
# Load settings
settings = QtCore.QSettings()
self.persistenceLengthSpinBox.setValue(settings.value("persistence_length", 5, int))
decay_function = settings.value("persistence_decay", "exponential")
i = self.decayFunctionComboBox.findText(decay_function)
if i == -1:
self.decayFunctionComboBox.setCurrentIndex(0)
else:
self.decayFunctionComboBox.setCurrentIndex(i)
def accept(self):
"""Save settings when dialog is accepted"""
settings = QtCore.QSettings()
settings.setValue("persistence_length", self.persistenceLengthSpinBox.value())
settings.setValue("persistence_decay", self.decayFunctionComboBox.currentText())
QtWidgets.QDialog.accept(self)

View File

@ -1,6 +1,6 @@
import collections, math import collections, math
from Qt import QtCore from PyQt4 import QtCore
import pyqtgraph as pg import pyqtgraph as pg
# Basic PyQtGraph settings # Basic PyQtGraph settings
@ -29,8 +29,6 @@ class SpectrumPlotWidget:
self.peak_hold_min_color = pg.mkColor("b") self.peak_hold_min_color = pg.mkColor("b")
self.average = False self.average = False
self.average_color = pg.mkColor("c") self.average_color = pg.mkColor("c")
self.baseline = False
self.baseline_color = pg.mkColor("m")
self.create_plot() self.create_plot()
@ -44,10 +42,6 @@ class SpectrumPlotWidget:
self.plot.setLimits(xMin=0) self.plot.setLimits(xMin=0)
self.plot.showButtons() self.plot.showButtons()
#self.plot.setDownsampling(mode="peak")
#self.plot.setClipToView(True)
self.create_baseline_curve()
self.create_persistence_curves() self.create_persistence_curves()
self.create_average_curve() self.create_average_curve()
self.create_peak_hold_min_curve() self.create_peak_hold_min_curve()
@ -84,11 +78,6 @@ class SpectrumPlotWidget:
self.curve_average = self.plot.plot(pen=self.average_color) self.curve_average = self.plot.plot(pen=self.average_color)
self.curve_average.setZValue(700) self.curve_average.setZValue(700)
def create_baseline_curve(self):
"""Create baseline curve"""
self.curve_baseline = self.plot.plot(pen=self.baseline_color)
self.curve_baseline.setZValue(500)
def create_persistence_curves(self): def create_persistence_curves(self):
"""Create spectrum persistence curves""" """Create spectrum persistence curves"""
z_index_base = 600 z_index_base = 600
@ -107,7 +96,6 @@ class SpectrumPlotWidget:
self.curve_peak_hold_max.setPen(self.peak_hold_max_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_peak_hold_min.setPen(self.peak_hold_min_color)
self.curve_average.setPen(self.average_color) self.curve_average.setPen(self.average_color)
self.curve_baseline.setPen(self.baseline_color)
decay = self.get_decay() decay = self.get_decay()
for i, curve in enumerate(self.persistence_curves): for i, curve in enumerate(self.persistence_curves):
@ -170,17 +158,6 @@ class SpectrumPlotWidget:
if force: if force:
self.curve_average.setVisible(self.average) self.curve_average.setVisible(self.average)
def update_baseline(self, data_storage, force=False):
"""Update baseline curve"""
if data_storage.baseline_x is None or data_storage.baseline is None:
self.curve_baseline.clear()
return
if self.baseline or force:
self.curve_baseline.setData(data_storage.baseline_x, data_storage.baseline)
if force:
self.curve_baseline.setVisible(self.baseline)
def update_persistence(self, data_storage, force=False): def update_persistence(self, data_storage, force=False):
"""Update persistence curves""" """Update persistence curves"""
if data_storage.x is None: if data_storage.x is None:
@ -204,7 +181,6 @@ class SpectrumPlotWidget:
QtCore.QTimer.singleShot(0, lambda: self.update_plot(data_storage, force=True)) 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_average(data_storage, force=True))
QtCore.QTimer.singleShot(0, lambda: self.update_baseline(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_max(data_storage, force=True))
QtCore.QTimer.singleShot(0, lambda: self.update_peak_hold_min(data_storage, force=True)) QtCore.QTimer.singleShot(0, lambda: self.update_peak_hold_min(data_storage, force=True))
@ -252,10 +228,6 @@ class SpectrumPlotWidget:
"""Clear average curve""" """Clear average curve"""
self.curve_average.clear() self.curve_average.clear()
def clear_baseline(self):
"""Clear baseline curve"""
self.curve_baseline.clear()
def clear_persistence(self): def clear_persistence(self):
"""Clear spectrum persistence curves""" """Clear spectrum persistence curves"""
self.persistence_data = None self.persistence_data = None
@ -292,7 +264,6 @@ class WaterfallPlotWidget:
self.plot.setLimits(xMin=0, yMax=0) self.plot.setLimits(xMin=0, yMax=0)
self.plot.showButtons() self.plot.showButtons()
#self.plot.setAspectLocked(True) #self.plot.setAspectLocked(True)
#self.plot.setDownsampling(mode="peak") #self.plot.setDownsampling(mode="peak")
#self.plot.setClipToView(True) #self.plot.setClipToView(True)
@ -333,16 +304,3 @@ class WaterfallPlotWidget:
def clear_plot(self): def clear_plot(self):
"""Clear waterfall plot""" """Clear waterfall plot"""
self.counter = 0 self.counter = 0
def recalculate_plot(self, data_storage):
"""Recalculate waterfall plot"""
if data_storage.x is None:
return
self.waterfallImg.setImage(data_storage.history.buffer[-self.counter:].T,
autoLevels=False, autoRange=False)
self.waterfallImg.setPos(
data_storage.x[0],
-self.counter if self.counter < self.history_size else -self.history_size
)
self.histogram.setImageItem(self.waterfallImg)

View File

@ -1,133 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="32"
height="32"
id="svg4290"
version="1.1"
inkscape:version="0.91 r13725"
viewBox="0 0 32 32"
inkscape:export-filename="qspectrumanalyzer.png"
inkscape:export-xdpi="135"
inkscape:export-ydpi="135"
sodipodi:docname="qspectrumanalyzer.svg">
<defs
id="defs4292" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.6568543"
inkscape:cx="0.51171273"
inkscape:cy="17.429759"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:snap-intersection-paths="true"
inkscape:snap-bbox="false"
inkscape:snap-nodes="true"
inkscape:object-nodes="true"
inkscape:snap-global="false"
inkscape:window-width="1366"
inkscape:window-height="709"
inkscape:window-x="-4"
inkscape:window-y="0"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid4298" />
</sodipodi:namedview>
<metadata
id="metadata4295">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<rect
style="fill:#000000;stroke:#666666;stroke-opacity:1"
id="rect4300"
width="30"
height="30"
x="1"
y="1"
rx="3"
ry="3" />
<path
style="fill:none;fill-rule:evenodd;stroke:#666666;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 16,1 0,30"
id="path4302"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-rule:evenodd;stroke:#666666;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 31,16 1,16"
id="path4302-5"
inkscape:connector-curvature="0" />
<use
x="0"
y="0"
xlink:href="#path4302"
id="use4369"
transform="translate(-7.5,0)"
width="100%"
height="100%" />
<use
x="0"
y="0"
xlink:href="#path4302"
id="use4371"
transform="translate(7.5,0)"
width="100%"
height="100%" />
<path
inkscape:connector-curvature="0"
id="path4373"
d="M 31,8.5 1,8.5"
style="fill:none;fill-rule:evenodd;stroke:#666666;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<use
x="0"
y="0"
xlink:href="#path4302-5"
id="use4375"
transform="translate(0,7.5)"
width="100%"
height="100%" />
<path
style="fill:none;fill-rule:evenodd;stroke:#00ff00;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 1.0625,25.25 c 0,0 2.5545099,5.432144 4.3470654,0.903939 0.6415968,-1.620748 1.1843693,-10.505075 2.3294368,-10.451145 1.124605,0.05297 1.2928473,9.79388 3.0231028,11.399454 0.836834,0.735662 2.019611,-2.789575 2.96484,-2.691821 1.178304,0.121857 2.125956,3.657855 3.181223,2.383073 2.07617,-2.508052 1.527752,-21.6078848 2.588897,-21.5746877 1.200441,0.037555 1.333727,19.4989257 3.765313,21.7522057 1.533625,1.421166 1.791478,-2.106359 3.115303,-2.461012 0.660576,-0.176968 2.034012,3.420657 2.702589,3.52241 0.772278,0.117536 1.624099,-1.153766 2.01348,-0.813666"
id="path4394"
inkscape:connector-curvature="0"
sodipodi:nodetypes="csscssssssc" />
<rect
style="fill:none;stroke:#666666;stroke-opacity:1"
id="rect4300-8"
width="30"
height="30"
x="1"
y="1"
rx="3"
ry="3" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1200</width> <width>1200</width>
<height>892</height> <height>810</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -52,7 +52,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1200</width> <width>1200</width>
<height>32</height> <height>30</height>
</rect> </rect>
</property> </property>
<widget class="QMenu" name="menu_File"> <widget class="QMenu" name="menu_File">
@ -82,8 +82,8 @@
</property> </property>
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>190</width> <width>10</width>
<height>130</height> <height>10</height>
</size> </size>
</property> </property>
<property name="features"> <property name="features">
@ -143,8 +143,8 @@
</property> </property>
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>208</width> <width>10</width>
<height>166</height> <height>10</height>
</size> </size>
</property> </property>
<property name="features"> <property name="features">
@ -182,9 +182,6 @@
<property name="alignment"> <property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property> </property>
<property name="showGroupSeparator" stdset="0">
<bool>true</bool>
</property>
<property name="suffix"> <property name="suffix">
<string> MHz</string> <string> MHz</string>
</property> </property>
@ -192,10 +189,10 @@
<number>3</number> <number>3</number>
</property> </property>
<property name="minimum"> <property name="minimum">
<double>0.000000000000000</double> <double>24.000000000000000</double>
</property> </property>
<property name="maximum"> <property name="maximum">
<double>2200.000000000000000</double> <double>1766.000000000000000</double>
</property> </property>
<property name="value"> <property name="value">
<double>87.000000000000000</double> <double>87.000000000000000</double>
@ -223,9 +220,6 @@
<property name="alignment"> <property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property> </property>
<property name="showGroupSeparator" stdset="0">
<bool>true</bool>
</property>
<property name="suffix"> <property name="suffix">
<string> MHz</string> <string> MHz</string>
</property> </property>
@ -233,10 +227,10 @@
<number>3</number> <number>3</number>
</property> </property>
<property name="minimum"> <property name="minimum">
<double>0.000000000000000</double> <double>24.000000000000000</double>
</property> </property>
<property name="maximum"> <property name="maximum">
<double>2200.000000000000000</double> <double>1766.000000000000000</double>
</property> </property>
<property name="value"> <property name="value">
<double>108.000000000000000</double> <double>108.000000000000000</double>
@ -246,7 +240,7 @@
<item row="2" column="0"> <item row="2" column="0">
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="text"> <property name="text">
<string>&amp;Bin size:</string> <string>Bin size:</string>
</property> </property>
<property name="buddy"> <property name="buddy">
<cstring>binSizeSpinBox</cstring> <cstring>binSizeSpinBox</cstring>
@ -264,20 +258,14 @@
<property name="alignment"> <property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property> </property>
<property name="showGroupSeparator" stdset="0">
<bool>true</bool>
</property>
<property name="suffix"> <property name="suffix">
<string> kHz</string> <string> kHz</string>
</property> </property>
<property name="decimals"> <property name="decimals">
<number>3</number> <number>3</number>
</property> </property>
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum"> <property name="maximum">
<double>10000.000000000000000</double> <double>2800.000000000000000</double>
</property> </property>
<property name="value"> <property name="value">
<double>10.000000000000000</double> <double>10.000000000000000</double>
@ -321,7 +309,7 @@
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="label_4"> <widget class="QLabel" name="label_4">
<property name="text"> <property name="text">
<string>&amp;Interval [s]:</string> <string>Interval [s]:</string>
</property> </property>
<property name="buddy"> <property name="buddy">
<cstring>intervalSpinBox</cstring> <cstring>intervalSpinBox</cstring>
@ -331,7 +319,7 @@
<item row="0" column="1"> <item row="0" column="1">
<widget class="QLabel" name="label_6"> <widget class="QLabel" name="label_6">
<property name="text"> <property name="text">
<string>&amp;Gain [dB]:</string> <string>Gain [dB]:</string>
</property> </property>
<property name="buddy"> <property name="buddy">
<cstring>gainSpinBox</cstring> <cstring>gainSpinBox</cstring>
@ -351,6 +339,25 @@
</property> </property>
</widget> </widget>
</item> </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"> <item row="2" column="0">
<widget class="QLabel" name="label_5"> <widget class="QLabel" name="label_5">
<property name="text"> <property name="text">
@ -456,7 +463,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="11" column="0"> <item row="9" column="0">
<spacer name="verticalSpacer_2"> <spacer name="verticalSpacer_2">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
@ -476,55 +483,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1" colspan="2">
<widget class="QDoubleSpinBox" name="gainSpinBox">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="specialValueText">
<string>auto</string>
</property>
<property name="decimals">
<number>1</number>
</property>
<property name="minimum">
<double>-1.000000000000000</double>
</property>
<property name="maximum">
<double>999.000000000000000</double>
</property>
<property name="singleStep">
<double>1.000000000000000</double>
</property>
<property name="value">
<double>-1.000000000000000</double>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QCheckBox" name="baselineCheckBox">
<property name="text">
<string>Baseline</string>
</property>
</widget>
</item>
<item row="9" column="2">
<widget class="QToolButton" name="baselineButton">
<property name="text">
<string>...</string>
</property>
<property name="autoRaise">
<bool>false</bool>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QCheckBox" name="subtractBaselineCheckBox">
<property name="text">
<string>Subtract baseline</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</widget> </widget>
@ -605,9 +563,6 @@
<tabstop>smoothButton</tabstop> <tabstop>smoothButton</tabstop>
<tabstop>persistenceCheckBox</tabstop> <tabstop>persistenceCheckBox</tabstop>
<tabstop>persistenceButton</tabstop> <tabstop>persistenceButton</tabstop>
<tabstop>baselineCheckBox</tabstop>
<tabstop>baselineButton</tabstop>
<tabstop>subtractBaselineCheckBox</tabstop>
<tabstop>histogramPlotLayout</tabstop> <tabstop>histogramPlotLayout</tabstop>
<tabstop>mainPlotLayout</tabstop> <tabstop>mainPlotLayout</tabstop>
<tabstop>waterfallPlotLayout</tabstop> <tabstop>waterfallPlotLayout</tabstop>

View File

@ -1,115 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QSpectrumAnalyzerBaseline</class>
<widget class="QDialog" name="QSpectrumAnalyzerBaseline">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>500</width>
<height>100</height>
</rect>
</property>
<property name="windowTitle">
<string>Baseline - QSpectrumAnalyzer</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Baseline &amp;file:</string>
</property>
<property name="buddy">
<cstring>baselineFileEdit</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLineEdit" name="baselineFileEdit"/>
</item>
<item>
<widget class="QToolButton" name="baselineFileButton">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<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>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>baselineFileEdit</tabstop>
<tabstop>baselineFileButton</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>QSpectrumAnalyzerBaseline</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>224</x>
<y>72</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>99</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>QSpectrumAnalyzerBaseline</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>292</x>
<y>78</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>99</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>253</width> <width>232</width>
<height>266</height> <height>260</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -19,7 +19,7 @@
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="label_2"> <widget class="QLabel" name="label_2">
<property name="text"> <property name="text">
<string>&amp;Main curve color:</string> <string>Main curve color:</string>
</property> </property>
<property name="buddy"> <property name="buddy">
<cstring>mainColorButton</cstring> <cstring>mainColorButton</cstring>
@ -42,7 +42,7 @@
<item row="1" column="0"> <item row="1" column="0">
<widget class="QLabel" name="label_4"> <widget class="QLabel" name="label_4">
<property name="text"> <property name="text">
<string>Max. peak &amp;hold color:</string> <string>Max. peak hold color:</string>
</property> </property>
<property name="buddy"> <property name="buddy">
<cstring>peakHoldMaxColorButton</cstring> <cstring>peakHoldMaxColorButton</cstring>
@ -65,7 +65,7 @@
<item row="2" column="0"> <item row="2" column="0">
<widget class="QLabel" name="label_6"> <widget class="QLabel" name="label_6">
<property name="text"> <property name="text">
<string>M&amp;in. peak hold color:</string> <string>Min. peak hold color:</string>
</property> </property>
<property name="buddy"> <property name="buddy">
<cstring>peakHoldMinColorButton</cstring> <cstring>peakHoldMinColorButton</cstring>
@ -88,7 +88,7 @@
<item row="3" column="0"> <item row="3" column="0">
<widget class="QLabel" name="label_5"> <widget class="QLabel" name="label_5">
<property name="text"> <property name="text">
<string>Average &amp;color:</string> <string>Average color:</string>
</property> </property>
<property name="buddy"> <property name="buddy">
<cstring>averageColorButton</cstring> <cstring>averageColorButton</cstring>
@ -111,7 +111,7 @@
<item row="4" column="0"> <item row="4" column="0">
<widget class="QLabel" name="label_3"> <widget class="QLabel" name="label_3">
<property name="text"> <property name="text">
<string>Persistence co&amp;lor:</string> <string>Persistence color:</string>
</property> </property>
<property name="buddy"> <property name="buddy">
<cstring>persistenceColorButton</cstring> <cstring>persistenceColorButton</cstring>
@ -131,29 +131,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>&amp;Baseline color:</string>
</property>
<property name="buddy">
<cstring>baselineColorButton</cstring>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="ColorButton" name="baselineColorButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item> <item>
@ -194,7 +171,7 @@
<tabstop>peakHoldMinColorButton</tabstop> <tabstop>peakHoldMinColorButton</tabstop>
<tabstop>averageColorButton</tabstop> <tabstop>averageColorButton</tabstop>
<tabstop>persistenceColorButton</tabstop> <tabstop>persistenceColorButton</tabstop>
<tabstop>baselineColorButton</tabstop> <tabstop>buttonBox</tabstop>
</tabstops> </tabstops>
<resources/> <resources/>
<connections> <connections>
@ -205,12 +182,12 @@
<slot>accept()</slot> <slot>accept()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>246</x> <x>248</x>
<y>259</y> <y>254</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>157</x> <x>157</x>
<y>265</y> <y>274</y>
</hint> </hint>
</hints> </hints>
</connection> </connection>
@ -221,12 +198,12 @@
<slot>reject()</slot> <slot>reject()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>246</x> <x>316</x>
<y>259</y> <y>260</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>252</x> <x>286</x>
<y>265</y> <y>274</y>
</hint> </hint>
</hints> </hints>
</connection> </connection>

View File

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>600</width> <width>420</width>
<height>388</height> <height>255</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -76,12 +76,6 @@
</item> </item>
<item> <item>
<widget class="QToolButton" name="executableButton"> <widget class="QToolButton" name="executableButton">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="text"> <property name="text">
<string>...</string> <string>...</string>
</property> </property>
@ -89,17 +83,20 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="3" column="0"> <item row="2" column="0">
<widget class="QLabel" name="label_5"> <widget class="QLabel" name="label_5">
<property name="text"> <property name="text">
<string>&amp;Device:</string> <string>Device:</string>
</property> </property>
<property name="buddy"> <property name="buddy">
<cstring>deviceEdit</cstring> <cstring>deviceEdit</cstring>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0"> <item row="2" column="1">
<widget class="QLineEdit" name="deviceEdit"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_4"> <widget class="QLabel" name="label_4">
<property name="text"> <property name="text">
<string>Sa&amp;mple rate:</string> <string>Sa&amp;mple rate:</string>
@ -109,7 +106,23 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="7" column="0"> <item row="3" column="1">
<widget class="QSpinBox" name="sampleRateSpinBox">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>25000000</number>
</property>
<property name="singleStep">
<number>10000</number>
</property>
<property name="value">
<number>2560000</number>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_2"> <widget class="QLabel" name="label_2">
<property name="text"> <property name="text">
<string>&amp;Waterfall history size:</string> <string>&amp;Waterfall history size:</string>
@ -119,7 +132,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="7" column="1"> <item row="4" column="1">
<widget class="QSpinBox" name="waterfallHistorySizeSpinBox"> <widget class="QSpinBox" name="waterfallHistorySizeSpinBox">
<property name="minimum"> <property name="minimum">
<number>1</number> <number>1</number>
@ -132,157 +145,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Bandwidt&amp;h:</string>
</property>
<property name="buddy">
<cstring>bandwidthSpinBox</cstring>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_8">
<property name="toolTip">
<string>Negative frequency for upconverters, positive frequency for downconverters.</string>
</property>
<property name="text">
<string>&amp;LNB LO:</string>
</property>
<property name="buddy">
<cstring>lnbSpinBox</cstring>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Add&amp;itional parameters:</string>
</property>
<property name="buddy">
<cstring>paramsEdit</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLineEdit" name="paramsEdit"/>
</item>
<item>
<widget class="QToolButton" name="paramsHelpButton">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="text">
<string> ? </string>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLineEdit" name="deviceEdit"/>
</item>
<item>
<widget class="QToolButton" name="deviceHelpButton">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="text">
<string> ? </string>
</property>
</widget>
</item>
</layout>
</item>
<item row="4" column="1">
<widget class="QDoubleSpinBox" name="sampleRateSpinBox">
<property name="showGroupSeparator" stdset="0">
<bool>true</bool>
</property>
<property name="suffix">
<string> MHz</string>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<double>999999.989999999990687</double>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
<property name="value">
<double>61.439999999999998</double>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QDoubleSpinBox" name="bandwidthSpinBox">
<property name="showGroupSeparator" stdset="0">
<bool>true</bool>
</property>
<property name="suffix">
<string> MHz</string>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<double>999999.989999999990687</double>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
<property name="value">
<double>0.000000000000000</double>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QDoubleSpinBox" name="lnbSpinBox">
<property name="toolTip">
<string>Negative frequency for upconverters, positive frequency for downconverters.</string>
</property>
<property name="showGroupSeparator" stdset="0">
<bool>true</bool>
</property>
<property name="suffix">
<string> MHz</string>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>-999999.998999999952503</double>
</property>
<property name="maximum">
<double>999999.998999999952503</double>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
<property name="value">
<double>0.000000000000000</double>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item> <item>
@ -314,14 +176,10 @@
<tabstop>backendComboBox</tabstop> <tabstop>backendComboBox</tabstop>
<tabstop>executableEdit</tabstop> <tabstop>executableEdit</tabstop>
<tabstop>executableButton</tabstop> <tabstop>executableButton</tabstop>
<tabstop>paramsEdit</tabstop>
<tabstop>paramsHelpButton</tabstop>
<tabstop>deviceEdit</tabstop> <tabstop>deviceEdit</tabstop>
<tabstop>deviceHelpButton</tabstop>
<tabstop>sampleRateSpinBox</tabstop> <tabstop>sampleRateSpinBox</tabstop>
<tabstop>bandwidthSpinBox</tabstop>
<tabstop>lnbSpinBox</tabstop>
<tabstop>waterfallHistorySizeSpinBox</tabstop> <tabstop>waterfallHistorySizeSpinBox</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops> </tabstops>
<resources/> <resources/>
<connections> <connections>
@ -332,8 +190,8 @@
<slot>accept()</slot> <slot>accept()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>254</x> <x>242</x>
<y>377</y> <y>248</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>157</x> <x>157</x>
@ -348,8 +206,8 @@
<slot>reject()</slot> <slot>reject()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>322</x> <x>310</x>
<y>377</y> <y>248</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>286</x> <x>286</x>

View File

@ -1,78 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QSpectrumAnalyzerSettingsHelp</class>
<widget class="QDialog" name="QSpectrumAnalyzerSettingsHelp">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1200</width>
<height>700</height>
</rect>
</property>
<property name="windowTitle">
<string>Help - QSpectrumAnalyzer</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPlainTextEdit" name="helpTextEdit">
<property name="undoRedoEnabled">
<bool>false</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>helpTextEdit</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>QSpectrumAnalyzerSettingsHelp</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>224</x>
<y>672</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>QSpectrumAnalyzerSettingsHelp</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>292</x>
<y>678</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>QSpectrumAnalyzerSmoothing</class> <class>QSpectrumAnalyzerSmooth</class>
<widget class="QDialog" name="QSpectrumAnalyzerSmoothing"> <widget class="QDialog" name="QSpectrumAnalyzerSmooth">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
@ -118,7 +118,7 @@
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>
<signal>accepted()</signal> <signal>accepted()</signal>
<receiver>QSpectrumAnalyzerSmoothing</receiver> <receiver>QSpectrumAnalyzerSmooth</receiver>
<slot>accept()</slot> <slot>accept()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
@ -134,7 +134,7 @@
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>
<signal>rejected()</signal> <signal>rejected()</signal>
<receiver>QSpectrumAnalyzerSmoothing</receiver> <receiver>QSpectrumAnalyzerSmooth</receiver>
<slot>reject()</slot> <slot>reject()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">

View File

@ -1,139 +0,0 @@
from Qt import QtCore, QtGui, QtWidgets
from qspectrumanalyzer import backends
from qspectrumanalyzer.ui_qspectrumanalyzer_settings import Ui_QSpectrumAnalyzerSettings
from qspectrumanalyzer.ui_qspectrumanalyzer_settings_help import Ui_QSpectrumAnalyzerSettingsHelp
class QSpectrumAnalyzerSettings(QtWidgets.QDialog, Ui_QSpectrumAnalyzerSettings):
"""QSpectrumAnalyzer settings dialog"""
def __init__(self, parent=None):
# Initialize UI
super().__init__(parent)
self.setupUi(self)
self.params_help_dialog = None
self.device_help_dialog = None
# Load settings
settings = QtCore.QSettings()
self.executableEdit.setText(settings.value("executable", "soapy_power"))
self.deviceEdit.setText(settings.value("device", ""))
self.lnbSpinBox.setValue(settings.value("lnb_lo", 0, float) / 1e6)
self.waterfallHistorySizeSpinBox.setValue(settings.value("waterfall_history_size", 100, int))
backend = settings.value("backend", "soapy_power")
try:
backend_module = getattr(backends, backend)
except AttributeError:
backend_module = backends.soapy_power
self.paramsEdit.setText(settings.value("params", backend_module.Info.additional_params))
self.deviceHelpButton.setEnabled(bool(backend_module.Info.help_device))
self.sampleRateSpinBox.setMinimum(backend_module.Info.sample_rate_min / 1e6)
self.sampleRateSpinBox.setMaximum(backend_module.Info.sample_rate_max / 1e6)
self.sampleRateSpinBox.setValue(settings.value("sample_rate", backend_module.Info.sample_rate, float) / 1e6)
self.bandwidthSpinBox.setMinimum(backend_module.Info.bandwidth_min / 1e6)
self.bandwidthSpinBox.setMaximum(backend_module.Info.bandwidth_max / 1e6)
self.bandwidthSpinBox.setValue(settings.value("bandwidth", backend_module.Info.bandwidth, float) / 1e6)
self.backendComboBox.blockSignals(True)
self.backendComboBox.clear()
for b in sorted(backends.__all__):
self.backendComboBox.addItem(b)
i = self.backendComboBox.findText(backend)
if i == -1:
self.backendComboBox.setCurrentIndex(0)
else:
self.backendComboBox.setCurrentIndex(i)
self.backendComboBox.blockSignals(False)
@QtCore.Slot()
def on_executableButton_clicked(self):
"""Open file dialog when button is clicked"""
filename = QtWidgets.QFileDialog.getOpenFileName(self, self.tr("Select executable - QSpectrumAnalyzer"))[0]
if filename:
self.executableEdit.setText(filename)
@QtCore.Slot()
def on_paramsHelpButton_clicked(self):
"""Open additional parameters help dialog when button is clicked"""
try:
backend_module = getattr(backends, self.backendComboBox.currentText())
except AttributeError:
backend_module = backends.soapy_power
self.params_help_dialog = QSpectrumAnalyzerSettingsHelp(
backend_module.Info.help_params(self.executableEdit.text()),
parent=self
)
self.params_help_dialog.show()
self.params_help_dialog.raise_()
self.params_help_dialog.activateWindow()
@QtCore.Slot()
def on_deviceHelpButton_clicked(self):
"""Open device help dialog when button is clicked"""
try:
backend_module = getattr(backends, self.backendComboBox.currentText())
except AttributeError:
backend_module = backends.soapy_power
self.device_help_dialog = QSpectrumAnalyzerSettingsHelp(
backend_module.Info.help_device(self.executableEdit.text(), self.deviceEdit.text()),
parent=self
)
self.device_help_dialog.show()
self.device_help_dialog.raise_()
self.device_help_dialog.activateWindow()
@QtCore.Slot(str)
def on_backendComboBox_currentIndexChanged(self, text):
"""Change executable when backend is changed"""
self.executableEdit.setText(text)
self.deviceEdit.setText("")
try:
backend_module = getattr(backends, text)
except AttributeError:
backend_module = backends.soapy_power
self.paramsEdit.setText(backend_module.Info.additional_params)
self.deviceHelpButton.setEnabled(bool(backend_module.Info.help_device))
self.sampleRateSpinBox.setMinimum(backend_module.Info.sample_rate_min / 1e6)
self.sampleRateSpinBox.setMaximum(backend_module.Info.sample_rate_max / 1e6)
self.sampleRateSpinBox.setValue(backend_module.Info.sample_rate / 1e6)
self.bandwidthSpinBox.setMinimum(backend_module.Info.bandwidth_min / 1e6)
self.bandwidthSpinBox.setMaximum(backend_module.Info.bandwidth_max / 1e6)
self.bandwidthSpinBox.setValue(backend_module.Info.bandwidth / 1e6)
def accept(self):
"""Save settings when dialog is accepted"""
settings = QtCore.QSettings()
settings.setValue("backend", self.backendComboBox.currentText())
settings.setValue("executable", self.executableEdit.text())
settings.setValue("params", self.paramsEdit.text())
settings.setValue("device", self.deviceEdit.text())
settings.setValue("sample_rate", self.sampleRateSpinBox.value() * 1e6)
settings.setValue("bandwidth", self.bandwidthSpinBox.value() * 1e6)
settings.setValue("lnb_lo", self.lnbSpinBox.value() * 1e6)
settings.setValue("waterfall_history_size", self.waterfallHistorySizeSpinBox.value())
QtWidgets.QDialog.accept(self)
class QSpectrumAnalyzerSettingsHelp(QtWidgets.QDialog, Ui_QSpectrumAnalyzerSettingsHelp):
"""QSpectrumAnalyzer settings help dialog"""
def __init__(self, text, parent=None):
# Initialize UI
super().__init__(parent)
self.setupUi(self)
monospace_font = QtGui.QFont('monospace')
monospace_font.setStyleHint(QtGui.QFont.Monospace)
self.helpTextEdit.setFont(monospace_font)
self.helpTextEdit.setPlainText(text)

View File

@ -1,29 +0,0 @@
from Qt import QtCore, QtWidgets
from qspectrumanalyzer.ui_qspectrumanalyzer_smoothing import Ui_QSpectrumAnalyzerSmoothing
class QSpectrumAnalyzerSmoothing(QtWidgets.QDialog, Ui_QSpectrumAnalyzerSmoothing):
"""QSpectrumAnalyzer spectrum smoothing dialog"""
def __init__(self, parent=None):
# Initialize UI
super().__init__(parent)
self.setupUi(self)
# Load settings
settings = QtCore.QSettings()
self.windowLengthSpinBox.setValue(settings.value("smooth_length", 11, int))
window_function = settings.value("smooth_window", "hanning")
i = self.windowFunctionComboBox.findText(window_function)
if i == -1:
self.windowFunctionComboBox.setCurrentIndex(0)
else:
self.windowFunctionComboBox.setCurrentIndex(i)
def accept(self):
"""Save settings when dialog is accepted"""
settings = QtCore.QSettings()
settings.setValue("smooth_length", self.windowLengthSpinBox.value())
settings.setValue("smooth_window", self.windowFunctionComboBox.currentText())
QtWidgets.QDialog.accept(self)

View File

@ -1,81 +0,0 @@
import sys, subprocess
# Basic attributes and exceptions
PIPE = subprocess.PIPE
STDOUT = subprocess.STDOUT
DEVNULL = subprocess.DEVNULL
SubprocessError = subprocess.SubprocessError
TimeoutExpired = subprocess.TimeoutExpired
CalledProcessError = subprocess.CalledProcessError
# Windows-only attributes and functions
if sys.platform == 'win32':
import msvcrt
import _winapi
# creationflags
CREATE_NEW_CONSOLE = subprocess.CREATE_NEW_CONSOLE
CREATE_NEW_PROCESS_GROUP = subprocess.CREATE_NEW_PROCESS_GROUP
# startupinfo
STARTUPINFO = subprocess.STARTUPINFO
STARTF_USESTDHANDLES = subprocess.STARTF_USESTDHANDLES
STARTF_USESHOWWINDOW = subprocess.STARTF_USESHOWWINDOW
SW_HIDE = subprocess.SW_HIDE
# file handles
Handle = subprocess.Handle
STD_INPUT_HANDLE = subprocess.STD_INPUT_HANDLE
STD_OUTPUT_HANDLE = subprocess.STD_OUTPUT_HANDLE
STD_ERROR_HANDLE = subprocess.STD_ERROR_HANDLE
def make_inheritable_handle(fd):
"""Create inheritable duplicate of handle from file descriptor"""
h = _winapi.DuplicateHandle(
_winapi.GetCurrentProcess(),
msvcrt.get_osfhandle(fd),
_winapi.GetCurrentProcess(), 0, 1,
_winapi.DUPLICATE_SAME_ACCESS
)
return subprocess.Handle(h)
def hide_console_window(startupinfo=None):
"""Returns altered startupinfo to hide console window on Windows"""
if sys.platform != 'win32':
return None
if not startupinfo:
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
return startupinfo
class Popen(subprocess.Popen):
"""subprocess.Popen with ability to hide console window on Windows"""
def __init__(self, *pargs, console=True, **kwargs):
if not console:
kwargs['startupinfo'] = hide_console_window(kwargs.get('startupinfo'))
super().__init__(*pargs, **kwargs)
def call(*pargs, console=True, **kwargs):
"""subprocess.call with ability to hide console window on Windows"""
if not console:
kwargs['startupinfo'] = hide_console_window(kwargs.get('startupinfo'))
return subprocess.call(*pargs, **kwargs)
def check_call(*pargs, console=True, **kwargs):
"""subprocess.check_call with ability to hide console window on Windows"""
if not console:
kwargs['startupinfo'] = hide_console_window(kwargs.get('startupinfo'))
return subprocess.check_call(*pargs, **kwargs)
def check_output(*pargs, console=True, **kwargs):
"""subprocess.check_output with ability to hide console window on Windows"""
if not console:
kwargs['startupinfo'] = hide_console_window(kwargs.get('startupinfo'))
return subprocess.check_output(*pargs, **kwargs)

View File

@ -2,275 +2,273 @@
# Form implementation generated from reading ui file 'qspectrumanalyzer/qspectrumanalyzer.ui' # Form implementation generated from reading ui file 'qspectrumanalyzer/qspectrumanalyzer.ui'
# #
# Created by: PyQt5 UI code generator 5.8 # Created by: PyQt4 UI code generator 4.12
# #
# WARNING! All changes made in this file will be lost! # WARNING! All changes made in this file will be lost!
from Qt import QtCore, QtGui, QtWidgets from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_QSpectrumAnalyzerMainWindow(object): class Ui_QSpectrumAnalyzerMainWindow(object):
def setupUi(self, QSpectrumAnalyzerMainWindow): def setupUi(self, QSpectrumAnalyzerMainWindow):
QSpectrumAnalyzerMainWindow.setObjectName("QSpectrumAnalyzerMainWindow") QSpectrumAnalyzerMainWindow.setObjectName(_fromUtf8("QSpectrumAnalyzerMainWindow"))
QSpectrumAnalyzerMainWindow.resize(1200, 892) QSpectrumAnalyzerMainWindow.resize(1200, 810)
self.centralwidget = QtWidgets.QWidget(QSpectrumAnalyzerMainWindow) self.centralwidget = QtGui.QWidget(QSpectrumAnalyzerMainWindow)
self.centralwidget.setObjectName("centralwidget") self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget) self.horizontalLayout = QtGui.QHBoxLayout(self.centralwidget)
self.horizontalLayout.setObjectName("horizontalLayout") self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
self.plotSplitter = QtWidgets.QSplitter(self.centralwidget) self.plotSplitter = QtGui.QSplitter(self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.plotSplitter.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(self.plotSplitter.sizePolicy().hasHeightForWidth())
self.plotSplitter.setSizePolicy(sizePolicy) self.plotSplitter.setSizePolicy(sizePolicy)
self.plotSplitter.setOrientation(QtCore.Qt.Vertical) self.plotSplitter.setOrientation(QtCore.Qt.Vertical)
self.plotSplitter.setObjectName("plotSplitter") self.plotSplitter.setObjectName(_fromUtf8("plotSplitter"))
self.mainPlotLayout = GraphicsLayoutWidget(self.plotSplitter) self.mainPlotLayout = GraphicsLayoutWidget(self.plotSplitter)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.mainPlotLayout.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(self.mainPlotLayout.sizePolicy().hasHeightForWidth())
self.mainPlotLayout.setSizePolicy(sizePolicy) self.mainPlotLayout.setSizePolicy(sizePolicy)
self.mainPlotLayout.setObjectName("mainPlotLayout") self.mainPlotLayout.setObjectName(_fromUtf8("mainPlotLayout"))
self.waterfallPlotLayout = GraphicsLayoutWidget(self.plotSplitter) self.waterfallPlotLayout = GraphicsLayoutWidget(self.plotSplitter)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.waterfallPlotLayout.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(self.waterfallPlotLayout.sizePolicy().hasHeightForWidth())
self.waterfallPlotLayout.setSizePolicy(sizePolicy) self.waterfallPlotLayout.setSizePolicy(sizePolicy)
self.waterfallPlotLayout.setObjectName("waterfallPlotLayout") self.waterfallPlotLayout.setObjectName(_fromUtf8("waterfallPlotLayout"))
self.horizontalLayout.addWidget(self.plotSplitter) self.horizontalLayout.addWidget(self.plotSplitter)
QSpectrumAnalyzerMainWindow.setCentralWidget(self.centralwidget) QSpectrumAnalyzerMainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(QSpectrumAnalyzerMainWindow) self.menubar = QtGui.QMenuBar(QSpectrumAnalyzerMainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 1200, 32)) self.menubar.setGeometry(QtCore.QRect(0, 0, 1200, 30))
self.menubar.setObjectName("menubar") self.menubar.setObjectName(_fromUtf8("menubar"))
self.menu_File = QtWidgets.QMenu(self.menubar) self.menu_File = QtGui.QMenu(self.menubar)
self.menu_File.setObjectName("menu_File") self.menu_File.setObjectName(_fromUtf8("menu_File"))
self.menu_Help = QtWidgets.QMenu(self.menubar) self.menu_Help = QtGui.QMenu(self.menubar)
self.menu_Help.setObjectName("menu_Help") self.menu_Help.setObjectName(_fromUtf8("menu_Help"))
QSpectrumAnalyzerMainWindow.setMenuBar(self.menubar) QSpectrumAnalyzerMainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(QSpectrumAnalyzerMainWindow) self.statusbar = QtGui.QStatusBar(QSpectrumAnalyzerMainWindow)
self.statusbar.setObjectName("statusbar") self.statusbar.setObjectName(_fromUtf8("statusbar"))
QSpectrumAnalyzerMainWindow.setStatusBar(self.statusbar) QSpectrumAnalyzerMainWindow.setStatusBar(self.statusbar)
self.controlsDockWidget = QtWidgets.QDockWidget(QSpectrumAnalyzerMainWindow) self.controlsDockWidget = QtGui.QDockWidget(QSpectrumAnalyzerMainWindow)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Minimum)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.controlsDockWidget.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(self.controlsDockWidget.sizePolicy().hasHeightForWidth())
self.controlsDockWidget.setSizePolicy(sizePolicy) self.controlsDockWidget.setSizePolicy(sizePolicy)
self.controlsDockWidget.setMinimumSize(QtCore.QSize(190, 130)) self.controlsDockWidget.setMinimumSize(QtCore.QSize(10, 10))
self.controlsDockWidget.setFeatures(QtWidgets.QDockWidget.DockWidgetFloatable|QtWidgets.QDockWidget.DockWidgetMovable) self.controlsDockWidget.setFeatures(QtGui.QDockWidget.DockWidgetFloatable|QtGui.QDockWidget.DockWidgetMovable)
self.controlsDockWidget.setObjectName("controlsDockWidget") self.controlsDockWidget.setObjectName(_fromUtf8("controlsDockWidget"))
self.controlsDockWidgetContents = QtWidgets.QWidget() self.controlsDockWidgetContents = QtGui.QWidget()
self.controlsDockWidgetContents.setObjectName("controlsDockWidgetContents") self.controlsDockWidgetContents.setObjectName(_fromUtf8("controlsDockWidgetContents"))
self.gridLayout_2 = QtWidgets.QGridLayout(self.controlsDockWidgetContents) self.gridLayout_2 = QtGui.QGridLayout(self.controlsDockWidgetContents)
self.gridLayout_2.setContentsMargins(0, 0, 0, 0) self.gridLayout_2.setMargin(0)
self.gridLayout_2.setObjectName("gridLayout_2") self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
self.startButton = QtWidgets.QPushButton(self.controlsDockWidgetContents) self.startButton = QtGui.QPushButton(self.controlsDockWidgetContents)
self.startButton.setObjectName("startButton") self.startButton.setObjectName(_fromUtf8("startButton"))
self.gridLayout_2.addWidget(self.startButton, 0, 0, 1, 1) self.gridLayout_2.addWidget(self.startButton, 0, 0, 1, 1)
self.stopButton = QtWidgets.QPushButton(self.controlsDockWidgetContents) self.stopButton = QtGui.QPushButton(self.controlsDockWidgetContents)
self.stopButton.setObjectName("stopButton") self.stopButton.setObjectName(_fromUtf8("stopButton"))
self.gridLayout_2.addWidget(self.stopButton, 0, 1, 1, 1) self.gridLayout_2.addWidget(self.stopButton, 0, 1, 1, 1)
self.singleShotButton = QtWidgets.QPushButton(self.controlsDockWidgetContents) self.singleShotButton = QtGui.QPushButton(self.controlsDockWidgetContents)
self.singleShotButton.setObjectName("singleShotButton") self.singleShotButton.setObjectName(_fromUtf8("singleShotButton"))
self.gridLayout_2.addWidget(self.singleShotButton, 1, 0, 1, 2) self.gridLayout_2.addWidget(self.singleShotButton, 1, 0, 1, 2)
spacerItem = QtWidgets.QSpacerItem(20, 561, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) spacerItem = QtGui.QSpacerItem(20, 561, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.gridLayout_2.addItem(spacerItem, 2, 0, 1, 1) self.gridLayout_2.addItem(spacerItem, 2, 0, 1, 1)
self.controlsDockWidget.setWidget(self.controlsDockWidgetContents) self.controlsDockWidget.setWidget(self.controlsDockWidgetContents)
QSpectrumAnalyzerMainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.controlsDockWidget) QSpectrumAnalyzerMainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.controlsDockWidget)
self.frequencyDockWidget = QtWidgets.QDockWidget(QSpectrumAnalyzerMainWindow) self.frequencyDockWidget = QtGui.QDockWidget(QSpectrumAnalyzerMainWindow)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Minimum)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.frequencyDockWidget.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(self.frequencyDockWidget.sizePolicy().hasHeightForWidth())
self.frequencyDockWidget.setSizePolicy(sizePolicy) self.frequencyDockWidget.setSizePolicy(sizePolicy)
self.frequencyDockWidget.setMinimumSize(QtCore.QSize(208, 166)) self.frequencyDockWidget.setMinimumSize(QtCore.QSize(10, 10))
self.frequencyDockWidget.setFeatures(QtWidgets.QDockWidget.DockWidgetFloatable|QtWidgets.QDockWidget.DockWidgetMovable) self.frequencyDockWidget.setFeatures(QtGui.QDockWidget.DockWidgetFloatable|QtGui.QDockWidget.DockWidgetMovable)
self.frequencyDockWidget.setObjectName("frequencyDockWidget") self.frequencyDockWidget.setObjectName(_fromUtf8("frequencyDockWidget"))
self.frequencyDockWidgetContents = QtWidgets.QWidget() self.frequencyDockWidgetContents = QtGui.QWidget()
self.frequencyDockWidgetContents.setObjectName("frequencyDockWidgetContents") self.frequencyDockWidgetContents.setObjectName(_fromUtf8("frequencyDockWidgetContents"))
self.formLayout = QtWidgets.QFormLayout(self.frequencyDockWidgetContents) self.formLayout = QtGui.QFormLayout(self.frequencyDockWidgetContents)
self.formLayout.setFieldGrowthPolicy(QtWidgets.QFormLayout.ExpandingFieldsGrow) self.formLayout.setFieldGrowthPolicy(QtGui.QFormLayout.ExpandingFieldsGrow)
self.formLayout.setContentsMargins(0, 0, 0, 0) self.formLayout.setMargin(0)
self.formLayout.setObjectName("formLayout") self.formLayout.setObjectName(_fromUtf8("formLayout"))
self.label_2 = QtWidgets.QLabel(self.frequencyDockWidgetContents) self.label_2 = QtGui.QLabel(self.frequencyDockWidgetContents)
self.label_2.setObjectName("label_2") self.label_2.setObjectName(_fromUtf8("label_2"))
self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.label_2) self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.label_2)
self.startFreqSpinBox = QtWidgets.QDoubleSpinBox(self.frequencyDockWidgetContents) self.startFreqSpinBox = QtGui.QDoubleSpinBox(self.frequencyDockWidgetContents)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.startFreqSpinBox.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(self.startFreqSpinBox.sizePolicy().hasHeightForWidth())
self.startFreqSpinBox.setSizePolicy(sizePolicy) self.startFreqSpinBox.setSizePolicy(sizePolicy)
self.startFreqSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) self.startFreqSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.startFreqSpinBox.setProperty("showGroupSeparator", True)
self.startFreqSpinBox.setDecimals(3) self.startFreqSpinBox.setDecimals(3)
self.startFreqSpinBox.setMinimum(0.0) self.startFreqSpinBox.setMinimum(24.0)
self.startFreqSpinBox.setMaximum(2200.0) self.startFreqSpinBox.setMaximum(1766.0)
self.startFreqSpinBox.setProperty("value", 87.0) self.startFreqSpinBox.setProperty("value", 87.0)
self.startFreqSpinBox.setObjectName("startFreqSpinBox") self.startFreqSpinBox.setObjectName(_fromUtf8("startFreqSpinBox"))
self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.startFreqSpinBox) self.formLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.startFreqSpinBox)
self.label_3 = QtWidgets.QLabel(self.frequencyDockWidgetContents) self.label_3 = QtGui.QLabel(self.frequencyDockWidgetContents)
self.label_3.setObjectName("label_3") self.label_3.setObjectName(_fromUtf8("label_3"))
self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label_3) self.formLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.label_3)
self.stopFreqSpinBox = QtWidgets.QDoubleSpinBox(self.frequencyDockWidgetContents) self.stopFreqSpinBox = QtGui.QDoubleSpinBox(self.frequencyDockWidgetContents)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.stopFreqSpinBox.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(self.stopFreqSpinBox.sizePolicy().hasHeightForWidth())
self.stopFreqSpinBox.setSizePolicy(sizePolicy) self.stopFreqSpinBox.setSizePolicy(sizePolicy)
self.stopFreqSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) self.stopFreqSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.stopFreqSpinBox.setProperty("showGroupSeparator", True)
self.stopFreqSpinBox.setDecimals(3) self.stopFreqSpinBox.setDecimals(3)
self.stopFreqSpinBox.setMinimum(0.0) self.stopFreqSpinBox.setMinimum(24.0)
self.stopFreqSpinBox.setMaximum(2200.0) self.stopFreqSpinBox.setMaximum(1766.0)
self.stopFreqSpinBox.setProperty("value", 108.0) self.stopFreqSpinBox.setProperty("value", 108.0)
self.stopFreqSpinBox.setObjectName("stopFreqSpinBox") self.stopFreqSpinBox.setObjectName(_fromUtf8("stopFreqSpinBox"))
self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.stopFreqSpinBox) self.formLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.stopFreqSpinBox)
self.label = QtWidgets.QLabel(self.frequencyDockWidgetContents) self.label = QtGui.QLabel(self.frequencyDockWidgetContents)
self.label.setObjectName("label") self.label.setObjectName(_fromUtf8("label"))
self.formLayout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.label) self.formLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.label)
self.binSizeSpinBox = QtWidgets.QDoubleSpinBox(self.frequencyDockWidgetContents) self.binSizeSpinBox = QtGui.QDoubleSpinBox(self.frequencyDockWidgetContents)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.binSizeSpinBox.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(self.binSizeSpinBox.sizePolicy().hasHeightForWidth())
self.binSizeSpinBox.setSizePolicy(sizePolicy) self.binSizeSpinBox.setSizePolicy(sizePolicy)
self.binSizeSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) self.binSizeSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.binSizeSpinBox.setProperty("showGroupSeparator", True)
self.binSizeSpinBox.setDecimals(3) self.binSizeSpinBox.setDecimals(3)
self.binSizeSpinBox.setMinimum(0.0) self.binSizeSpinBox.setMaximum(2800.0)
self.binSizeSpinBox.setMaximum(10000.0)
self.binSizeSpinBox.setProperty("value", 10.0) self.binSizeSpinBox.setProperty("value", 10.0)
self.binSizeSpinBox.setObjectName("binSizeSpinBox") self.binSizeSpinBox.setObjectName(_fromUtf8("binSizeSpinBox"))
self.formLayout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.binSizeSpinBox) self.formLayout.setWidget(2, QtGui.QFormLayout.FieldRole, self.binSizeSpinBox)
spacerItem1 = QtWidgets.QSpacerItem(20, 0, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) spacerItem1 = QtGui.QSpacerItem(20, 0, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.formLayout.setItem(3, QtWidgets.QFormLayout.SpanningRole, spacerItem1) self.formLayout.setItem(3, QtGui.QFormLayout.SpanningRole, spacerItem1)
self.frequencyDockWidget.setWidget(self.frequencyDockWidgetContents) self.frequencyDockWidget.setWidget(self.frequencyDockWidgetContents)
QSpectrumAnalyzerMainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.frequencyDockWidget) QSpectrumAnalyzerMainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.frequencyDockWidget)
self.settingsDockWidget = QtWidgets.QDockWidget(QSpectrumAnalyzerMainWindow) self.settingsDockWidget = QtGui.QDockWidget(QSpectrumAnalyzerMainWindow)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.settingsDockWidget.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(self.settingsDockWidget.sizePolicy().hasHeightForWidth())
self.settingsDockWidget.setSizePolicy(sizePolicy) self.settingsDockWidget.setSizePolicy(sizePolicy)
self.settingsDockWidget.setFeatures(QtWidgets.QDockWidget.DockWidgetFloatable|QtWidgets.QDockWidget.DockWidgetMovable) self.settingsDockWidget.setFeatures(QtGui.QDockWidget.DockWidgetFloatable|QtGui.QDockWidget.DockWidgetMovable)
self.settingsDockWidget.setObjectName("settingsDockWidget") self.settingsDockWidget.setObjectName(_fromUtf8("settingsDockWidget"))
self.settingsDockWidgetContents = QtWidgets.QWidget() self.settingsDockWidgetContents = QtGui.QWidget()
self.settingsDockWidgetContents.setObjectName("settingsDockWidgetContents") self.settingsDockWidgetContents.setObjectName(_fromUtf8("settingsDockWidgetContents"))
self.gridLayout = QtWidgets.QGridLayout(self.settingsDockWidgetContents) self.gridLayout = QtGui.QGridLayout(self.settingsDockWidgetContents)
self.gridLayout.setContentsMargins(0, 0, 0, 0) self.gridLayout.setMargin(0)
self.gridLayout.setObjectName("gridLayout") self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
self.label_4 = QtWidgets.QLabel(self.settingsDockWidgetContents) self.label_4 = QtGui.QLabel(self.settingsDockWidgetContents)
self.label_4.setObjectName("label_4") self.label_4.setObjectName(_fromUtf8("label_4"))
self.gridLayout.addWidget(self.label_4, 0, 0, 1, 1) self.gridLayout.addWidget(self.label_4, 0, 0, 1, 1)
self.label_6 = QtWidgets.QLabel(self.settingsDockWidgetContents) self.label_6 = QtGui.QLabel(self.settingsDockWidgetContents)
self.label_6.setObjectName("label_6") self.label_6.setObjectName(_fromUtf8("label_6"))
self.gridLayout.addWidget(self.label_6, 0, 1, 1, 1) self.gridLayout.addWidget(self.label_6, 0, 1, 1, 1)
self.intervalSpinBox = QtWidgets.QDoubleSpinBox(self.settingsDockWidgetContents) self.intervalSpinBox = QtGui.QDoubleSpinBox(self.settingsDockWidgetContents)
self.intervalSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) self.intervalSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.intervalSpinBox.setMaximum(999.0) self.intervalSpinBox.setMaximum(999.0)
self.intervalSpinBox.setProperty("value", 1.0) self.intervalSpinBox.setProperty("value", 1.0)
self.intervalSpinBox.setObjectName("intervalSpinBox") self.intervalSpinBox.setObjectName(_fromUtf8("intervalSpinBox"))
self.gridLayout.addWidget(self.intervalSpinBox, 1, 0, 1, 1) self.gridLayout.addWidget(self.intervalSpinBox, 1, 0, 1, 1)
self.label_5 = QtWidgets.QLabel(self.settingsDockWidgetContents) self.gainSpinBox = QtGui.QSpinBox(self.settingsDockWidgetContents)
self.label_5.setObjectName("label_5") 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.gridLayout.addWidget(self.label_5, 2, 0, 1, 1)
self.label_7 = QtWidgets.QLabel(self.settingsDockWidgetContents) self.label_7 = QtGui.QLabel(self.settingsDockWidgetContents)
self.label_7.setObjectName("label_7") self.label_7.setObjectName(_fromUtf8("label_7"))
self.gridLayout.addWidget(self.label_7, 2, 1, 1, 1) self.gridLayout.addWidget(self.label_7, 2, 1, 1, 1)
self.ppmSpinBox = QtWidgets.QSpinBox(self.settingsDockWidgetContents) self.ppmSpinBox = QtGui.QSpinBox(self.settingsDockWidgetContents)
self.ppmSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) self.ppmSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.ppmSpinBox.setMinimum(-999) self.ppmSpinBox.setMinimum(-999)
self.ppmSpinBox.setMaximum(999) self.ppmSpinBox.setMaximum(999)
self.ppmSpinBox.setObjectName("ppmSpinBox") self.ppmSpinBox.setObjectName(_fromUtf8("ppmSpinBox"))
self.gridLayout.addWidget(self.ppmSpinBox, 3, 0, 1, 1) self.gridLayout.addWidget(self.ppmSpinBox, 3, 0, 1, 1)
self.mainCurveCheckBox = QtWidgets.QCheckBox(self.settingsDockWidgetContents) self.mainCurveCheckBox = QtGui.QCheckBox(self.settingsDockWidgetContents)
self.mainCurveCheckBox.setChecked(True) self.mainCurveCheckBox.setChecked(True)
self.mainCurveCheckBox.setObjectName("mainCurveCheckBox") self.mainCurveCheckBox.setObjectName(_fromUtf8("mainCurveCheckBox"))
self.gridLayout.addWidget(self.mainCurveCheckBox, 4, 0, 1, 1) self.gridLayout.addWidget(self.mainCurveCheckBox, 4, 0, 1, 1)
self.colorsButton = QtWidgets.QPushButton(self.settingsDockWidgetContents) self.colorsButton = QtGui.QPushButton(self.settingsDockWidgetContents)
self.colorsButton.setObjectName("colorsButton") self.colorsButton.setObjectName(_fromUtf8("colorsButton"))
self.gridLayout.addWidget(self.colorsButton, 4, 1, 1, 2) self.gridLayout.addWidget(self.colorsButton, 4, 1, 1, 2)
self.peakHoldMaxCheckBox = QtWidgets.QCheckBox(self.settingsDockWidgetContents) self.peakHoldMaxCheckBox = QtGui.QCheckBox(self.settingsDockWidgetContents)
self.peakHoldMaxCheckBox.setObjectName("peakHoldMaxCheckBox") self.peakHoldMaxCheckBox.setObjectName(_fromUtf8("peakHoldMaxCheckBox"))
self.gridLayout.addWidget(self.peakHoldMaxCheckBox, 5, 0, 1, 1) self.gridLayout.addWidget(self.peakHoldMaxCheckBox, 5, 0, 1, 1)
self.peakHoldMinCheckBox = QtWidgets.QCheckBox(self.settingsDockWidgetContents) self.peakHoldMinCheckBox = QtGui.QCheckBox(self.settingsDockWidgetContents)
self.peakHoldMinCheckBox.setObjectName("peakHoldMinCheckBox") self.peakHoldMinCheckBox.setObjectName(_fromUtf8("peakHoldMinCheckBox"))
self.gridLayout.addWidget(self.peakHoldMinCheckBox, 5, 1, 1, 2) self.gridLayout.addWidget(self.peakHoldMinCheckBox, 5, 1, 1, 2)
self.averageCheckBox = QtWidgets.QCheckBox(self.settingsDockWidgetContents) self.averageCheckBox = QtGui.QCheckBox(self.settingsDockWidgetContents)
self.averageCheckBox.setObjectName("averageCheckBox") self.averageCheckBox.setObjectName(_fromUtf8("averageCheckBox"))
self.gridLayout.addWidget(self.averageCheckBox, 6, 0, 1, 1) self.gridLayout.addWidget(self.averageCheckBox, 6, 0, 1, 1)
self.smoothCheckBox = QtWidgets.QCheckBox(self.settingsDockWidgetContents) self.smoothCheckBox = QtGui.QCheckBox(self.settingsDockWidgetContents)
self.smoothCheckBox.setObjectName("smoothCheckBox") self.smoothCheckBox.setObjectName(_fromUtf8("smoothCheckBox"))
self.gridLayout.addWidget(self.smoothCheckBox, 7, 0, 1, 1) self.gridLayout.addWidget(self.smoothCheckBox, 7, 0, 1, 1)
self.smoothButton = QtWidgets.QToolButton(self.settingsDockWidgetContents) self.smoothButton = QtGui.QToolButton(self.settingsDockWidgetContents)
self.smoothButton.setAutoRaise(False) self.smoothButton.setAutoRaise(False)
self.smoothButton.setObjectName("smoothButton") self.smoothButton.setObjectName(_fromUtf8("smoothButton"))
self.gridLayout.addWidget(self.smoothButton, 7, 2, 1, 1) self.gridLayout.addWidget(self.smoothButton, 7, 2, 1, 1)
self.persistenceCheckBox = QtWidgets.QCheckBox(self.settingsDockWidgetContents) self.persistenceCheckBox = QtGui.QCheckBox(self.settingsDockWidgetContents)
self.persistenceCheckBox.setObjectName("persistenceCheckBox") self.persistenceCheckBox.setObjectName(_fromUtf8("persistenceCheckBox"))
self.gridLayout.addWidget(self.persistenceCheckBox, 8, 0, 1, 1) self.gridLayout.addWidget(self.persistenceCheckBox, 8, 0, 1, 1)
self.persistenceButton = QtWidgets.QToolButton(self.settingsDockWidgetContents) self.persistenceButton = QtGui.QToolButton(self.settingsDockWidgetContents)
self.persistenceButton.setAutoRaise(False) self.persistenceButton.setAutoRaise(False)
self.persistenceButton.setObjectName("persistenceButton") self.persistenceButton.setObjectName(_fromUtf8("persistenceButton"))
self.gridLayout.addWidget(self.persistenceButton, 8, 2, 1, 1) self.gridLayout.addWidget(self.persistenceButton, 8, 2, 1, 1)
spacerItem2 = QtWidgets.QSpacerItem(20, 1, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) spacerItem2 = QtGui.QSpacerItem(20, 1, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.gridLayout.addItem(spacerItem2, 11, 0, 1, 1) self.gridLayout.addItem(spacerItem2, 9, 0, 1, 1)
self.cropSpinBox = QtWidgets.QSpinBox(self.settingsDockWidgetContents) self.cropSpinBox = QtGui.QSpinBox(self.settingsDockWidgetContents)
self.cropSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) self.cropSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.cropSpinBox.setObjectName("cropSpinBox") self.cropSpinBox.setObjectName(_fromUtf8("cropSpinBox"))
self.gridLayout.addWidget(self.cropSpinBox, 3, 1, 1, 2) self.gridLayout.addWidget(self.cropSpinBox, 3, 1, 1, 2)
self.gainSpinBox = QtWidgets.QDoubleSpinBox(self.settingsDockWidgetContents)
self.gainSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.gainSpinBox.setDecimals(1)
self.gainSpinBox.setMinimum(-1.0)
self.gainSpinBox.setMaximum(999.0)
self.gainSpinBox.setSingleStep(1.0)
self.gainSpinBox.setProperty("value", -1.0)
self.gainSpinBox.setObjectName("gainSpinBox")
self.gridLayout.addWidget(self.gainSpinBox, 1, 1, 1, 2)
self.baselineCheckBox = QtWidgets.QCheckBox(self.settingsDockWidgetContents)
self.baselineCheckBox.setObjectName("baselineCheckBox")
self.gridLayout.addWidget(self.baselineCheckBox, 9, 0, 1, 1)
self.baselineButton = QtWidgets.QToolButton(self.settingsDockWidgetContents)
self.baselineButton.setAutoRaise(False)
self.baselineButton.setObjectName("baselineButton")
self.gridLayout.addWidget(self.baselineButton, 9, 2, 1, 1)
self.subtractBaselineCheckBox = QtWidgets.QCheckBox(self.settingsDockWidgetContents)
self.subtractBaselineCheckBox.setObjectName("subtractBaselineCheckBox")
self.gridLayout.addWidget(self.subtractBaselineCheckBox, 10, 0, 1, 1)
self.settingsDockWidget.setWidget(self.settingsDockWidgetContents) self.settingsDockWidget.setWidget(self.settingsDockWidgetContents)
QSpectrumAnalyzerMainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.settingsDockWidget) QSpectrumAnalyzerMainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.settingsDockWidget)
self.levelsDockWidget = QtWidgets.QDockWidget(QSpectrumAnalyzerMainWindow) self.levelsDockWidget = QtGui.QDockWidget(QSpectrumAnalyzerMainWindow)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.levelsDockWidget.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(self.levelsDockWidget.sizePolicy().hasHeightForWidth())
self.levelsDockWidget.setSizePolicy(sizePolicy) self.levelsDockWidget.setSizePolicy(sizePolicy)
self.levelsDockWidget.setFeatures(QtWidgets.QDockWidget.DockWidgetFloatable|QtWidgets.QDockWidget.DockWidgetMovable) self.levelsDockWidget.setFeatures(QtGui.QDockWidget.DockWidgetFloatable|QtGui.QDockWidget.DockWidgetMovable)
self.levelsDockWidget.setObjectName("levelsDockWidget") self.levelsDockWidget.setObjectName(_fromUtf8("levelsDockWidget"))
self.levelsDockWidgetContents = QtWidgets.QWidget() self.levelsDockWidgetContents = QtGui.QWidget()
self.levelsDockWidgetContents.setObjectName("levelsDockWidgetContents") self.levelsDockWidgetContents.setObjectName(_fromUtf8("levelsDockWidgetContents"))
self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.levelsDockWidgetContents) self.verticalLayout_6 = QtGui.QVBoxLayout(self.levelsDockWidgetContents)
self.verticalLayout_6.setContentsMargins(0, 0, 0, 0) self.verticalLayout_6.setMargin(0)
self.verticalLayout_6.setObjectName("verticalLayout_6") self.verticalLayout_6.setObjectName(_fromUtf8("verticalLayout_6"))
self.histogramPlotLayout = GraphicsLayoutWidget(self.levelsDockWidgetContents) self.histogramPlotLayout = GraphicsLayoutWidget(self.levelsDockWidgetContents)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Expanding) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Ignored, QtGui.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.histogramPlotLayout.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(self.histogramPlotLayout.sizePolicy().hasHeightForWidth())
self.histogramPlotLayout.setSizePolicy(sizePolicy) self.histogramPlotLayout.setSizePolicy(sizePolicy)
self.histogramPlotLayout.setObjectName("histogramPlotLayout") self.histogramPlotLayout.setObjectName(_fromUtf8("histogramPlotLayout"))
self.verticalLayout_6.addWidget(self.histogramPlotLayout) self.verticalLayout_6.addWidget(self.histogramPlotLayout)
self.levelsDockWidget.setWidget(self.levelsDockWidgetContents) self.levelsDockWidget.setWidget(self.levelsDockWidgetContents)
QSpectrumAnalyzerMainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.levelsDockWidget) QSpectrumAnalyzerMainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.levelsDockWidget)
self.action_Settings = QtWidgets.QAction(QSpectrumAnalyzerMainWindow) self.action_Settings = QtGui.QAction(QSpectrumAnalyzerMainWindow)
self.action_Settings.setObjectName("action_Settings") self.action_Settings.setObjectName(_fromUtf8("action_Settings"))
self.action_Quit = QtWidgets.QAction(QSpectrumAnalyzerMainWindow) self.action_Quit = QtGui.QAction(QSpectrumAnalyzerMainWindow)
self.action_Quit.setObjectName("action_Quit") self.action_Quit.setObjectName(_fromUtf8("action_Quit"))
self.action_About = QtWidgets.QAction(QSpectrumAnalyzerMainWindow) self.action_About = QtGui.QAction(QSpectrumAnalyzerMainWindow)
self.action_About.setObjectName("action_About") self.action_About.setObjectName(_fromUtf8("action_About"))
self.menu_File.addAction(self.action_Settings) self.menu_File.addAction(self.action_Settings)
self.menu_File.addSeparator() self.menu_File.addSeparator()
self.menu_File.addAction(self.action_Quit) self.menu_File.addAction(self.action_Quit)
@ -305,51 +303,44 @@ class Ui_QSpectrumAnalyzerMainWindow(object):
QSpectrumAnalyzerMainWindow.setTabOrder(self.smoothCheckBox, self.smoothButton) QSpectrumAnalyzerMainWindow.setTabOrder(self.smoothCheckBox, self.smoothButton)
QSpectrumAnalyzerMainWindow.setTabOrder(self.smoothButton, self.persistenceCheckBox) QSpectrumAnalyzerMainWindow.setTabOrder(self.smoothButton, self.persistenceCheckBox)
QSpectrumAnalyzerMainWindow.setTabOrder(self.persistenceCheckBox, self.persistenceButton) QSpectrumAnalyzerMainWindow.setTabOrder(self.persistenceCheckBox, self.persistenceButton)
QSpectrumAnalyzerMainWindow.setTabOrder(self.persistenceButton, self.baselineCheckBox) QSpectrumAnalyzerMainWindow.setTabOrder(self.persistenceButton, self.histogramPlotLayout)
QSpectrumAnalyzerMainWindow.setTabOrder(self.baselineCheckBox, self.baselineButton)
QSpectrumAnalyzerMainWindow.setTabOrder(self.baselineButton, self.subtractBaselineCheckBox)
QSpectrumAnalyzerMainWindow.setTabOrder(self.subtractBaselineCheckBox, self.histogramPlotLayout)
QSpectrumAnalyzerMainWindow.setTabOrder(self.histogramPlotLayout, self.mainPlotLayout) QSpectrumAnalyzerMainWindow.setTabOrder(self.histogramPlotLayout, self.mainPlotLayout)
QSpectrumAnalyzerMainWindow.setTabOrder(self.mainPlotLayout, self.waterfallPlotLayout) QSpectrumAnalyzerMainWindow.setTabOrder(self.mainPlotLayout, self.waterfallPlotLayout)
def retranslateUi(self, QSpectrumAnalyzerMainWindow): def retranslateUi(self, QSpectrumAnalyzerMainWindow):
_translate = QtCore.QCoreApplication.translate QSpectrumAnalyzerMainWindow.setWindowTitle(_translate("QSpectrumAnalyzerMainWindow", "QSpectrumAnalyzer", None))
QSpectrumAnalyzerMainWindow.setWindowTitle(_translate("QSpectrumAnalyzerMainWindow", "QSpectrumAnalyzer")) self.menu_File.setTitle(_translate("QSpectrumAnalyzerMainWindow", "&File", None))
self.menu_File.setTitle(_translate("QSpectrumAnalyzerMainWindow", "&File")) self.menu_Help.setTitle(_translate("QSpectrumAnalyzerMainWindow", "&Help", None))
self.menu_Help.setTitle(_translate("QSpectrumAnalyzerMainWindow", "&Help")) self.controlsDockWidget.setWindowTitle(_translate("QSpectrumAnalyzerMainWindow", "Controls", None))
self.controlsDockWidget.setWindowTitle(_translate("QSpectrumAnalyzerMainWindow", "Controls")) self.startButton.setText(_translate("QSpectrumAnalyzerMainWindow", "&Start", None))
self.startButton.setText(_translate("QSpectrumAnalyzerMainWindow", "&Start")) self.stopButton.setText(_translate("QSpectrumAnalyzerMainWindow", "S&top", None))
self.stopButton.setText(_translate("QSpectrumAnalyzerMainWindow", "S&top")) self.singleShotButton.setText(_translate("QSpectrumAnalyzerMainWindow", "Si&ngle shot", None))
self.singleShotButton.setText(_translate("QSpectrumAnalyzerMainWindow", "Si&ngle shot")) self.frequencyDockWidget.setWindowTitle(_translate("QSpectrumAnalyzerMainWindow", "Frequency", None))
self.frequencyDockWidget.setWindowTitle(_translate("QSpectrumAnalyzerMainWindow", "Frequency")) self.label_2.setText(_translate("QSpectrumAnalyzerMainWindow", "Start:", None))
self.label_2.setText(_translate("QSpectrumAnalyzerMainWindow", "Start:")) self.startFreqSpinBox.setSuffix(_translate("QSpectrumAnalyzerMainWindow", " MHz", None))
self.startFreqSpinBox.setSuffix(_translate("QSpectrumAnalyzerMainWindow", " MHz")) self.label_3.setText(_translate("QSpectrumAnalyzerMainWindow", "Stop:", None))
self.label_3.setText(_translate("QSpectrumAnalyzerMainWindow", "Stop:")) self.stopFreqSpinBox.setSuffix(_translate("QSpectrumAnalyzerMainWindow", " MHz", None))
self.stopFreqSpinBox.setSuffix(_translate("QSpectrumAnalyzerMainWindow", " MHz")) self.label.setText(_translate("QSpectrumAnalyzerMainWindow", "Bin size:", None))
self.label.setText(_translate("QSpectrumAnalyzerMainWindow", "&Bin size:")) self.binSizeSpinBox.setSuffix(_translate("QSpectrumAnalyzerMainWindow", " kHz", None))
self.binSizeSpinBox.setSuffix(_translate("QSpectrumAnalyzerMainWindow", " kHz")) self.settingsDockWidget.setWindowTitle(_translate("QSpectrumAnalyzerMainWindow", "Settings", None))
self.settingsDockWidget.setWindowTitle(_translate("QSpectrumAnalyzerMainWindow", "Settings")) self.label_4.setText(_translate("QSpectrumAnalyzerMainWindow", "Interval [s]:", None))
self.label_4.setText(_translate("QSpectrumAnalyzerMainWindow", "&Interval [s]:")) self.label_6.setText(_translate("QSpectrumAnalyzerMainWindow", "Gain [dB]:", None))
self.label_6.setText(_translate("QSpectrumAnalyzerMainWindow", "&Gain [dB]:")) self.gainSpinBox.setSpecialValueText(_translate("QSpectrumAnalyzerMainWindow", "auto", None))
self.label_5.setText(_translate("QSpectrumAnalyzerMainWindow", "Corr. [ppm]:")) self.label_5.setText(_translate("QSpectrumAnalyzerMainWindow", "Corr. [ppm]:", None))
self.label_7.setText(_translate("QSpectrumAnalyzerMainWindow", "Crop [%]:")) self.label_7.setText(_translate("QSpectrumAnalyzerMainWindow", "Crop [%]:", None))
self.mainCurveCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Main curve")) self.mainCurveCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Main curve", None))
self.colorsButton.setText(_translate("QSpectrumAnalyzerMainWindow", "Colors...")) self.colorsButton.setText(_translate("QSpectrumAnalyzerMainWindow", "Colors...", None))
self.peakHoldMaxCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Max. hold")) self.peakHoldMaxCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Max. hold", None))
self.peakHoldMinCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Min. hold")) self.peakHoldMinCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Min. hold", None))
self.averageCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Average")) self.averageCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Average", None))
self.smoothCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Smoothing")) self.smoothCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Smoothing", None))
self.smoothButton.setText(_translate("QSpectrumAnalyzerMainWindow", "...")) self.smoothButton.setText(_translate("QSpectrumAnalyzerMainWindow", "...", None))
self.persistenceCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Persistence")) self.persistenceCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Persistence", None))
self.persistenceButton.setText(_translate("QSpectrumAnalyzerMainWindow", "...")) self.persistenceButton.setText(_translate("QSpectrumAnalyzerMainWindow", "...", None))
self.gainSpinBox.setSpecialValueText(_translate("QSpectrumAnalyzerMainWindow", "auto")) self.levelsDockWidget.setWindowTitle(_translate("QSpectrumAnalyzerMainWindow", "Levels", None))
self.baselineCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Baseline")) self.action_Settings.setText(_translate("QSpectrumAnalyzerMainWindow", "&Settings...", None))
self.baselineButton.setText(_translate("QSpectrumAnalyzerMainWindow", "...")) self.action_Quit.setText(_translate("QSpectrumAnalyzerMainWindow", "&Quit", None))
self.subtractBaselineCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Subtract baseline")) self.action_Quit.setShortcut(_translate("QSpectrumAnalyzerMainWindow", "Ctrl+Q", None))
self.levelsDockWidget.setWindowTitle(_translate("QSpectrumAnalyzerMainWindow", "Levels")) self.action_About.setText(_translate("QSpectrumAnalyzerMainWindow", "&About", None))
self.action_Settings.setText(_translate("QSpectrumAnalyzerMainWindow", "&Settings..."))
self.action_Quit.setText(_translate("QSpectrumAnalyzerMainWindow", "&Quit"))
self.action_Quit.setShortcut(_translate("QSpectrumAnalyzerMainWindow", "Ctrl+Q"))
self.action_About.setText(_translate("QSpectrumAnalyzerMainWindow", "&About"))
from pyqtgraph import GraphicsLayoutWidget from pyqtgraph import GraphicsLayoutWidget

View File

@ -1,53 +0,0 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'qspectrumanalyzer/qspectrumanalyzer_baseline.ui'
#
# Created by: PyQt5 UI code generator 5.8
#
# WARNING! All changes made in this file will be lost!
from Qt import QtCore, QtGui, QtWidgets
class Ui_QSpectrumAnalyzerBaseline(object):
def setupUi(self, QSpectrumAnalyzerBaseline):
QSpectrumAnalyzerBaseline.setObjectName("QSpectrumAnalyzerBaseline")
QSpectrumAnalyzerBaseline.resize(500, 100)
self.verticalLayout = QtWidgets.QVBoxLayout(QSpectrumAnalyzerBaseline)
self.verticalLayout.setObjectName("verticalLayout")
self.formLayout = QtWidgets.QFormLayout()
self.formLayout.setObjectName("formLayout")
self.label = QtWidgets.QLabel(QSpectrumAnalyzerBaseline)
self.label.setObjectName("label")
self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.label)
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.baselineFileEdit = QtWidgets.QLineEdit(QSpectrumAnalyzerBaseline)
self.baselineFileEdit.setObjectName("baselineFileEdit")
self.horizontalLayout.addWidget(self.baselineFileEdit)
self.baselineFileButton = QtWidgets.QToolButton(QSpectrumAnalyzerBaseline)
self.baselineFileButton.setMinimumSize(QtCore.QSize(50, 0))
self.baselineFileButton.setObjectName("baselineFileButton")
self.horizontalLayout.addWidget(self.baselineFileButton)
self.formLayout.setLayout(0, QtWidgets.QFormLayout.FieldRole, self.horizontalLayout)
self.verticalLayout.addLayout(self.formLayout)
spacerItem = QtWidgets.QSpacerItem(20, 1, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.verticalLayout.addItem(spacerItem)
self.buttonBox = QtWidgets.QDialogButtonBox(QSpectrumAnalyzerBaseline)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
self.buttonBox.setObjectName("buttonBox")
self.verticalLayout.addWidget(self.buttonBox)
self.label.setBuddy(self.baselineFileEdit)
self.retranslateUi(QSpectrumAnalyzerBaseline)
self.buttonBox.accepted.connect(QSpectrumAnalyzerBaseline.accept)
self.buttonBox.rejected.connect(QSpectrumAnalyzerBaseline.reject)
QtCore.QMetaObject.connectSlotsByName(QSpectrumAnalyzerBaseline)
QSpectrumAnalyzerBaseline.setTabOrder(self.baselineFileEdit, self.baselineFileButton)
def retranslateUi(self, QSpectrumAnalyzerBaseline):
_translate = QtCore.QCoreApplication.translate
QSpectrumAnalyzerBaseline.setWindowTitle(_translate("QSpectrumAnalyzerBaseline", "Baseline - QSpectrumAnalyzer"))
self.label.setText(_translate("QSpectrumAnalyzerBaseline", "Baseline &file:"))
self.baselineFileButton.setText(_translate("QSpectrumAnalyzerBaseline", "..."))

View File

@ -2,125 +2,124 @@
# Form implementation generated from reading ui file 'qspectrumanalyzer/qspectrumanalyzer_colors.ui' # Form implementation generated from reading ui file 'qspectrumanalyzer/qspectrumanalyzer_colors.ui'
# #
# Created by: PyQt5 UI code generator 5.8 # Created by: PyQt4 UI code generator 4.12
# #
# WARNING! All changes made in this file will be lost! # WARNING! All changes made in this file will be lost!
from Qt import QtCore, QtGui, QtWidgets from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_QSpectrumAnalyzerColors(object): class Ui_QSpectrumAnalyzerColors(object):
def setupUi(self, QSpectrumAnalyzerColors): def setupUi(self, QSpectrumAnalyzerColors):
QSpectrumAnalyzerColors.setObjectName("QSpectrumAnalyzerColors") QSpectrumAnalyzerColors.setObjectName(_fromUtf8("QSpectrumAnalyzerColors"))
QSpectrumAnalyzerColors.resize(253, 266) QSpectrumAnalyzerColors.resize(232, 260)
self.verticalLayout = QtWidgets.QVBoxLayout(QSpectrumAnalyzerColors) self.verticalLayout = QtGui.QVBoxLayout(QSpectrumAnalyzerColors)
self.verticalLayout.setObjectName("verticalLayout") self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
self.formLayout = QtWidgets.QFormLayout() self.formLayout = QtGui.QFormLayout()
self.formLayout.setObjectName("formLayout") self.formLayout.setObjectName(_fromUtf8("formLayout"))
self.label_2 = QtWidgets.QLabel(QSpectrumAnalyzerColors) self.label_2 = QtGui.QLabel(QSpectrumAnalyzerColors)
self.label_2.setObjectName("label_2") self.label_2.setObjectName(_fromUtf8("label_2"))
self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.label_2) self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.label_2)
self.mainColorButton = ColorButton(QSpectrumAnalyzerColors) self.mainColorButton = ColorButton(QSpectrumAnalyzerColors)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.mainColorButton.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(self.mainColorButton.sizePolicy().hasHeightForWidth())
self.mainColorButton.setSizePolicy(sizePolicy) self.mainColorButton.setSizePolicy(sizePolicy)
self.mainColorButton.setObjectName("mainColorButton") self.mainColorButton.setObjectName(_fromUtf8("mainColorButton"))
self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.mainColorButton) self.formLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.mainColorButton)
self.label_4 = QtWidgets.QLabel(QSpectrumAnalyzerColors) self.label_4 = QtGui.QLabel(QSpectrumAnalyzerColors)
self.label_4.setObjectName("label_4") self.label_4.setObjectName(_fromUtf8("label_4"))
self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label_4) self.formLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.label_4)
self.peakHoldMaxColorButton = ColorButton(QSpectrumAnalyzerColors) self.peakHoldMaxColorButton = ColorButton(QSpectrumAnalyzerColors)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.peakHoldMaxColorButton.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(self.peakHoldMaxColorButton.sizePolicy().hasHeightForWidth())
self.peakHoldMaxColorButton.setSizePolicy(sizePolicy) self.peakHoldMaxColorButton.setSizePolicy(sizePolicy)
self.peakHoldMaxColorButton.setObjectName("peakHoldMaxColorButton") self.peakHoldMaxColorButton.setObjectName(_fromUtf8("peakHoldMaxColorButton"))
self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.peakHoldMaxColorButton) self.formLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.peakHoldMaxColorButton)
self.label_6 = QtWidgets.QLabel(QSpectrumAnalyzerColors) self.label_6 = QtGui.QLabel(QSpectrumAnalyzerColors)
self.label_6.setObjectName("label_6") self.label_6.setObjectName(_fromUtf8("label_6"))
self.formLayout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.label_6) self.formLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.label_6)
self.peakHoldMinColorButton = ColorButton(QSpectrumAnalyzerColors) self.peakHoldMinColorButton = ColorButton(QSpectrumAnalyzerColors)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.peakHoldMinColorButton.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(self.peakHoldMinColorButton.sizePolicy().hasHeightForWidth())
self.peakHoldMinColorButton.setSizePolicy(sizePolicy) self.peakHoldMinColorButton.setSizePolicy(sizePolicy)
self.peakHoldMinColorButton.setObjectName("peakHoldMinColorButton") self.peakHoldMinColorButton.setObjectName(_fromUtf8("peakHoldMinColorButton"))
self.formLayout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.peakHoldMinColorButton) self.formLayout.setWidget(2, QtGui.QFormLayout.FieldRole, self.peakHoldMinColorButton)
self.label_5 = QtWidgets.QLabel(QSpectrumAnalyzerColors) self.label_5 = QtGui.QLabel(QSpectrumAnalyzerColors)
self.label_5.setObjectName("label_5") self.label_5.setObjectName(_fromUtf8("label_5"))
self.formLayout.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.label_5) self.formLayout.setWidget(3, QtGui.QFormLayout.LabelRole, self.label_5)
self.averageColorButton = ColorButton(QSpectrumAnalyzerColors) self.averageColorButton = ColorButton(QSpectrumAnalyzerColors)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.averageColorButton.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(self.averageColorButton.sizePolicy().hasHeightForWidth())
self.averageColorButton.setSizePolicy(sizePolicy) self.averageColorButton.setSizePolicy(sizePolicy)
self.averageColorButton.setObjectName("averageColorButton") self.averageColorButton.setObjectName(_fromUtf8("averageColorButton"))
self.formLayout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.averageColorButton) self.formLayout.setWidget(3, QtGui.QFormLayout.FieldRole, self.averageColorButton)
self.label_3 = QtWidgets.QLabel(QSpectrumAnalyzerColors) self.label_3 = QtGui.QLabel(QSpectrumAnalyzerColors)
self.label_3.setObjectName("label_3") self.label_3.setObjectName(_fromUtf8("label_3"))
self.formLayout.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.label_3) self.formLayout.setWidget(4, QtGui.QFormLayout.LabelRole, self.label_3)
self.persistenceColorButton = ColorButton(QSpectrumAnalyzerColors) self.persistenceColorButton = ColorButton(QSpectrumAnalyzerColors)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.persistenceColorButton.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(self.persistenceColorButton.sizePolicy().hasHeightForWidth())
self.persistenceColorButton.setSizePolicy(sizePolicy) self.persistenceColorButton.setSizePolicy(sizePolicy)
self.persistenceColorButton.setObjectName("persistenceColorButton") self.persistenceColorButton.setObjectName(_fromUtf8("persistenceColorButton"))
self.formLayout.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.persistenceColorButton) self.formLayout.setWidget(4, QtGui.QFormLayout.FieldRole, self.persistenceColorButton)
self.label = QtWidgets.QLabel(QSpectrumAnalyzerColors)
self.label.setObjectName("label")
self.formLayout.setWidget(5, QtWidgets.QFormLayout.LabelRole, self.label)
self.baselineColorButton = ColorButton(QSpectrumAnalyzerColors)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.baselineColorButton.sizePolicy().hasHeightForWidth())
self.baselineColorButton.setSizePolicy(sizePolicy)
self.baselineColorButton.setObjectName("baselineColorButton")
self.formLayout.setWidget(5, QtWidgets.QFormLayout.FieldRole, self.baselineColorButton)
self.verticalLayout.addLayout(self.formLayout) self.verticalLayout.addLayout(self.formLayout)
spacerItem = QtWidgets.QSpacerItem(20, 2, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) spacerItem = QtGui.QSpacerItem(20, 2, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.verticalLayout.addItem(spacerItem) self.verticalLayout.addItem(spacerItem)
self.buttonBox = QtWidgets.QDialogButtonBox(QSpectrumAnalyzerColors) self.buttonBox = QtGui.QDialogButtonBox(QSpectrumAnalyzerColors)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal) self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok) self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
self.buttonBox.setObjectName("buttonBox") self.buttonBox.setObjectName(_fromUtf8("buttonBox"))
self.verticalLayout.addWidget(self.buttonBox) self.verticalLayout.addWidget(self.buttonBox)
self.label_2.setBuddy(self.mainColorButton) self.label_2.setBuddy(self.mainColorButton)
self.label_4.setBuddy(self.peakHoldMaxColorButton) self.label_4.setBuddy(self.peakHoldMaxColorButton)
self.label_6.setBuddy(self.peakHoldMinColorButton) self.label_6.setBuddy(self.peakHoldMinColorButton)
self.label_5.setBuddy(self.averageColorButton) self.label_5.setBuddy(self.averageColorButton)
self.label_3.setBuddy(self.persistenceColorButton) self.label_3.setBuddy(self.persistenceColorButton)
self.label.setBuddy(self.baselineColorButton)
self.retranslateUi(QSpectrumAnalyzerColors) self.retranslateUi(QSpectrumAnalyzerColors)
self.buttonBox.accepted.connect(QSpectrumAnalyzerColors.accept) QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), QSpectrumAnalyzerColors.accept)
self.buttonBox.rejected.connect(QSpectrumAnalyzerColors.reject) QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), QSpectrumAnalyzerColors.reject)
QtCore.QMetaObject.connectSlotsByName(QSpectrumAnalyzerColors) QtCore.QMetaObject.connectSlotsByName(QSpectrumAnalyzerColors)
QSpectrumAnalyzerColors.setTabOrder(self.mainColorButton, self.peakHoldMaxColorButton) QSpectrumAnalyzerColors.setTabOrder(self.mainColorButton, self.peakHoldMaxColorButton)
QSpectrumAnalyzerColors.setTabOrder(self.peakHoldMaxColorButton, self.peakHoldMinColorButton) QSpectrumAnalyzerColors.setTabOrder(self.peakHoldMaxColorButton, self.peakHoldMinColorButton)
QSpectrumAnalyzerColors.setTabOrder(self.peakHoldMinColorButton, self.averageColorButton) QSpectrumAnalyzerColors.setTabOrder(self.peakHoldMinColorButton, self.averageColorButton)
QSpectrumAnalyzerColors.setTabOrder(self.averageColorButton, self.persistenceColorButton) QSpectrumAnalyzerColors.setTabOrder(self.averageColorButton, self.persistenceColorButton)
QSpectrumAnalyzerColors.setTabOrder(self.persistenceColorButton, self.baselineColorButton) QSpectrumAnalyzerColors.setTabOrder(self.persistenceColorButton, self.buttonBox)
def retranslateUi(self, QSpectrumAnalyzerColors): def retranslateUi(self, QSpectrumAnalyzerColors):
_translate = QtCore.QCoreApplication.translate QSpectrumAnalyzerColors.setWindowTitle(_translate("QSpectrumAnalyzerColors", "Colors - QSpectrumAnalyzer", None))
QSpectrumAnalyzerColors.setWindowTitle(_translate("QSpectrumAnalyzerColors", "Colors - QSpectrumAnalyzer")) self.label_2.setText(_translate("QSpectrumAnalyzerColors", "Main curve color:", None))
self.label_2.setText(_translate("QSpectrumAnalyzerColors", "&Main curve color:")) self.mainColorButton.setText(_translate("QSpectrumAnalyzerColors", "...", None))
self.mainColorButton.setText(_translate("QSpectrumAnalyzerColors", "...")) self.label_4.setText(_translate("QSpectrumAnalyzerColors", "Max. peak hold color:", None))
self.label_4.setText(_translate("QSpectrumAnalyzerColors", "Max. peak &hold color:")) self.peakHoldMaxColorButton.setText(_translate("QSpectrumAnalyzerColors", "...", None))
self.peakHoldMaxColorButton.setText(_translate("QSpectrumAnalyzerColors", "...")) self.label_6.setText(_translate("QSpectrumAnalyzerColors", "Min. peak hold color:", None))
self.label_6.setText(_translate("QSpectrumAnalyzerColors", "M&in. peak hold color:")) self.peakHoldMinColorButton.setText(_translate("QSpectrumAnalyzerColors", "...", None))
self.peakHoldMinColorButton.setText(_translate("QSpectrumAnalyzerColors", "...")) self.label_5.setText(_translate("QSpectrumAnalyzerColors", "Average color:", None))
self.label_5.setText(_translate("QSpectrumAnalyzerColors", "Average &color:")) self.averageColorButton.setText(_translate("QSpectrumAnalyzerColors", "...", None))
self.averageColorButton.setText(_translate("QSpectrumAnalyzerColors", "...")) self.label_3.setText(_translate("QSpectrumAnalyzerColors", "Persistence color:", None))
self.label_3.setText(_translate("QSpectrumAnalyzerColors", "Persistence co&lor:")) self.persistenceColorButton.setText(_translate("QSpectrumAnalyzerColors", "...", None))
self.persistenceColorButton.setText(_translate("QSpectrumAnalyzerColors", "..."))
self.label.setText(_translate("QSpectrumAnalyzerColors", "&Baseline color:"))
self.baselineColorButton.setText(_translate("QSpectrumAnalyzerColors", "..."))
from pyqtgraph import ColorButton from pyqtgraph import ColorButton

View File

@ -2,59 +2,72 @@
# Form implementation generated from reading ui file 'qspectrumanalyzer/qspectrumanalyzer_persistence.ui' # Form implementation generated from reading ui file 'qspectrumanalyzer/qspectrumanalyzer_persistence.ui'
# #
# Created by: PyQt5 UI code generator 5.8 # Created by: PyQt4 UI code generator 4.12
# #
# WARNING! All changes made in this file will be lost! # WARNING! All changes made in this file will be lost!
from Qt import QtCore, QtGui, QtWidgets from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_QSpectrumAnalyzerPersistence(object): class Ui_QSpectrumAnalyzerPersistence(object):
def setupUi(self, QSpectrumAnalyzerPersistence): def setupUi(self, QSpectrumAnalyzerPersistence):
QSpectrumAnalyzerPersistence.setObjectName("QSpectrumAnalyzerPersistence") QSpectrumAnalyzerPersistence.setObjectName(_fromUtf8("QSpectrumAnalyzerPersistence"))
QSpectrumAnalyzerPersistence.resize(250, 130) QSpectrumAnalyzerPersistence.resize(250, 130)
self.verticalLayout = QtWidgets.QVBoxLayout(QSpectrumAnalyzerPersistence) self.verticalLayout = QtGui.QVBoxLayout(QSpectrumAnalyzerPersistence)
self.verticalLayout.setObjectName("verticalLayout") self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
self.formLayout = QtWidgets.QFormLayout() self.formLayout = QtGui.QFormLayout()
self.formLayout.setObjectName("formLayout") self.formLayout.setObjectName(_fromUtf8("formLayout"))
self.label_2 = QtWidgets.QLabel(QSpectrumAnalyzerPersistence) self.label_2 = QtGui.QLabel(QSpectrumAnalyzerPersistence)
self.label_2.setObjectName("label_2") self.label_2.setObjectName(_fromUtf8("label_2"))
self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.label_2) self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.label_2)
self.decayFunctionComboBox = QtWidgets.QComboBox(QSpectrumAnalyzerPersistence) self.decayFunctionComboBox = QtGui.QComboBox(QSpectrumAnalyzerPersistence)
self.decayFunctionComboBox.setObjectName("decayFunctionComboBox") self.decayFunctionComboBox.setObjectName(_fromUtf8("decayFunctionComboBox"))
self.decayFunctionComboBox.addItem("") self.decayFunctionComboBox.addItem(_fromUtf8(""))
self.decayFunctionComboBox.addItem("") self.decayFunctionComboBox.addItem(_fromUtf8(""))
self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.decayFunctionComboBox) self.formLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.decayFunctionComboBox)
self.label = QtWidgets.QLabel(QSpectrumAnalyzerPersistence) self.label = QtGui.QLabel(QSpectrumAnalyzerPersistence)
self.label.setObjectName("label") self.label.setObjectName(_fromUtf8("label"))
self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label) self.formLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.label)
self.persistenceLengthSpinBox = QtWidgets.QSpinBox(QSpectrumAnalyzerPersistence) self.persistenceLengthSpinBox = QtGui.QSpinBox(QSpectrumAnalyzerPersistence)
self.persistenceLengthSpinBox.setProperty("value", 5) self.persistenceLengthSpinBox.setProperty("value", 5)
self.persistenceLengthSpinBox.setObjectName("persistenceLengthSpinBox") self.persistenceLengthSpinBox.setObjectName(_fromUtf8("persistenceLengthSpinBox"))
self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.persistenceLengthSpinBox) self.formLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.persistenceLengthSpinBox)
self.verticalLayout.addLayout(self.formLayout) self.verticalLayout.addLayout(self.formLayout)
spacerItem = QtWidgets.QSpacerItem(20, 5, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) spacerItem = QtGui.QSpacerItem(20, 5, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.verticalLayout.addItem(spacerItem) self.verticalLayout.addItem(spacerItem)
self.buttonBox = QtWidgets.QDialogButtonBox(QSpectrumAnalyzerPersistence) self.buttonBox = QtGui.QDialogButtonBox(QSpectrumAnalyzerPersistence)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal) self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok) self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
self.buttonBox.setObjectName("buttonBox") self.buttonBox.setObjectName(_fromUtf8("buttonBox"))
self.verticalLayout.addWidget(self.buttonBox) self.verticalLayout.addWidget(self.buttonBox)
self.label_2.setBuddy(self.decayFunctionComboBox) self.label_2.setBuddy(self.decayFunctionComboBox)
self.label.setBuddy(self.persistenceLengthSpinBox) self.label.setBuddy(self.persistenceLengthSpinBox)
self.retranslateUi(QSpectrumAnalyzerPersistence) self.retranslateUi(QSpectrumAnalyzerPersistence)
self.decayFunctionComboBox.setCurrentIndex(1) self.decayFunctionComboBox.setCurrentIndex(1)
self.buttonBox.accepted.connect(QSpectrumAnalyzerPersistence.accept) QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), QSpectrumAnalyzerPersistence.accept)
self.buttonBox.rejected.connect(QSpectrumAnalyzerPersistence.reject) QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), QSpectrumAnalyzerPersistence.reject)
QtCore.QMetaObject.connectSlotsByName(QSpectrumAnalyzerPersistence) QtCore.QMetaObject.connectSlotsByName(QSpectrumAnalyzerPersistence)
QSpectrumAnalyzerPersistence.setTabOrder(self.decayFunctionComboBox, self.persistenceLengthSpinBox) QSpectrumAnalyzerPersistence.setTabOrder(self.decayFunctionComboBox, self.persistenceLengthSpinBox)
QSpectrumAnalyzerPersistence.setTabOrder(self.persistenceLengthSpinBox, self.buttonBox) QSpectrumAnalyzerPersistence.setTabOrder(self.persistenceLengthSpinBox, self.buttonBox)
def retranslateUi(self, QSpectrumAnalyzerPersistence): def retranslateUi(self, QSpectrumAnalyzerPersistence):
_translate = QtCore.QCoreApplication.translate QSpectrumAnalyzerPersistence.setWindowTitle(_translate("QSpectrumAnalyzerPersistence", "Persistence - QSpectrumAnalyzer", None))
QSpectrumAnalyzerPersistence.setWindowTitle(_translate("QSpectrumAnalyzerPersistence", "Persistence - QSpectrumAnalyzer")) self.label_2.setText(_translate("QSpectrumAnalyzerPersistence", "Decay function:", None))
self.label_2.setText(_translate("QSpectrumAnalyzerPersistence", "Decay function:")) self.decayFunctionComboBox.setItemText(0, _translate("QSpectrumAnalyzerPersistence", "linear", None))
self.decayFunctionComboBox.setItemText(0, _translate("QSpectrumAnalyzerPersistence", "linear")) self.decayFunctionComboBox.setItemText(1, _translate("QSpectrumAnalyzerPersistence", "exponential", None))
self.decayFunctionComboBox.setItemText(1, _translate("QSpectrumAnalyzerPersistence", "exponential")) self.label.setText(_translate("QSpectrumAnalyzerPersistence", "Persistence length:", None))
self.label.setText(_translate("QSpectrumAnalyzerPersistence", "Persistence length:"))

View File

@ -2,170 +2,119 @@
# Form implementation generated from reading ui file 'qspectrumanalyzer/qspectrumanalyzer_settings.ui' # Form implementation generated from reading ui file 'qspectrumanalyzer/qspectrumanalyzer_settings.ui'
# #
# Created by: PyQt5 UI code generator 5.8 # Created by: PyQt4 UI code generator 4.12
# #
# WARNING! All changes made in this file will be lost! # WARNING! All changes made in this file will be lost!
from Qt import QtCore, QtGui, QtWidgets from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_QSpectrumAnalyzerSettings(object): class Ui_QSpectrumAnalyzerSettings(object):
def setupUi(self, QSpectrumAnalyzerSettings): def setupUi(self, QSpectrumAnalyzerSettings):
QSpectrumAnalyzerSettings.setObjectName("QSpectrumAnalyzerSettings") QSpectrumAnalyzerSettings.setObjectName(_fromUtf8("QSpectrumAnalyzerSettings"))
QSpectrumAnalyzerSettings.resize(600, 388) QSpectrumAnalyzerSettings.resize(420, 255)
self.verticalLayout = QtWidgets.QVBoxLayout(QSpectrumAnalyzerSettings) self.verticalLayout = QtGui.QVBoxLayout(QSpectrumAnalyzerSettings)
self.verticalLayout.setObjectName("verticalLayout") self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
self.formLayout = QtWidgets.QFormLayout() self.formLayout = QtGui.QFormLayout()
self.formLayout.setObjectName("formLayout") self.formLayout.setObjectName(_fromUtf8("formLayout"))
self.label_3 = QtWidgets.QLabel(QSpectrumAnalyzerSettings) self.label_3 = QtGui.QLabel(QSpectrumAnalyzerSettings)
self.label_3.setObjectName("label_3") self.label_3.setObjectName(_fromUtf8("label_3"))
self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.label_3) self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.label_3)
self.backendComboBox = QtWidgets.QComboBox(QSpectrumAnalyzerSettings) self.backendComboBox = QtGui.QComboBox(QSpectrumAnalyzerSettings)
self.backendComboBox.setObjectName("backendComboBox") self.backendComboBox.setObjectName(_fromUtf8("backendComboBox"))
self.backendComboBox.addItem("") self.backendComboBox.addItem(_fromUtf8(""))
self.backendComboBox.addItem("") self.backendComboBox.addItem(_fromUtf8(""))
self.backendComboBox.addItem("") self.backendComboBox.addItem(_fromUtf8(""))
self.backendComboBox.addItem("") self.backendComboBox.addItem(_fromUtf8(""))
self.backendComboBox.addItem("") self.backendComboBox.addItem(_fromUtf8(""))
self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.backendComboBox) self.formLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.backendComboBox)
self.label = QtWidgets.QLabel(QSpectrumAnalyzerSettings) self.label = QtGui.QLabel(QSpectrumAnalyzerSettings)
self.label.setObjectName("label") self.label.setObjectName(_fromUtf8("label"))
self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label) self.formLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.label)
self.horizontalLayout = QtWidgets.QHBoxLayout() self.horizontalLayout = QtGui.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout") self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
self.executableEdit = QtWidgets.QLineEdit(QSpectrumAnalyzerSettings) self.executableEdit = QtGui.QLineEdit(QSpectrumAnalyzerSettings)
self.executableEdit.setObjectName("executableEdit") self.executableEdit.setObjectName(_fromUtf8("executableEdit"))
self.horizontalLayout.addWidget(self.executableEdit) self.horizontalLayout.addWidget(self.executableEdit)
self.executableButton = QtWidgets.QToolButton(QSpectrumAnalyzerSettings) self.executableButton = QtGui.QToolButton(QSpectrumAnalyzerSettings)
self.executableButton.setMinimumSize(QtCore.QSize(50, 0)) self.executableButton.setObjectName(_fromUtf8("executableButton"))
self.executableButton.setObjectName("executableButton")
self.horizontalLayout.addWidget(self.executableButton) self.horizontalLayout.addWidget(self.executableButton)
self.formLayout.setLayout(1, QtWidgets.QFormLayout.FieldRole, self.horizontalLayout) self.formLayout.setLayout(1, QtGui.QFormLayout.FieldRole, self.horizontalLayout)
self.label_5 = QtWidgets.QLabel(QSpectrumAnalyzerSettings) self.label_5 = QtGui.QLabel(QSpectrumAnalyzerSettings)
self.label_5.setObjectName("label_5") self.label_5.setObjectName(_fromUtf8("label_5"))
self.formLayout.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.label_5) self.formLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.label_5)
self.label_4 = QtWidgets.QLabel(QSpectrumAnalyzerSettings) self.deviceEdit = QtGui.QLineEdit(QSpectrumAnalyzerSettings)
self.label_4.setObjectName("label_4") self.deviceEdit.setObjectName(_fromUtf8("deviceEdit"))
self.formLayout.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.label_4) self.formLayout.setWidget(2, QtGui.QFormLayout.FieldRole, self.deviceEdit)
self.label_2 = QtWidgets.QLabel(QSpectrumAnalyzerSettings) self.label_4 = QtGui.QLabel(QSpectrumAnalyzerSettings)
self.label_2.setObjectName("label_2") self.label_4.setObjectName(_fromUtf8("label_4"))
self.formLayout.setWidget(7, QtWidgets.QFormLayout.LabelRole, self.label_2) self.formLayout.setWidget(3, QtGui.QFormLayout.LabelRole, self.label_4)
self.waterfallHistorySizeSpinBox = QtWidgets.QSpinBox(QSpectrumAnalyzerSettings) self.sampleRateSpinBox = QtGui.QSpinBox(QSpectrumAnalyzerSettings)
self.sampleRateSpinBox.setMinimum(0)
self.sampleRateSpinBox.setMaximum(25000000)
self.sampleRateSpinBox.setSingleStep(10000)
self.sampleRateSpinBox.setProperty("value", 2560000)
self.sampleRateSpinBox.setObjectName(_fromUtf8("sampleRateSpinBox"))
self.formLayout.setWidget(3, QtGui.QFormLayout.FieldRole, self.sampleRateSpinBox)
self.label_2 = QtGui.QLabel(QSpectrumAnalyzerSettings)
self.label_2.setObjectName(_fromUtf8("label_2"))
self.formLayout.setWidget(4, QtGui.QFormLayout.LabelRole, self.label_2)
self.waterfallHistorySizeSpinBox = QtGui.QSpinBox(QSpectrumAnalyzerSettings)
self.waterfallHistorySizeSpinBox.setMinimum(1) self.waterfallHistorySizeSpinBox.setMinimum(1)
self.waterfallHistorySizeSpinBox.setMaximum(10000000) self.waterfallHistorySizeSpinBox.setMaximum(10000000)
self.waterfallHistorySizeSpinBox.setProperty("value", 100) self.waterfallHistorySizeSpinBox.setProperty("value", 100)
self.waterfallHistorySizeSpinBox.setObjectName("waterfallHistorySizeSpinBox") self.waterfallHistorySizeSpinBox.setObjectName(_fromUtf8("waterfallHistorySizeSpinBox"))
self.formLayout.setWidget(7, QtWidgets.QFormLayout.FieldRole, self.waterfallHistorySizeSpinBox) self.formLayout.setWidget(4, QtGui.QFormLayout.FieldRole, self.waterfallHistorySizeSpinBox)
self.label_7 = QtWidgets.QLabel(QSpectrumAnalyzerSettings)
self.label_7.setObjectName("label_7")
self.formLayout.setWidget(5, QtWidgets.QFormLayout.LabelRole, self.label_7)
self.label_8 = QtWidgets.QLabel(QSpectrumAnalyzerSettings)
self.label_8.setObjectName("label_8")
self.formLayout.setWidget(6, QtWidgets.QFormLayout.LabelRole, self.label_8)
self.label_6 = QtWidgets.QLabel(QSpectrumAnalyzerSettings)
self.label_6.setObjectName("label_6")
self.formLayout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.label_6)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.paramsEdit = QtWidgets.QLineEdit(QSpectrumAnalyzerSettings)
self.paramsEdit.setObjectName("paramsEdit")
self.horizontalLayout_2.addWidget(self.paramsEdit)
self.paramsHelpButton = QtWidgets.QToolButton(QSpectrumAnalyzerSettings)
self.paramsHelpButton.setMinimumSize(QtCore.QSize(50, 0))
self.paramsHelpButton.setObjectName("paramsHelpButton")
self.horizontalLayout_2.addWidget(self.paramsHelpButton)
self.formLayout.setLayout(2, QtWidgets.QFormLayout.FieldRole, self.horizontalLayout_2)
self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.deviceEdit = QtWidgets.QLineEdit(QSpectrumAnalyzerSettings)
self.deviceEdit.setObjectName("deviceEdit")
self.horizontalLayout_3.addWidget(self.deviceEdit)
self.deviceHelpButton = QtWidgets.QToolButton(QSpectrumAnalyzerSettings)
self.deviceHelpButton.setMinimumSize(QtCore.QSize(50, 0))
self.deviceHelpButton.setObjectName("deviceHelpButton")
self.horizontalLayout_3.addWidget(self.deviceHelpButton)
self.formLayout.setLayout(3, QtWidgets.QFormLayout.FieldRole, self.horizontalLayout_3)
self.sampleRateSpinBox = QtWidgets.QDoubleSpinBox(QSpectrumAnalyzerSettings)
self.sampleRateSpinBox.setProperty("showGroupSeparator", True)
self.sampleRateSpinBox.setDecimals(3)
self.sampleRateSpinBox.setMinimum(0.0)
self.sampleRateSpinBox.setMaximum(999999.99)
self.sampleRateSpinBox.setSingleStep(0.01)
self.sampleRateSpinBox.setProperty("value", 61.44)
self.sampleRateSpinBox.setObjectName("sampleRateSpinBox")
self.formLayout.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.sampleRateSpinBox)
self.bandwidthSpinBox = QtWidgets.QDoubleSpinBox(QSpectrumAnalyzerSettings)
self.bandwidthSpinBox.setProperty("showGroupSeparator", True)
self.bandwidthSpinBox.setDecimals(3)
self.bandwidthSpinBox.setMinimum(0.0)
self.bandwidthSpinBox.setMaximum(999999.99)
self.bandwidthSpinBox.setSingleStep(0.01)
self.bandwidthSpinBox.setProperty("value", 0.0)
self.bandwidthSpinBox.setObjectName("bandwidthSpinBox")
self.formLayout.setWidget(5, QtWidgets.QFormLayout.FieldRole, self.bandwidthSpinBox)
self.lnbSpinBox = QtWidgets.QDoubleSpinBox(QSpectrumAnalyzerSettings)
self.lnbSpinBox.setProperty("showGroupSeparator", True)
self.lnbSpinBox.setDecimals(3)
self.lnbSpinBox.setMinimum(-999999.999)
self.lnbSpinBox.setMaximum(999999.999)
self.lnbSpinBox.setSingleStep(0.01)
self.lnbSpinBox.setProperty("value", 0.0)
self.lnbSpinBox.setObjectName("lnbSpinBox")
self.formLayout.setWidget(6, QtWidgets.QFormLayout.FieldRole, self.lnbSpinBox)
self.verticalLayout.addLayout(self.formLayout) self.verticalLayout.addLayout(self.formLayout)
spacerItem = QtWidgets.QSpacerItem(20, 21, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) spacerItem = QtGui.QSpacerItem(20, 21, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.verticalLayout.addItem(spacerItem) self.verticalLayout.addItem(spacerItem)
self.buttonBox = QtWidgets.QDialogButtonBox(QSpectrumAnalyzerSettings) self.buttonBox = QtGui.QDialogButtonBox(QSpectrumAnalyzerSettings)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal) self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok) self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
self.buttonBox.setObjectName("buttonBox") self.buttonBox.setObjectName(_fromUtf8("buttonBox"))
self.verticalLayout.addWidget(self.buttonBox) self.verticalLayout.addWidget(self.buttonBox)
self.label_3.setBuddy(self.backendComboBox) self.label_3.setBuddy(self.backendComboBox)
self.label.setBuddy(self.executableEdit) self.label.setBuddy(self.executableEdit)
self.label_5.setBuddy(self.deviceEdit) self.label_5.setBuddy(self.deviceEdit)
self.label_4.setBuddy(self.sampleRateSpinBox) self.label_4.setBuddy(self.sampleRateSpinBox)
self.label_2.setBuddy(self.waterfallHistorySizeSpinBox) self.label_2.setBuddy(self.waterfallHistorySizeSpinBox)
self.label_7.setBuddy(self.bandwidthSpinBox)
self.label_8.setBuddy(self.lnbSpinBox)
self.label_6.setBuddy(self.paramsEdit)
self.retranslateUi(QSpectrumAnalyzerSettings) self.retranslateUi(QSpectrumAnalyzerSettings)
self.buttonBox.accepted.connect(QSpectrumAnalyzerSettings.accept) QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), QSpectrumAnalyzerSettings.accept)
self.buttonBox.rejected.connect(QSpectrumAnalyzerSettings.reject) QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), QSpectrumAnalyzerSettings.reject)
QtCore.QMetaObject.connectSlotsByName(QSpectrumAnalyzerSettings) QtCore.QMetaObject.connectSlotsByName(QSpectrumAnalyzerSettings)
QSpectrumAnalyzerSettings.setTabOrder(self.backendComboBox, self.executableEdit) QSpectrumAnalyzerSettings.setTabOrder(self.backendComboBox, self.executableEdit)
QSpectrumAnalyzerSettings.setTabOrder(self.executableEdit, self.executableButton) QSpectrumAnalyzerSettings.setTabOrder(self.executableEdit, self.executableButton)
QSpectrumAnalyzerSettings.setTabOrder(self.executableButton, self.paramsEdit) QSpectrumAnalyzerSettings.setTabOrder(self.executableButton, self.deviceEdit)
QSpectrumAnalyzerSettings.setTabOrder(self.paramsEdit, self.paramsHelpButton) QSpectrumAnalyzerSettings.setTabOrder(self.deviceEdit, self.sampleRateSpinBox)
QSpectrumAnalyzerSettings.setTabOrder(self.paramsHelpButton, self.deviceEdit) QSpectrumAnalyzerSettings.setTabOrder(self.sampleRateSpinBox, self.waterfallHistorySizeSpinBox)
QSpectrumAnalyzerSettings.setTabOrder(self.deviceEdit, self.deviceHelpButton) QSpectrumAnalyzerSettings.setTabOrder(self.waterfallHistorySizeSpinBox, self.buttonBox)
QSpectrumAnalyzerSettings.setTabOrder(self.deviceHelpButton, self.sampleRateSpinBox)
QSpectrumAnalyzerSettings.setTabOrder(self.sampleRateSpinBox, self.bandwidthSpinBox)
QSpectrumAnalyzerSettings.setTabOrder(self.bandwidthSpinBox, self.lnbSpinBox)
QSpectrumAnalyzerSettings.setTabOrder(self.lnbSpinBox, self.waterfallHistorySizeSpinBox)
def retranslateUi(self, QSpectrumAnalyzerSettings): def retranslateUi(self, QSpectrumAnalyzerSettings):
_translate = QtCore.QCoreApplication.translate QSpectrumAnalyzerSettings.setWindowTitle(_translate("QSpectrumAnalyzerSettings", "Settings - QSpectrumAnalyzer", None))
QSpectrumAnalyzerSettings.setWindowTitle(_translate("QSpectrumAnalyzerSettings", "Settings - QSpectrumAnalyzer")) self.label_3.setText(_translate("QSpectrumAnalyzerSettings", "&Backend:", None))
self.label_3.setText(_translate("QSpectrumAnalyzerSettings", "&Backend:")) self.backendComboBox.setItemText(0, _translate("QSpectrumAnalyzerSettings", "soapy_power", None))
self.backendComboBox.setItemText(0, _translate("QSpectrumAnalyzerSettings", "soapy_power")) self.backendComboBox.setItemText(1, _translate("QSpectrumAnalyzerSettings", "rx_power", None))
self.backendComboBox.setItemText(1, _translate("QSpectrumAnalyzerSettings", "rx_power")) self.backendComboBox.setItemText(2, _translate("QSpectrumAnalyzerSettings", "rtl_power_fftw", None))
self.backendComboBox.setItemText(2, _translate("QSpectrumAnalyzerSettings", "rtl_power_fftw")) self.backendComboBox.setItemText(3, _translate("QSpectrumAnalyzerSettings", "rtl_power", None))
self.backendComboBox.setItemText(3, _translate("QSpectrumAnalyzerSettings", "rtl_power")) self.backendComboBox.setItemText(4, _translate("QSpectrumAnalyzerSettings", "hackrf_sweep", None))
self.backendComboBox.setItemText(4, _translate("QSpectrumAnalyzerSettings", "hackrf_sweep")) self.label.setText(_translate("QSpectrumAnalyzerSettings", "E&xecutable:", None))
self.label.setText(_translate("QSpectrumAnalyzerSettings", "E&xecutable:")) self.executableEdit.setText(_translate("QSpectrumAnalyzerSettings", "soapy_power", None))
self.executableEdit.setText(_translate("QSpectrumAnalyzerSettings", "soapy_power")) self.executableButton.setText(_translate("QSpectrumAnalyzerSettings", "...", None))
self.executableButton.setText(_translate("QSpectrumAnalyzerSettings", "...")) self.label_5.setText(_translate("QSpectrumAnalyzerSettings", "Device:", None))
self.label_5.setText(_translate("QSpectrumAnalyzerSettings", "&Device:")) self.label_4.setText(_translate("QSpectrumAnalyzerSettings", "Sa&mple rate:", None))
self.label_4.setText(_translate("QSpectrumAnalyzerSettings", "Sa&mple rate:")) self.label_2.setText(_translate("QSpectrumAnalyzerSettings", "&Waterfall history size:", None))
self.label_2.setText(_translate("QSpectrumAnalyzerSettings", "&Waterfall history size:"))
self.label_7.setText(_translate("QSpectrumAnalyzerSettings", "Bandwidt&h:"))
self.label_8.setToolTip(_translate("QSpectrumAnalyzerSettings", "Negative frequency for upconverters, positive frequency for downconverters."))
self.label_8.setText(_translate("QSpectrumAnalyzerSettings", "&LNB LO:"))
self.label_6.setText(_translate("QSpectrumAnalyzerSettings", "Add&itional parameters:"))
self.paramsHelpButton.setText(_translate("QSpectrumAnalyzerSettings", " ? "))
self.deviceHelpButton.setText(_translate("QSpectrumAnalyzerSettings", " ? "))
self.sampleRateSpinBox.setSuffix(_translate("QSpectrumAnalyzerSettings", " MHz"))
self.bandwidthSpinBox.setSuffix(_translate("QSpectrumAnalyzerSettings", " MHz"))
self.lnbSpinBox.setToolTip(_translate("QSpectrumAnalyzerSettings", "Negative frequency for upconverters, positive frequency for downconverters."))
self.lnbSpinBox.setSuffix(_translate("QSpectrumAnalyzerSettings", " MHz"))

View File

@ -1,37 +0,0 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'qspectrumanalyzer/qspectrumanalyzer_settings_help.ui'
#
# Created by: PyQt5 UI code generator 5.8
#
# WARNING! All changes made in this file will be lost!
from Qt import QtCore, QtGui, QtWidgets
class Ui_QSpectrumAnalyzerSettingsHelp(object):
def setupUi(self, QSpectrumAnalyzerSettingsHelp):
QSpectrumAnalyzerSettingsHelp.setObjectName("QSpectrumAnalyzerSettingsHelp")
QSpectrumAnalyzerSettingsHelp.resize(1200, 700)
self.verticalLayout = QtWidgets.QVBoxLayout(QSpectrumAnalyzerSettingsHelp)
self.verticalLayout.setObjectName("verticalLayout")
self.helpTextEdit = QtWidgets.QPlainTextEdit(QSpectrumAnalyzerSettingsHelp)
self.helpTextEdit.setUndoRedoEnabled(False)
self.helpTextEdit.setTextInteractionFlags(QtCore.Qt.TextSelectableByKeyboard|QtCore.Qt.TextSelectableByMouse)
self.helpTextEdit.setObjectName("helpTextEdit")
self.verticalLayout.addWidget(self.helpTextEdit)
self.buttonBox = QtWidgets.QDialogButtonBox(QSpectrumAnalyzerSettingsHelp)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Close)
self.buttonBox.setObjectName("buttonBox")
self.verticalLayout.addWidget(self.buttonBox)
self.retranslateUi(QSpectrumAnalyzerSettingsHelp)
self.buttonBox.accepted.connect(QSpectrumAnalyzerSettingsHelp.accept)
self.buttonBox.rejected.connect(QSpectrumAnalyzerSettingsHelp.reject)
QtCore.QMetaObject.connectSlotsByName(QSpectrumAnalyzerSettingsHelp)
QSpectrumAnalyzerSettingsHelp.setTabOrder(self.helpTextEdit, self.buttonBox)
def retranslateUi(self, QSpectrumAnalyzerSettingsHelp):
_translate = QtCore.QCoreApplication.translate
QSpectrumAnalyzerSettingsHelp.setWindowTitle(_translate("QSpectrumAnalyzerSettingsHelp", "Help - QSpectrumAnalyzer"))

View File

@ -0,0 +1,81 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'qspectrumanalyzer/qspectrumanalyzer_smooth.ui'
#
# Created by: PyQt4 UI code generator 4.12
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_QSpectrumAnalyzerSmooth(object):
def setupUi(self, QSpectrumAnalyzerSmooth):
QSpectrumAnalyzerSmooth.setObjectName(_fromUtf8("QSpectrumAnalyzerSmooth"))
QSpectrumAnalyzerSmooth.resize(250, 130)
self.verticalLayout = QtGui.QVBoxLayout(QSpectrumAnalyzerSmooth)
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
self.formLayout = QtGui.QFormLayout()
self.formLayout.setObjectName(_fromUtf8("formLayout"))
self.label = QtGui.QLabel(QSpectrumAnalyzerSmooth)
self.label.setObjectName(_fromUtf8("label"))
self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.label)
self.windowFunctionComboBox = QtGui.QComboBox(QSpectrumAnalyzerSmooth)
self.windowFunctionComboBox.setObjectName(_fromUtf8("windowFunctionComboBox"))
self.windowFunctionComboBox.addItem(_fromUtf8(""))
self.windowFunctionComboBox.addItem(_fromUtf8(""))
self.windowFunctionComboBox.addItem(_fromUtf8(""))
self.windowFunctionComboBox.addItem(_fromUtf8(""))
self.windowFunctionComboBox.addItem(_fromUtf8(""))
self.formLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.windowFunctionComboBox)
self.label_2 = QtGui.QLabel(QSpectrumAnalyzerSmooth)
self.label_2.setObjectName(_fromUtf8("label_2"))
self.formLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.label_2)
self.windowLengthSpinBox = QtGui.QSpinBox(QSpectrumAnalyzerSmooth)
self.windowLengthSpinBox.setMinimum(3)
self.windowLengthSpinBox.setMaximum(1001)
self.windowLengthSpinBox.setProperty("value", 11)
self.windowLengthSpinBox.setObjectName(_fromUtf8("windowLengthSpinBox"))
self.formLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.windowLengthSpinBox)
self.verticalLayout.addLayout(self.formLayout)
spacerItem = QtGui.QSpacerItem(20, 1, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.verticalLayout.addItem(spacerItem)
self.buttonBox = QtGui.QDialogButtonBox(QSpectrumAnalyzerSmooth)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
self.buttonBox.setObjectName(_fromUtf8("buttonBox"))
self.verticalLayout.addWidget(self.buttonBox)
self.label.setBuddy(self.windowFunctionComboBox)
self.label_2.setBuddy(self.windowLengthSpinBox)
self.retranslateUi(QSpectrumAnalyzerSmooth)
self.windowFunctionComboBox.setCurrentIndex(1)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), QSpectrumAnalyzerSmooth.accept)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), QSpectrumAnalyzerSmooth.reject)
QtCore.QMetaObject.connectSlotsByName(QSpectrumAnalyzerSmooth)
QSpectrumAnalyzerSmooth.setTabOrder(self.windowFunctionComboBox, self.windowLengthSpinBox)
QSpectrumAnalyzerSmooth.setTabOrder(self.windowLengthSpinBox, self.buttonBox)
def retranslateUi(self, QSpectrumAnalyzerSmooth):
QSpectrumAnalyzerSmooth.setWindowTitle(_translate("QSpectrumAnalyzerSmooth", "Smoothing - QSpectrumAnalyzer", None))
self.label.setText(_translate("QSpectrumAnalyzerSmooth", "&Window function:", None))
self.windowFunctionComboBox.setItemText(0, _translate("QSpectrumAnalyzerSmooth", "rectangular", None))
self.windowFunctionComboBox.setItemText(1, _translate("QSpectrumAnalyzerSmooth", "hanning", None))
self.windowFunctionComboBox.setItemText(2, _translate("QSpectrumAnalyzerSmooth", "hamming", None))
self.windowFunctionComboBox.setItemText(3, _translate("QSpectrumAnalyzerSmooth", "bartlett", None))
self.windowFunctionComboBox.setItemText(4, _translate("QSpectrumAnalyzerSmooth", "blackman", None))
self.label_2.setText(_translate("QSpectrumAnalyzerSmooth", "Window len&gth:", None))

View File

@ -1,68 +0,0 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'qspectrumanalyzer/qspectrumanalyzer_smoothing.ui'
#
# Created by: PyQt5 UI code generator 5.8
#
# WARNING! All changes made in this file will be lost!
from Qt import QtCore, QtGui, QtWidgets
class Ui_QSpectrumAnalyzerSmoothing(object):
def setupUi(self, QSpectrumAnalyzerSmoothing):
QSpectrumAnalyzerSmoothing.setObjectName("QSpectrumAnalyzerSmoothing")
QSpectrumAnalyzerSmoothing.resize(250, 130)
self.verticalLayout = QtWidgets.QVBoxLayout(QSpectrumAnalyzerSmoothing)
self.verticalLayout.setObjectName("verticalLayout")
self.formLayout = QtWidgets.QFormLayout()
self.formLayout.setObjectName("formLayout")
self.label = QtWidgets.QLabel(QSpectrumAnalyzerSmoothing)
self.label.setObjectName("label")
self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.label)
self.windowFunctionComboBox = QtWidgets.QComboBox(QSpectrumAnalyzerSmoothing)
self.windowFunctionComboBox.setObjectName("windowFunctionComboBox")
self.windowFunctionComboBox.addItem("")
self.windowFunctionComboBox.addItem("")
self.windowFunctionComboBox.addItem("")
self.windowFunctionComboBox.addItem("")
self.windowFunctionComboBox.addItem("")
self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.windowFunctionComboBox)
self.label_2 = QtWidgets.QLabel(QSpectrumAnalyzerSmoothing)
self.label_2.setObjectName("label_2")
self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label_2)
self.windowLengthSpinBox = QtWidgets.QSpinBox(QSpectrumAnalyzerSmoothing)
self.windowLengthSpinBox.setMinimum(3)
self.windowLengthSpinBox.setMaximum(1001)
self.windowLengthSpinBox.setProperty("value", 11)
self.windowLengthSpinBox.setObjectName("windowLengthSpinBox")
self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.windowLengthSpinBox)
self.verticalLayout.addLayout(self.formLayout)
spacerItem = QtWidgets.QSpacerItem(20, 1, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.verticalLayout.addItem(spacerItem)
self.buttonBox = QtWidgets.QDialogButtonBox(QSpectrumAnalyzerSmoothing)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
self.buttonBox.setObjectName("buttonBox")
self.verticalLayout.addWidget(self.buttonBox)
self.label.setBuddy(self.windowFunctionComboBox)
self.label_2.setBuddy(self.windowLengthSpinBox)
self.retranslateUi(QSpectrumAnalyzerSmoothing)
self.windowFunctionComboBox.setCurrentIndex(1)
self.buttonBox.accepted.connect(QSpectrumAnalyzerSmoothing.accept)
self.buttonBox.rejected.connect(QSpectrumAnalyzerSmoothing.reject)
QtCore.QMetaObject.connectSlotsByName(QSpectrumAnalyzerSmoothing)
QSpectrumAnalyzerSmoothing.setTabOrder(self.windowFunctionComboBox, self.windowLengthSpinBox)
QSpectrumAnalyzerSmoothing.setTabOrder(self.windowLengthSpinBox, self.buttonBox)
def retranslateUi(self, QSpectrumAnalyzerSmoothing):
_translate = QtCore.QCoreApplication.translate
QSpectrumAnalyzerSmoothing.setWindowTitle(_translate("QSpectrumAnalyzerSmoothing", "Smoothing - QSpectrumAnalyzer"))
self.label.setText(_translate("QSpectrumAnalyzerSmoothing", "&Window function:"))
self.windowFunctionComboBox.setItemText(0, _translate("QSpectrumAnalyzerSmoothing", "rectangular"))
self.windowFunctionComboBox.setItemText(1, _translate("QSpectrumAnalyzerSmoothing", "hanning"))
self.windowFunctionComboBox.setItemText(2, _translate("QSpectrumAnalyzerSmoothing", "hamming"))
self.windowFunctionComboBox.setItemText(3, _translate("QSpectrumAnalyzerSmoothing", "bartlett"))
self.windowFunctionComboBox.setItemText(4, _translate("QSpectrumAnalyzerSmoothing", "blackman"))
self.label_2.setText(_translate("QSpectrumAnalyzerSmoothing", "Window len&gth:"))

View File

@ -1,6 +1,6 @@
import numpy as np import numpy as np
from Qt import QtGui from PyQt4 import QtGui
def smooth(x, window_len=11, window='hanning'): def smooth(x, window_len=11, window='hanning'):
@ -35,19 +35,3 @@ def str_to_color(color_string):
def color_to_str(color): def color_to_str(color):
"""Create comma separated RGBA string from QColor""" """Create comma separated RGBA string from QColor"""
return ", ".join([str(color.red()), str(color.green()), str(color.blue()), str(color.alpha())]) return ", ".join([str(color.red()), str(color.green()), str(color.blue()), str(color.alpha())])
def human_time(seconds):
"""Format time in seconds to human readable form (e.g. 1 h 2 min 3 s)"""
seconds = int(seconds)
m, s = divmod(seconds, 60)
h, m = divmod(m, 60)
if h > 0:
timestr = '{:.0f} h {:.0f} min {:.0f} s'.format(h, m, s)
elif m > 0:
timestr = '{:.0f} min {:.0f} s'.format(m, s)
else:
timestr = '{:.0f} s'.format(s)
return timestr

View File

@ -1 +1 @@
__version__ = "2.2.0" __version__ = "1.4.0"

View File

@ -1,51 +0,0 @@
# -*- coding: utf-8 -*-
#
# Copyright © Spyder Project Contributors
# Licensed under the terms of the MIT License
# (see spyder/__init__.py for details)
"""Windows-specific utilities"""
from ctypes import windll
# --- Window control ---
SW_SHOW = 5 # activate and display
SW_SHOWNA = 8 # show without activation
SW_HIDE = 0
GetConsoleWindow = windll.kernel32.GetConsoleWindow
ShowWindow = windll.user32.ShowWindow
IsWindowVisible = windll.user32.IsWindowVisible
# Handle to console window associated with current Python
# interpreter procss, 0 if there is no window
console_window_handle = GetConsoleWindow()
def set_attached_console_visible(state):
"""Show/hide system console window attached to current process.
Return it's previous state.
Availability: Windows"""
flag = {True: SW_SHOW, False: SW_HIDE}
return bool(ShowWindow(console_window_handle, flag[state]))
def is_attached_console_visible():
"""Return True if attached console window is visible"""
return IsWindowVisible(console_window_handle)
def set_windows_appusermodelid():
"""Make sure correct icon is used on Windows 7 taskbar"""
try:
return windll.shell32.SetCurrentProcessExplicitAppUserModelID("spyder.Spyder")
except AttributeError:
return "SetCurrentProcessExplicitAppUserModelID not found"
# [ ] the console state asks for a storage container
# [ ] reopen console on exit - better die open than become a zombie

26
setup-qt.py Executable file
View File

@ -0,0 +1,26 @@
#!/usr/bin/env python
import os, shutil
from glob import glob
package = "qspectrumanalyzer"
languages = ["cs"]
print("Rebuilding PyQt resource files...")
for f in glob("{}/*.qrc".format(package)):
os.system("pyrcc4 -o {}/qrc_{}.py {}".format(package, os.path.basename(f[:-4]), f))
print("Rebuilding PyQt UI files...")
for f in glob("{}/*.ui".format(package)):
os.system("pyuic4 -o {}/ui_{}.py {}".format(package, os.path.basename(f[:-3]), f))
print("Updating translations...")
lang_files = " ".join("{}/languages/{}_{}.ts".format(package, package, lang) for lang in languages)
os.system("pylupdate4 {}/*.py -ts {}".format(package, lang_files))
os.system("lrelease {}/languages/*.ts".format(package))
print("Regenerating .pyc files...")
shutil.rmtree("{}/__pycache__".format(package), ignore_errors=True)
for f in glob("{}/*.pyc".format(package)):
os.remove(f)
__import__("{}.__main__".format(package))

View File

@ -1,90 +1,36 @@
#!/usr/bin/env python #!/usr/bin/env python
import setuptools
from setuptools import setup from setuptools import setup
from qspectrumanalyzer.version import __version__ from qspectrumanalyzer.version import __version__
setup_cmdclass = {}
setup_entry_points = {
"gui_scripts": [
"qspectrumanalyzer=qspectrumanalyzer.__main__:main",
],
}
# Allow compilation of Qt .qrc, .ui and .ts files (build_qt command)
try:
from setup_qt import build_qt
setup_cmdclass['build_qt'] = build_qt
except ImportError:
pass
# Allow building frozen executables with PyInstaller / subzero (build_exe command)
try:
from subzero import setup, Executable
setup_entry_points = {
"console_scripts": [
Executable('qspectrumanalyzer=qspectrumanalyzer.__main__:main',
console=True, icon_file='qspectrumanalyzer.ico'),
Executable('soapy_power=soapypower.__main__:main',
console=True),
],
}
except ImportError:
pass
setup( setup(
name="QSpectrumAnalyzer", name="QSpectrumAnalyzer",
version=__version__, version=__version__,
description=("Spectrum analyzer for multiple SDR platforms " description="Spectrum analyzer for RTL-SDR (GUI for rtl_power based on PyQtGraph)",
"(PyQtGraph based GUI for soapy_power, hackrf_sweep, rtl_power, rx_power and other backends)"),
long_description=open('README.rst').read(),
author="Michal Krenek (Mikos)", author="Michal Krenek (Mikos)",
author_email="m.krenek@gmail.com", author_email="m.krenek@gmail.com",
url="https://github.com/xmikos/qspectrumanalyzer", url="https://github.com/xmikos/qspectrumanalyzer",
license="GNU GPLv3", license="GNU GPLv3",
packages=["qspectrumanalyzer", "qspectrumanalyzer.backends"], packages=["qspectrumanalyzer"],
package_data={ package_data={
"qspectrumanalyzer": [ "qspectrumanalyzer": [
"qspectrumanalyzer.svg",
"*.ui", "*.ui",
"languages/*.qm", "languages/*.qm",
"languages/*.ts", "languages/*.ts"
], ]
}, },
data_files=[ data_files=[
("share/applications", ["qspectrumanalyzer.desktop"]), ("share/applications", ["qspectrumanalyzer.desktop"]),
("share/pixmaps", ["qspectrumanalyzer.png"]), ("share/pixmaps", ["qspectrumanalyzer.png"])
], ],
install_requires=[ entry_points={
"soapy_power>=1.6.0", "gui_scripts": [
"pyqtgraph>=0.10.0", "qspectrumanalyzer=qspectrumanalyzer.__main__:main"
"Qt.py", ],
],
options={
'build_qt': {
'packages': ['qspectrumanalyzer'],
'languages': ['cs'],
'replacement_bindings': 'Qt',
},
'build_exe': {
'datas': [
('qspectrumanalyzer/qspectrumanalyzer.svg', 'qspectrumanalyzer'),
('qspectrumanalyzer/*.ui', 'qspectrumanalyzer'),
('qspectrumanalyzer/languages/*.ts', 'qspectrumanalyzer/languages'),
('qspectrumanalyzer/languages/*.qm', 'qspectrumanalyzer/languages'),
('README.rst', '.'),
('LICENSE', '.'),
],
},
'bdist_msi': {
'upgrade_code': '30740ef4-84e7-4e67-8e4a-12b53492c387',
'shortcuts': [
'QSpectrumAnalyzer=qspectrumanalyzer',
],
},
}, },
install_requires=[
"pyqtgraph"
],
classifiers=[ classifiers=[
"Development Status :: 4 - Beta", "Development Status :: 4 - Beta",
"Environment :: MacOS X", "Environment :: MacOS X",
@ -98,8 +44,6 @@ setup(
"Operating System :: OS Independent", "Operating System :: OS Independent",
"Programming Language :: Python :: 3", "Programming Language :: Python :: 3",
"Topic :: Communications :: Ham Radio", "Topic :: Communications :: Ham Radio",
"Topic :: Scientific/Engineering :: Visualization", "Topic :: Scientific/Engineering :: Visualization"
], ]
entry_points=setup_entry_points,
cmdclass=setup_cmdclass,
) )