Compare commits
No commits in common. "master" and "hackrf_sweep" have entirely different histories.
master
...
hackrf_swe
@ -2,3 +2,4 @@ include LICENSE
|
||||
include README.rst
|
||||
include qspectrumanalyzer.desktop
|
||||
include qspectrumanalyzer.png
|
||||
include qspectrumanalyzer.svg
|
||||
|
14
PKGBUILD
14
PKGBUILD
@ -1,20 +1,14 @@
|
||||
# Maintainer: Michal Krenek (Mikos) <m.krenek@gmail.com>
|
||||
pkgname=qspectrumanalyzer
|
||||
pkgver=2.2.0
|
||||
pkgver=1.4.0
|
||||
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')
|
||||
url="https://github.com/xmikos/qspectrumanalyzer"
|
||||
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')
|
||||
optdepends=(
|
||||
'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)'
|
||||
)
|
||||
optdepends=('rtl_power_fftw-git: alternative rtl_power implementation using FFTW library')
|
||||
source=(https://github.com/xmikos/qspectrumanalyzer/archive/v$pkgver.tar.gz)
|
||||
|
||||
build() {
|
||||
|
155
README.rst
155
README.rst
@ -1,8 +1,7 @@
|
||||
QSpectrumAnalyzer
|
||||
=================
|
||||
|
||||
Spectrum analyzer for multiple SDR platforms (PyQtGraph based GUI for soapy_power,
|
||||
hackrf_sweep, rtl_power, rx_power and other backends)
|
||||
Spectrum analyzer for RTL-SDR (GUI for rtl_power based on PyQtGraph)
|
||||
|
||||
Screenshots
|
||||
-----------
|
||||
@ -15,73 +14,37 @@ Requirements
|
||||
------------
|
||||
|
||||
- Python >= 3.3
|
||||
- PyQt4 / PyQt5 / PySide / PySide2
|
||||
- Qt.py (https://github.com/mottosso/Qt.py)
|
||||
- PyQt >= 4.5
|
||||
- PyQtGraph (http://www.pyqtgraph.org)
|
||||
- soapy_power (https://github.com/xmikos/soapy_power)
|
||||
- Optional: hackrf / rtl-sdr / rtl_power_fftw / rx_tools
|
||||
- rtl-sdr (https://github.com/keenerd/rtl-sdr)
|
||||
- Optional: rtl_power_fftw (https://github.com/AD-Vega/rtl-power-fftw)
|
||||
|
||||
Backends
|
||||
--------
|
||||
|
||||
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)
|
||||
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)
|
||||
is broken (especially when used with cropping).
|
||||
|
||||
- **rx_power** (https://github.com/rxseger/rx_tools) *[unsupported]*
|
||||
|
||||
``rx_power`` (part of ``rx_tools``) is also based on SoapySDR (like default ``soapy_power`` backend)
|
||||
and therefore supports nearly all SDR platforms. But it is much slower than soapy_power, doesn't support
|
||||
near real-time continuous measurement (minimum interval is 1 second, same as ``rtl_power``)
|
||||
and is buggy. Backend is currently unsupported, if you want to fix it, patches are welcome.
|
||||
Another alternative is
|
||||
`rtl_power_fftw <https://github.com/AD-Vega/rtl-power-fftw>`_ which has various
|
||||
benefits over ``rtl_power``. E.g. better FFT performance (thanks to
|
||||
use of ``fftw`` library) and possibility to use much shorter acquisition time
|
||||
for more real-time continuous measurement (minimum interval in original
|
||||
``rtl_power`` is 1 second, but in ``rtl_power_fftw`` you are only limited
|
||||
by number of frequency hops).
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Start QSpectrumAnalyzer by running ``qspectrumanalyzer``.
|
||||
|
||||
You can choose which backend you want to use in *File* -> *Settings*
|
||||
(or *Application menu* -> *Preferences* on Mac OS X), default is
|
||||
``soapy_power``. Device, sample rate, bandwidth, LNB LO, path to backend executable
|
||||
and additional backend parameters can be also manually specified there. You can
|
||||
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 don't make this number too big.
|
||||
You can choose if you want to use ``rtl_power`` or ``rtl_power_fftw`` backend in
|
||||
*File* -> *Settings* (default is ``rtl_power``). Path to ``rtl_power``
|
||||
(or ``rtl_power_fftw``) executable can be also manually specified there. You can also
|
||||
set waterfall plot history size in there. Default is 100 lines, be aware that
|
||||
really large sweeps (with a lot of bins) would require a lot of system memory, so
|
||||
don't make this number too big.
|
||||
|
||||
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
|
||||
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
|
||||
------------
|
||||
|
||||
Arch Linux:
|
||||
***********
|
||||
|
||||
Stable version:
|
||||
**Arch Linux:**
|
||||
::
|
||||
|
||||
git clone https://aur.archlinux.org/qspectrumanalyzer.git
|
||||
cd qspectrumanalyzer
|
||||
makepkg -sri
|
||||
|
||||
Git master branch:
|
||||
::
|
||||
|
||||
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:
|
||||
Or simply use `pacaur <https://aur.archlinux.org/packages/pacaur>`_ (or any other AUR helper):
|
||||
::
|
||||
|
||||
pacaur -S qspectrumanalyzer
|
||||
pacaur -S qspectrumanalyzer-git
|
||||
|
||||
Ubuntu:
|
||||
*******
|
||||
**Debian / Ubuntu:**
|
||||
::
|
||||
|
||||
# Add SoapySDR PPA to your system
|
||||
sudo add-apt-repository -y ppa:myriadrf/drivers
|
||||
sudo apt-get install python3-pip python3-pyqt4 python3-numpy
|
||||
sudo pip3 install qspectrumanalyzer
|
||||
|
||||
# Update list of packages
|
||||
sudo apt-get update
|
||||
Warning! ``pip`` will install packages system-wide by default, but you
|
||||
should always use your distribution package manager for this.
|
||||
|
||||
# Install basic dependencies
|
||||
sudo apt-get install python3-pip python3-pyqt5 python3-numpy python3-scipy soapysdr python3-soapysdr
|
||||
You can install it locally only for your current user by running this (without ``sudo``):
|
||||
::
|
||||
|
||||
# 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
|
||||
|
||||
``qspectrumanalyzer`` and ``soapy_power`` executables will be then placed in
|
||||
``~/.local/bin`` directory, you can add it to your 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).
|
||||
Executables will be then placed in ``~/.local/bin`` directory, you can add it to your
|
||||
PATH in ``~/.bashrc``.
|
||||
|
||||
Todo:
|
||||
-----
|
||||
|
||||
- save FFT history (allow big waterfall plot saved to file)
|
||||
- automatic peak detection / highlighting
|
||||
- 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.)
|
||||
|
@ -1,7 +1,7 @@
|
||||
[Desktop Entry]
|
||||
Name=QSpectrumAnalyzer
|
||||
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
|
||||
Icon=qspectrumanalyzer
|
||||
StartupNotify=true
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 15 KiB |
453
qspectrumanalyzer/__main__.py
Normal file → Executable file
453
qspectrumanalyzer/__main__.py
Normal file → Executable file
@ -1,46 +1,166 @@
|
||||
#!/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.backend import RtlPowerThread, RtlPowerFftwThread, SoapyPowerThread, RxPowerThread, HackRFSweepThread
|
||||
from qspectrumanalyzer.data import DataStorage
|
||||
from qspectrumanalyzer.plot import SpectrumPlotWidget, WaterfallPlotWidget
|
||||
from qspectrumanalyzer.utils import str_to_color, human_time
|
||||
|
||||
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.utils import color_to_str, str_to_color
|
||||
|
||||
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
|
||||
|
||||
debug = False
|
||||
|
||||
# Allow CTRL+C and/or SIGTERM to kill us (PyQt blocks it otherwise)
|
||||
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
||||
signal.signal(signal.SIGTERM, signal.SIG_DFL)
|
||||
|
||||
|
||||
class QSpectrumAnalyzerMainWindow(QtWidgets.QMainWindow, Ui_QSpectrumAnalyzerMainWindow):
|
||||
"""QSpectrumAnalyzer main window"""
|
||||
class QSpectrumAnalyzerSettings(QtGui.QDialog, Ui_QSpectrumAnalyzerSettings):
|
||||
"""QSpectrumAnalyzer settings dialog"""
|
||||
def __init__(self, parent=None):
|
||||
# Initialize UI
|
||||
super().__init__(parent)
|
||||
self.setupUi(self)
|
||||
|
||||
# Set window icon
|
||||
icon_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "qspectrumanalyzer.svg")
|
||||
self.setWindowIcon(QtGui.QIcon(icon_path))
|
||||
# Load settings
|
||||
settings = QtCore.QSettings()
|
||||
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
|
||||
self.progressbar = QtWidgets.QProgressBar()
|
||||
self.progressbar.setMaximumWidth(250)
|
||||
self.progressbar.setVisible(False)
|
||||
self.statusbar.addPermanentWidget(self.progressbar)
|
||||
backend = settings.value("backend", "soapy_power")
|
||||
self.backendComboBox.blockSignals(True)
|
||||
i = self.backendComboBox.findText(backend)
|
||||
if i == -1:
|
||||
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
|
||||
self.spectrumPlotWidget = SpectrumPlotWidget(self.mainPlotLayout)
|
||||
@ -50,14 +170,9 @@ class QSpectrumAnalyzerMainWindow(QtWidgets.QMainWindow, Ui_QSpectrumAnalyzerMai
|
||||
self.spectrumPlotWidget.plot.setXLink(self.waterfallPlotWidget.plot)
|
||||
|
||||
# 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.start_timestamp = None
|
||||
self.data_storage = None
|
||||
self.power_thread = None
|
||||
self.backend = None
|
||||
self.setup_power_thread()
|
||||
|
||||
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_persistence)
|
||||
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.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_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")
|
||||
try:
|
||||
backend_module = getattr(backends, backend)
|
||||
except AttributeError:
|
||||
backend_module = backends.soapy_power
|
||||
if backend == "soapy_power":
|
||||
self.power_thread = SoapyPowerThread(self.data_storage)
|
||||
elif backend == "rx_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.backend = backend
|
||||
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)
|
||||
self.power_thread.powerThreadStarted.connect(self.update_buttons)
|
||||
self.power_thread.powerThreadStopped.connect(self.update_buttons)
|
||||
|
||||
def set_dock_size(self, dock, width, height):
|
||||
"""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.binSizeSpinBox.setValue(settings.value("bin_size", 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.cropSpinBox.setValue(settings.value("crop", 0, 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.smoothCheckBox.setChecked(settings.value("smooth", 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
|
||||
if settings.value("window_state"):
|
||||
@ -219,8 +311,6 @@ class QSpectrumAnalyzerMainWindow(QtWidgets.QMainWindow, Ui_QSpectrumAnalyzerMai
|
||||
settings.setValue("average", int(self.averageCheckBox.isChecked()))
|
||||
settings.setValue("smooth", int(self.smoothCheckBox.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
|
||||
settings.setValue("window_geometry", self.saveGeometry())
|
||||
@ -239,72 +329,32 @@ class QSpectrumAnalyzerMainWindow(QtWidgets.QMainWindow, Ui_QSpectrumAnalyzerMai
|
||||
|
||||
def update_data(self, data_storage):
|
||||
"""Update GUI when new data is received"""
|
||||
# Show number of hops and how much time did the sweep really take
|
||||
timestamp = time.time()
|
||||
self.prev_sweep_time = timestamp - self.prev_data_timestamp
|
||||
sweep_time = timestamp - self.prev_data_timestamp
|
||||
self.prev_data_timestamp = timestamp
|
||||
self.update_status()
|
||||
|
||||
def update_status(self):
|
||||
"""Update status bar"""
|
||||
timestamp = time.time()
|
||||
status = []
|
||||
|
||||
if self.power_thread.params["hops"]:
|
||||
status.append(self.tr("Frequency hops: {}").format(self.power_thread.params["hops"]))
|
||||
|
||||
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)
|
||||
self.show_status(
|
||||
self.tr("Frequency hops: {} | Sweep time: {:.2f} s | FPS: {:.2f}").format(
|
||||
self.power_thread.params["hops"] or self.tr("N/A"),
|
||||
sweep_time,
|
||||
1 / sweep_time
|
||||
),
|
||||
timeout=0
|
||||
)
|
||||
|
||||
def start(self, single_shot=False):
|
||||
"""Start power thread"""
|
||||
settings = QtCore.QSettings()
|
||||
|
||||
self.prev_sweep_time = 0
|
||||
self.prev_data_timestamp = time.time()
|
||||
self.start_timestamp = self.prev_data_timestamp
|
||||
|
||||
if self.intervalSpinBox.value() >= 1:
|
||||
self.progressbar.setRange(0, self.intervalSpinBox.value() * 1000)
|
||||
else:
|
||||
self.progressbar.setRange(0, 0)
|
||||
self.update_progress(0)
|
||||
self.update_status_timer.start(100)
|
||||
self.data_storage.reset()
|
||||
self.data_storage.set_smooth(
|
||||
bool(self.smoothCheckBox.isChecked()),
|
||||
settings.value("smooth_length", 11, int),
|
||||
settings.value("smooth_window", "hanning"),
|
||||
recalculate=False
|
||||
)
|
||||
|
||||
self.waterfallPlotWidget.history_size = settings.value("waterfall_history_size", 100, int)
|
||||
self.waterfallPlotWidget.clear_plot()
|
||||
@ -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.average = bool(self.averageCheckBox.isChecked())
|
||||
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_length = settings.value("persistence_length", 5, int)
|
||||
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_min()
|
||||
self.spectrumPlotWidget.clear_average()
|
||||
self.spectrumPlotWidget.clear_baseline()
|
||||
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:
|
||||
self.power_thread.setup(
|
||||
float(self.startFreqSpinBox.value()),
|
||||
self.power_thread.setup(float(self.startFreqSpinBox.value()),
|
||||
float(self.stopFreqSpinBox.value()),
|
||||
float(self.binSizeSpinBox.value()),
|
||||
interval=float(self.intervalSpinBox.value()),
|
||||
gain=float(self.gainSpinBox.value()),
|
||||
gain=int(self.gainSpinBox.value()),
|
||||
ppm=int(self.ppmSpinBox.value()),
|
||||
crop=int(self.cropSpinBox.value()) / 100.0,
|
||||
single_shot=single_shot,
|
||||
device=settings.value("device", ""),
|
||||
sample_rate=settings.value("sample_rate", 2560000, float),
|
||||
bandwidth=settings.value("bandwidth", 0, float),
|
||||
lnb_lo=settings.value("lnb_lo", 0, float)
|
||||
)
|
||||
sample_rate=settings.value("sample_rate", 2560000, int))
|
||||
self.power_thread.start()
|
||||
|
||||
def stop(self):
|
||||
@ -363,47 +395,47 @@ class QSpectrumAnalyzerMainWindow(QtWidgets.QMainWindow, Ui_QSpectrumAnalyzerMai
|
||||
if self.power_thread.alive:
|
||||
self.power_thread.stop()
|
||||
|
||||
@QtCore.Slot()
|
||||
@QtCore.pyqtSlot()
|
||||
def on_startButton_clicked(self):
|
||||
self.start()
|
||||
|
||||
@QtCore.Slot()
|
||||
@QtCore.pyqtSlot()
|
||||
def on_singleShotButton_clicked(self):
|
||||
self.start(single_shot=True)
|
||||
|
||||
@QtCore.Slot()
|
||||
@QtCore.pyqtSlot()
|
||||
def on_stopButton_clicked(self):
|
||||
self.stop()
|
||||
|
||||
@QtCore.Slot(bool)
|
||||
@QtCore.pyqtSlot(bool)
|
||||
def on_mainCurveCheckBox_toggled(self, checked):
|
||||
self.spectrumPlotWidget.main_curve = checked
|
||||
if self.spectrumPlotWidget.curve.xData is None:
|
||||
self.spectrumPlotWidget.update_plot(self.data_storage)
|
||||
self.spectrumPlotWidget.curve.setVisible(checked)
|
||||
|
||||
@QtCore.Slot(bool)
|
||||
@QtCore.pyqtSlot(bool)
|
||||
def on_peakHoldMaxCheckBox_toggled(self, checked):
|
||||
self.spectrumPlotWidget.peak_hold_max = checked
|
||||
if self.spectrumPlotWidget.curve_peak_hold_max.xData is None:
|
||||
self.spectrumPlotWidget.update_peak_hold_max(self.data_storage)
|
||||
self.spectrumPlotWidget.curve_peak_hold_max.setVisible(checked)
|
||||
|
||||
@QtCore.Slot(bool)
|
||||
@QtCore.pyqtSlot(bool)
|
||||
def on_peakHoldMinCheckBox_toggled(self, checked):
|
||||
self.spectrumPlotWidget.peak_hold_min = checked
|
||||
if self.spectrumPlotWidget.curve_peak_hold_min.xData is None:
|
||||
self.spectrumPlotWidget.update_peak_hold_min(self.data_storage)
|
||||
self.spectrumPlotWidget.curve_peak_hold_min.setVisible(checked)
|
||||
|
||||
@QtCore.Slot(bool)
|
||||
@QtCore.pyqtSlot(bool)
|
||||
def on_averageCheckBox_toggled(self, checked):
|
||||
self.spectrumPlotWidget.average = checked
|
||||
if self.spectrumPlotWidget.curve_average.xData is None:
|
||||
self.spectrumPlotWidget.update_average(self.data_storage)
|
||||
self.spectrumPlotWidget.curve_average.setVisible(checked)
|
||||
|
||||
@QtCore.Slot(bool)
|
||||
@QtCore.pyqtSlot(bool)
|
||||
def on_persistenceCheckBox_toggled(self, checked):
|
||||
self.spectrumPlotWidget.persistence = checked
|
||||
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:
|
||||
curve.setVisible(checked)
|
||||
|
||||
@QtCore.Slot(bool)
|
||||
@QtCore.pyqtSlot(bool)
|
||||
def on_smoothCheckBox_toggled(self, checked):
|
||||
settings = QtCore.QSettings()
|
||||
self.data_storage.set_smooth(
|
||||
checked,
|
||||
settings.value("smooth_length", 11, int),
|
||||
settings.value("smooth_window", "hanning")
|
||||
settings.value("smooth_window", "hanning"),
|
||||
recalculate=True
|
||||
)
|
||||
|
||||
@QtCore.Slot(bool)
|
||||
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()
|
||||
@QtCore.pyqtSlot()
|
||||
def on_smoothButton_clicked(self):
|
||||
dialog = QSpectrumAnalyzerSmoothing(self)
|
||||
dialog = QSpectrumAnalyzerSmooth(self)
|
||||
if dialog.exec_():
|
||||
settings = QtCore.QSettings()
|
||||
self.data_storage.set_smooth(
|
||||
bool(self.smoothCheckBox.isChecked()),
|
||||
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):
|
||||
prev_persistence_length = self.spectrumPlotWidget.persistence_length
|
||||
dialog = QSpectrumAnalyzerPersistence(self)
|
||||
@ -472,7 +481,7 @@ class QSpectrumAnalyzerMainWindow(QtWidgets.QMainWindow, Ui_QSpectrumAnalyzerMai
|
||||
else:
|
||||
self.spectrumPlotWidget.recalculate_persistence(self.data_storage)
|
||||
|
||||
@QtCore.Slot()
|
||||
@QtCore.pyqtSlot()
|
||||
def on_colorsButton_clicked(self):
|
||||
dialog = QSpectrumAnalyzerColors(self)
|
||||
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.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.baseline_color = str_to_color(settings.value("baseline_color", "255, 0, 255, 255"))
|
||||
self.spectrumPlotWidget.set_colors()
|
||||
|
||||
@QtCore.Slot()
|
||||
@QtCore.pyqtSlot()
|
||||
def on_action_Settings_triggered(self):
|
||||
dialog = QSpectrumAnalyzerSettings(self)
|
||||
if dialog.exec_():
|
||||
self.setup_power_thread()
|
||||
|
||||
@QtCore.Slot()
|
||||
@QtCore.pyqtSlot()
|
||||
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__))
|
||||
|
||||
@QtCore.Slot()
|
||||
@QtCore.pyqtSlot()
|
||||
def on_action_Quit_triggered(self):
|
||||
self.close()
|
||||
|
||||
@ -507,37 +515,12 @@ class QSpectrumAnalyzerMainWindow(QtWidgets.QMainWindow, Ui_QSpectrumAnalyzerMai
|
||||
|
||||
|
||||
def main():
|
||||
global debug
|
||||
|
||||
# Parse command line arguments
|
||||
parser = argparse.ArgumentParser(
|
||||
prog="qspectrumanalyzer",
|
||||
description="Spectrum analyzer for multiple SDR platforms",
|
||||
)
|
||||
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 = QtGui.QApplication(sys.argv)
|
||||
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__":
|
||||
|
566
qspectrumanalyzer/backend.py
Normal file
566
qspectrumanalyzer/backend.py
Normal 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()
|
@ -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
|
@ -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()
|
@ -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)
|
@ -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
|
@ -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)
|
@ -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)
|
@ -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)
|
@ -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)
|
@ -1,10 +1,9 @@
|
||||
import time, sys, os
|
||||
import time, sys
|
||||
|
||||
from Qt import QtCore
|
||||
from PyQt4 import QtCore
|
||||
import numpy as np
|
||||
|
||||
from qspectrumanalyzer.utils import smooth
|
||||
from qspectrumanalyzer.backends import soapy_power
|
||||
|
||||
|
||||
class HistoryBuffer:
|
||||
@ -37,7 +36,7 @@ class HistoryBuffer:
|
||||
|
||||
class TaskSignals(QtCore.QObject):
|
||||
"""Task signals emitter"""
|
||||
result = QtCore.Signal(object)
|
||||
result = QtCore.pyqtSignal(object)
|
||||
|
||||
|
||||
class Task(QtCore.QRunnable):
|
||||
@ -58,14 +57,12 @@ class Task(QtCore.QRunnable):
|
||||
|
||||
class DataStorage(QtCore.QObject):
|
||||
"""Data storage for spectrum measurements"""
|
||||
history_updated = QtCore.Signal(object)
|
||||
data_updated = QtCore.Signal(object)
|
||||
history_recalculated = QtCore.Signal(object)
|
||||
data_recalculated = QtCore.Signal(object)
|
||||
average_updated = QtCore.Signal(object)
|
||||
baseline_updated = QtCore.Signal(object)
|
||||
peak_hold_max_updated = QtCore.Signal(object)
|
||||
peak_hold_min_updated = QtCore.Signal(object)
|
||||
history_updated = QtCore.pyqtSignal(object)
|
||||
data_updated = QtCore.pyqtSignal(object)
|
||||
data_recalculated = QtCore.pyqtSignal(object)
|
||||
average_updated = QtCore.pyqtSignal(object)
|
||||
peak_hold_max_updated = QtCore.pyqtSignal(object)
|
||||
peak_hold_min_updated = QtCore.pyqtSignal(object)
|
||||
|
||||
def __init__(self, max_history_size=100, parent=None):
|
||||
super().__init__(parent)
|
||||
@ -73,10 +70,6 @@ class DataStorage(QtCore.QObject):
|
||||
self.smooth = False
|
||||
self.smooth_length = 11
|
||||
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
|
||||
# with more threads (and memory consumption is much higher)
|
||||
@ -112,20 +105,11 @@ class DataStorage(QtCore.QObject):
|
||||
|
||||
def update(self, data):
|
||||
"""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
|
||||
|
||||
if self.x is None:
|
||||
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_data, data)
|
||||
|
||||
@ -177,63 +161,16 @@ class DataStorage(QtCore.QObject):
|
||||
"""Apply smoothing function to data"""
|
||||
return smooth(y, window_len=self.smooth_length, window=self.smooth_window)
|
||||
|
||||
def set_smooth(self, toggle, length=11, window="hanning"):
|
||||
def set_smooth(self, toggle, length=11, window="hanning", recalculate=False):
|
||||
"""Toggle smoothing and set smoothing params"""
|
||||
if toggle != self.smooth or length != self.smooth_length or window != self.smooth_window:
|
||||
self.smooth = toggle
|
||||
self.smooth_length = length
|
||||
self.smooth_window = window
|
||||
if recalculate:
|
||||
self.start_task(self.recalculate_data)
|
||||
|
||||
def set_subtract_baseline(self, toggle, baseline_file=None):
|
||||
"""Toggle baseline subtraction and set baseline"""
|
||||
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)
|
||||
self.reset_data()
|
||||
|
||||
def recalculate_data(self):
|
||||
"""Recalculate current data from history"""
|
||||
|
@ -1,288 +1,250 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!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 &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>
|
||||
<name>QSpectrumAnalyzerColors</name>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_colors.py" line="112"/>
|
||||
<location filename="../ui_qspectrumanalyzer_colors.py" line="113"/>
|
||||
<source>Colors - QSpectrumAnalyzer</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_colors.py" line="124"/>
|
||||
<source>...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_colors.py" line="113"/>
|
||||
<source>&Main curve color:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_colors.py" line="115"/>
|
||||
<source>Max. peak &hold color:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_colors.py" line="117"/>
|
||||
<source>M&in. peak hold color:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_colors.py" line="119"/>
|
||||
<source>Average &color:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_colors.py" line="121"/>
|
||||
<source>Persistence co&lor:</source>
|
||||
<location filename="../ui_qspectrumanalyzer_colors.py" line="114"/>
|
||||
<source>Main curve color:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_colors.py" line="123"/>
|
||||
<source>&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>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>QSpectrumAnalyzerMainWindow</name>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer.py" line="317"/>
|
||||
<location filename="../ui_qspectrumanalyzer.py" line="311"/>
|
||||
<source>QSpectrumAnalyzer</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</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>&File</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer.py" line="319"/>
|
||||
<source>&Help</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer.py" line="350"/>
|
||||
<source>&Settings...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer.py" line="351"/>
|
||||
<source>&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>&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>&Start</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer.py" line="322"/>
|
||||
<source>S&top</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer.py" line="323"/>
|
||||
<source>Si&ngle shot</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<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>&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>&Interval [s]:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer.py" line="333"/>
|
||||
<source>&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>
|
||||
<translation type="unfinished"></translation>
|
||||
</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>
|
||||
<translation type="unfinished"></translation>
|
||||
</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>&File</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer.py" line="313"/>
|
||||
<source>&Help</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer.py" line="315"/>
|
||||
<source>&Start</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer.py" line="316"/>
|
||||
<source>S&top</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer.py" line="317"/>
|
||||
<source>Si&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>&Settings...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer.py" line="342"/>
|
||||
<source>&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>&About</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>QSpectrumAnalyzerPersistence</name>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_persistence.py" line="55"/>
|
||||
<location filename="../ui_qspectrumanalyzer_persistence.py" line="68"/>
|
||||
<source>Persistence - QSpectrumAnalyzer</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_persistence.py" line="56"/>
|
||||
<location filename="../ui_qspectrumanalyzer_persistence.py" line="69"/>
|
||||
<source>Decay function:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_persistence.py" line="57"/>
|
||||
<location filename="../ui_qspectrumanalyzer_persistence.py" line="70"/>
|
||||
<source>linear</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_persistence.py" line="58"/>
|
||||
<location filename="../ui_qspectrumanalyzer_persistence.py" line="71"/>
|
||||
<source>exponential</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_persistence.py" line="59"/>
|
||||
<location filename="../ui_qspectrumanalyzer_persistence.py" line="72"/>
|
||||
<source>Persistence length:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@ -290,148 +252,110 @@
|
||||
<context>
|
||||
<name>QSpectrumAnalyzerSettings</name>
|
||||
<message>
|
||||
<location filename="../settings.py" line="57"/>
|
||||
<location filename="../__main__.py" line="50"/>
|
||||
<source>Select executable - QSpectrumAnalyzer</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="148"/>
|
||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="107"/>
|
||||
<source>Settings - QSpectrumAnalyzer</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="149"/>
|
||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="108"/>
|
||||
<source>&Backend:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="156"/>
|
||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="115"/>
|
||||
<source>soapy_power</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="151"/>
|
||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="110"/>
|
||||
<source>rx_power</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="152"/>
|
||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="111"/>
|
||||
<source>rtl_power_fftw</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="153"/>
|
||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="112"/>
|
||||
<source>rtl_power</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="154"/>
|
||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="113"/>
|
||||
<source>hackrf_sweep</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="155"/>
|
||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="114"/>
|
||||
<source>E&xecutable:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="157"/>
|
||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="116"/>
|
||||
<source>...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</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&mple rate:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="160"/>
|
||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="119"/>
|
||||
<source>&Waterfall history size:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="158"/>
|
||||
<source>&Device:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="161"/>
|
||||
<source>Bandwidt&h:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="163"/>
|
||||
<source>&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&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>
|
||||
<name>QSpectrumAnalyzerSettingsHelp</name>
|
||||
<name>QSpectrumAnalyzerSmooth</name>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_settings_help.py" line="36"/>
|
||||
<source>Help - QSpectrumAnalyzer</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>QSpectrumAnalyzerSmoothing</name>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_smoothing.py" line="60"/>
|
||||
<location filename="../ui_qspectrumanalyzer_smooth.py" line="73"/>
|
||||
<source>Smoothing - QSpectrumAnalyzer</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_smoothing.py" line="61"/>
|
||||
<location filename="../ui_qspectrumanalyzer_smooth.py" line="74"/>
|
||||
<source>&Window function:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_smoothing.py" line="62"/>
|
||||
<location filename="../ui_qspectrumanalyzer_smooth.py" line="75"/>
|
||||
<source>rectangular</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_smoothing.py" line="63"/>
|
||||
<location filename="../ui_qspectrumanalyzer_smooth.py" line="76"/>
|
||||
<source>hanning</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_smoothing.py" line="64"/>
|
||||
<location filename="../ui_qspectrumanalyzer_smooth.py" line="77"/>
|
||||
<source>hamming</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_smoothing.py" line="65"/>
|
||||
<location filename="../ui_qspectrumanalyzer_smooth.py" line="78"/>
|
||||
<source>bartlett</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_smoothing.py" line="66"/>
|
||||
<location filename="../ui_qspectrumanalyzer_smooth.py" line="79"/>
|
||||
<source>blackman</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui_qspectrumanalyzer_smoothing.py" line="67"/>
|
||||
<location filename="../ui_qspectrumanalyzer_smooth.py" line="80"/>
|
||||
<source>Window len&gth:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -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)
|
@ -1,6 +1,6 @@
|
||||
import collections, math
|
||||
|
||||
from Qt import QtCore
|
||||
from PyQt4 import QtCore
|
||||
import pyqtgraph as pg
|
||||
|
||||
# Basic PyQtGraph settings
|
||||
@ -29,8 +29,6 @@ class SpectrumPlotWidget:
|
||||
self.peak_hold_min_color = pg.mkColor("b")
|
||||
self.average = False
|
||||
self.average_color = pg.mkColor("c")
|
||||
self.baseline = False
|
||||
self.baseline_color = pg.mkColor("m")
|
||||
|
||||
self.create_plot()
|
||||
|
||||
@ -44,10 +42,6 @@ class SpectrumPlotWidget:
|
||||
self.plot.setLimits(xMin=0)
|
||||
self.plot.showButtons()
|
||||
|
||||
#self.plot.setDownsampling(mode="peak")
|
||||
#self.plot.setClipToView(True)
|
||||
|
||||
self.create_baseline_curve()
|
||||
self.create_persistence_curves()
|
||||
self.create_average_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.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):
|
||||
"""Create spectrum persistence curves"""
|
||||
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_min.setPen(self.peak_hold_min_color)
|
||||
self.curve_average.setPen(self.average_color)
|
||||
self.curve_baseline.setPen(self.baseline_color)
|
||||
|
||||
decay = self.get_decay()
|
||||
for i, curve in enumerate(self.persistence_curves):
|
||||
@ -170,17 +158,6 @@ class SpectrumPlotWidget:
|
||||
if force:
|
||||
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):
|
||||
"""Update persistence curves"""
|
||||
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_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_min(data_storage, force=True))
|
||||
|
||||
@ -252,10 +228,6 @@ class SpectrumPlotWidget:
|
||||
"""Clear average curve"""
|
||||
self.curve_average.clear()
|
||||
|
||||
def clear_baseline(self):
|
||||
"""Clear baseline curve"""
|
||||
self.curve_baseline.clear()
|
||||
|
||||
def clear_persistence(self):
|
||||
"""Clear spectrum persistence curves"""
|
||||
self.persistence_data = None
|
||||
@ -292,7 +264,6 @@ class WaterfallPlotWidget:
|
||||
self.plot.setLimits(xMin=0, yMax=0)
|
||||
self.plot.showButtons()
|
||||
#self.plot.setAspectLocked(True)
|
||||
|
||||
#self.plot.setDownsampling(mode="peak")
|
||||
#self.plot.setClipToView(True)
|
||||
|
||||
@ -333,16 +304,3 @@ class WaterfallPlotWidget:
|
||||
def clear_plot(self):
|
||||
"""Clear waterfall plot"""
|
||||
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)
|
||||
|
@ -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 |
@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1200</width>
|
||||
<height>892</height>
|
||||
<height>810</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -52,7 +52,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1200</width>
|
||||
<height>32</height>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menu_File">
|
||||
@ -82,8 +82,8 @@
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>190</width>
|
||||
<height>130</height>
|
||||
<width>10</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="features">
|
||||
@ -143,8 +143,8 @@
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>208</width>
|
||||
<height>166</height>
|
||||
<width>10</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="features">
|
||||
@ -182,9 +182,6 @@
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="showGroupSeparator" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> MHz</string>
|
||||
</property>
|
||||
@ -192,10 +189,10 @@
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
<double>24.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>2200.000000000000000</double>
|
||||
<double>1766.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>87.000000000000000</double>
|
||||
@ -223,9 +220,6 @@
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="showGroupSeparator" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> MHz</string>
|
||||
</property>
|
||||
@ -233,10 +227,10 @@
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
<double>24.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>2200.000000000000000</double>
|
||||
<double>1766.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>108.000000000000000</double>
|
||||
@ -246,7 +240,7 @@
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>&Bin size:</string>
|
||||
<string>Bin size:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>binSizeSpinBox</cstring>
|
||||
@ -264,20 +258,14 @@
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="showGroupSeparator" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> kHz</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>10000.000000000000000</double>
|
||||
<double>2800.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>10.000000000000000</double>
|
||||
@ -321,7 +309,7 @@
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>&Interval [s]:</string>
|
||||
<string>Interval [s]:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>intervalSpinBox</cstring>
|
||||
@ -331,7 +319,7 @@
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>&Gain [dB]:</string>
|
||||
<string>Gain [dB]:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>gainSpinBox</cstring>
|
||||
@ -351,6 +339,25 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="2">
|
||||
<widget class="QSpinBox" name="gainSpinBox">
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="specialValueText">
|
||||
<string>auto</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>49</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
@ -456,7 +463,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<item row="9" column="0">
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
@ -476,55 +483,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</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>
|
||||
</widget>
|
||||
</widget>
|
||||
@ -605,9 +563,6 @@
|
||||
<tabstop>smoothButton</tabstop>
|
||||
<tabstop>persistenceCheckBox</tabstop>
|
||||
<tabstop>persistenceButton</tabstop>
|
||||
<tabstop>baselineCheckBox</tabstop>
|
||||
<tabstop>baselineButton</tabstop>
|
||||
<tabstop>subtractBaselineCheckBox</tabstop>
|
||||
<tabstop>histogramPlotLayout</tabstop>
|
||||
<tabstop>mainPlotLayout</tabstop>
|
||||
<tabstop>waterfallPlotLayout</tabstop>
|
||||
|
@ -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 &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>
|
@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>253</width>
|
||||
<height>266</height>
|
||||
<width>232</width>
|
||||
<height>260</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -19,7 +19,7 @@
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>&Main curve color:</string>
|
||||
<string>Main curve color:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>mainColorButton</cstring>
|
||||
@ -42,7 +42,7 @@
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Max. peak &hold color:</string>
|
||||
<string>Max. peak hold color:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>peakHoldMaxColorButton</cstring>
|
||||
@ -65,7 +65,7 @@
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>M&in. peak hold color:</string>
|
||||
<string>Min. peak hold color:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>peakHoldMinColorButton</cstring>
|
||||
@ -88,7 +88,7 @@
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Average &color:</string>
|
||||
<string>Average color:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>averageColorButton</cstring>
|
||||
@ -111,7 +111,7 @@
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Persistence co&lor:</string>
|
||||
<string>Persistence color:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>persistenceColorButton</cstring>
|
||||
@ -131,29 +131,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>&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>
|
||||
</item>
|
||||
<item>
|
||||
@ -194,7 +171,7 @@
|
||||
<tabstop>peakHoldMinColorButton</tabstop>
|
||||
<tabstop>averageColorButton</tabstop>
|
||||
<tabstop>persistenceColorButton</tabstop>
|
||||
<tabstop>baselineColorButton</tabstop>
|
||||
<tabstop>buttonBox</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
@ -205,12 +182,12 @@
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>246</x>
|
||||
<y>259</y>
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>265</y>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
@ -221,12 +198,12 @@
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>246</x>
|
||||
<y>259</y>
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>252</x>
|
||||
<y>265</y>
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
|
@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>600</width>
|
||||
<height>388</height>
|
||||
<width>420</width>
|
||||
<height>255</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -76,12 +76,6 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="executableButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
@ -89,17 +83,20 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>&Device:</string>
|
||||
<string>Device:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>deviceEdit</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</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">
|
||||
<property name="text">
|
||||
<string>Sa&mple rate:</string>
|
||||
@ -109,7 +106,23 @@
|
||||
</property>
|
||||
</widget>
|
||||
</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">
|
||||
<property name="text">
|
||||
<string>&Waterfall history size:</string>
|
||||
@ -119,7 +132,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<item row="4" column="1">
|
||||
<widget class="QSpinBox" name="waterfallHistorySizeSpinBox">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
@ -132,157 +145,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Bandwidt&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>&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&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>
|
||||
</item>
|
||||
<item>
|
||||
@ -314,14 +176,10 @@
|
||||
<tabstop>backendComboBox</tabstop>
|
||||
<tabstop>executableEdit</tabstop>
|
||||
<tabstop>executableButton</tabstop>
|
||||
<tabstop>paramsEdit</tabstop>
|
||||
<tabstop>paramsHelpButton</tabstop>
|
||||
<tabstop>deviceEdit</tabstop>
|
||||
<tabstop>deviceHelpButton</tabstop>
|
||||
<tabstop>sampleRateSpinBox</tabstop>
|
||||
<tabstop>bandwidthSpinBox</tabstop>
|
||||
<tabstop>lnbSpinBox</tabstop>
|
||||
<tabstop>waterfallHistorySizeSpinBox</tabstop>
|
||||
<tabstop>buttonBox</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
@ -332,8 +190,8 @@
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>254</x>
|
||||
<y>377</y>
|
||||
<x>242</x>
|
||||
<y>248</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
@ -348,8 +206,8 @@
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>322</x>
|
||||
<y>377</y>
|
||||
<x>310</x>
|
||||
<y>248</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
|
@ -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>
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>QSpectrumAnalyzerSmoothing</class>
|
||||
<widget class="QDialog" name="QSpectrumAnalyzerSmoothing">
|
||||
<class>QSpectrumAnalyzerSmooth</class>
|
||||
<widget class="QDialog" name="QSpectrumAnalyzerSmooth">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
@ -118,7 +118,7 @@
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>QSpectrumAnalyzerSmoothing</receiver>
|
||||
<receiver>QSpectrumAnalyzerSmooth</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
@ -134,7 +134,7 @@
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>QSpectrumAnalyzerSmoothing</receiver>
|
||||
<receiver>QSpectrumAnalyzerSmooth</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
@ -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)
|
@ -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)
|
@ -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)
|
@ -2,275 +2,273 @@
|
||||
|
||||
# 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!
|
||||
|
||||
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):
|
||||
def setupUi(self, QSpectrumAnalyzerMainWindow):
|
||||
QSpectrumAnalyzerMainWindow.setObjectName("QSpectrumAnalyzerMainWindow")
|
||||
QSpectrumAnalyzerMainWindow.resize(1200, 892)
|
||||
self.centralwidget = QtWidgets.QWidget(QSpectrumAnalyzerMainWindow)
|
||||
self.centralwidget.setObjectName("centralwidget")
|
||||
self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget)
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
self.plotSplitter = QtWidgets.QSplitter(self.centralwidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
|
||||
QSpectrumAnalyzerMainWindow.setObjectName(_fromUtf8("QSpectrumAnalyzerMainWindow"))
|
||||
QSpectrumAnalyzerMainWindow.resize(1200, 810)
|
||||
self.centralwidget = QtGui.QWidget(QSpectrumAnalyzerMainWindow)
|
||||
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
|
||||
self.horizontalLayout = QtGui.QHBoxLayout(self.centralwidget)
|
||||
self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
|
||||
self.plotSplitter = QtGui.QSplitter(self.centralwidget)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.plotSplitter.sizePolicy().hasHeightForWidth())
|
||||
self.plotSplitter.setSizePolicy(sizePolicy)
|
||||
self.plotSplitter.setOrientation(QtCore.Qt.Vertical)
|
||||
self.plotSplitter.setObjectName("plotSplitter")
|
||||
self.plotSplitter.setObjectName(_fromUtf8("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.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.mainPlotLayout.sizePolicy().hasHeightForWidth())
|
||||
self.mainPlotLayout.setSizePolicy(sizePolicy)
|
||||
self.mainPlotLayout.setObjectName("mainPlotLayout")
|
||||
self.mainPlotLayout.setObjectName(_fromUtf8("mainPlotLayout"))
|
||||
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.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.waterfallPlotLayout.sizePolicy().hasHeightForWidth())
|
||||
self.waterfallPlotLayout.setSizePolicy(sizePolicy)
|
||||
self.waterfallPlotLayout.setObjectName("waterfallPlotLayout")
|
||||
self.waterfallPlotLayout.setObjectName(_fromUtf8("waterfallPlotLayout"))
|
||||
self.horizontalLayout.addWidget(self.plotSplitter)
|
||||
QSpectrumAnalyzerMainWindow.setCentralWidget(self.centralwidget)
|
||||
self.menubar = QtWidgets.QMenuBar(QSpectrumAnalyzerMainWindow)
|
||||
self.menubar.setGeometry(QtCore.QRect(0, 0, 1200, 32))
|
||||
self.menubar.setObjectName("menubar")
|
||||
self.menu_File = QtWidgets.QMenu(self.menubar)
|
||||
self.menu_File.setObjectName("menu_File")
|
||||
self.menu_Help = QtWidgets.QMenu(self.menubar)
|
||||
self.menu_Help.setObjectName("menu_Help")
|
||||
self.menubar = QtGui.QMenuBar(QSpectrumAnalyzerMainWindow)
|
||||
self.menubar.setGeometry(QtCore.QRect(0, 0, 1200, 30))
|
||||
self.menubar.setObjectName(_fromUtf8("menubar"))
|
||||
self.menu_File = QtGui.QMenu(self.menubar)
|
||||
self.menu_File.setObjectName(_fromUtf8("menu_File"))
|
||||
self.menu_Help = QtGui.QMenu(self.menubar)
|
||||
self.menu_Help.setObjectName(_fromUtf8("menu_Help"))
|
||||
QSpectrumAnalyzerMainWindow.setMenuBar(self.menubar)
|
||||
self.statusbar = QtWidgets.QStatusBar(QSpectrumAnalyzerMainWindow)
|
||||
self.statusbar.setObjectName("statusbar")
|
||||
self.statusbar = QtGui.QStatusBar(QSpectrumAnalyzerMainWindow)
|
||||
self.statusbar.setObjectName(_fromUtf8("statusbar"))
|
||||
QSpectrumAnalyzerMainWindow.setStatusBar(self.statusbar)
|
||||
self.controlsDockWidget = QtWidgets.QDockWidget(QSpectrumAnalyzerMainWindow)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
|
||||
self.controlsDockWidget = QtGui.QDockWidget(QSpectrumAnalyzerMainWindow)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Minimum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.controlsDockWidget.sizePolicy().hasHeightForWidth())
|
||||
self.controlsDockWidget.setSizePolicy(sizePolicy)
|
||||
self.controlsDockWidget.setMinimumSize(QtCore.QSize(190, 130))
|
||||
self.controlsDockWidget.setFeatures(QtWidgets.QDockWidget.DockWidgetFloatable|QtWidgets.QDockWidget.DockWidgetMovable)
|
||||
self.controlsDockWidget.setObjectName("controlsDockWidget")
|
||||
self.controlsDockWidgetContents = QtWidgets.QWidget()
|
||||
self.controlsDockWidgetContents.setObjectName("controlsDockWidgetContents")
|
||||
self.gridLayout_2 = QtWidgets.QGridLayout(self.controlsDockWidgetContents)
|
||||
self.gridLayout_2.setContentsMargins(0, 0, 0, 0)
|
||||
self.gridLayout_2.setObjectName("gridLayout_2")
|
||||
self.startButton = QtWidgets.QPushButton(self.controlsDockWidgetContents)
|
||||
self.startButton.setObjectName("startButton")
|
||||
self.controlsDockWidget.setMinimumSize(QtCore.QSize(10, 10))
|
||||
self.controlsDockWidget.setFeatures(QtGui.QDockWidget.DockWidgetFloatable|QtGui.QDockWidget.DockWidgetMovable)
|
||||
self.controlsDockWidget.setObjectName(_fromUtf8("controlsDockWidget"))
|
||||
self.controlsDockWidgetContents = QtGui.QWidget()
|
||||
self.controlsDockWidgetContents.setObjectName(_fromUtf8("controlsDockWidgetContents"))
|
||||
self.gridLayout_2 = QtGui.QGridLayout(self.controlsDockWidgetContents)
|
||||
self.gridLayout_2.setMargin(0)
|
||||
self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
|
||||
self.startButton = QtGui.QPushButton(self.controlsDockWidgetContents)
|
||||
self.startButton.setObjectName(_fromUtf8("startButton"))
|
||||
self.gridLayout_2.addWidget(self.startButton, 0, 0, 1, 1)
|
||||
self.stopButton = QtWidgets.QPushButton(self.controlsDockWidgetContents)
|
||||
self.stopButton.setObjectName("stopButton")
|
||||
self.stopButton = QtGui.QPushButton(self.controlsDockWidgetContents)
|
||||
self.stopButton.setObjectName(_fromUtf8("stopButton"))
|
||||
self.gridLayout_2.addWidget(self.stopButton, 0, 1, 1, 1)
|
||||
self.singleShotButton = QtWidgets.QPushButton(self.controlsDockWidgetContents)
|
||||
self.singleShotButton.setObjectName("singleShotButton")
|
||||
self.singleShotButton = QtGui.QPushButton(self.controlsDockWidgetContents)
|
||||
self.singleShotButton.setObjectName(_fromUtf8("singleShotButton"))
|
||||
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.controlsDockWidget.setWidget(self.controlsDockWidgetContents)
|
||||
QSpectrumAnalyzerMainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.controlsDockWidget)
|
||||
self.frequencyDockWidget = QtWidgets.QDockWidget(QSpectrumAnalyzerMainWindow)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
|
||||
self.frequencyDockWidget = QtGui.QDockWidget(QSpectrumAnalyzerMainWindow)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Minimum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.frequencyDockWidget.sizePolicy().hasHeightForWidth())
|
||||
self.frequencyDockWidget.setSizePolicy(sizePolicy)
|
||||
self.frequencyDockWidget.setMinimumSize(QtCore.QSize(208, 166))
|
||||
self.frequencyDockWidget.setFeatures(QtWidgets.QDockWidget.DockWidgetFloatable|QtWidgets.QDockWidget.DockWidgetMovable)
|
||||
self.frequencyDockWidget.setObjectName("frequencyDockWidget")
|
||||
self.frequencyDockWidgetContents = QtWidgets.QWidget()
|
||||
self.frequencyDockWidgetContents.setObjectName("frequencyDockWidgetContents")
|
||||
self.formLayout = QtWidgets.QFormLayout(self.frequencyDockWidgetContents)
|
||||
self.formLayout.setFieldGrowthPolicy(QtWidgets.QFormLayout.ExpandingFieldsGrow)
|
||||
self.formLayout.setContentsMargins(0, 0, 0, 0)
|
||||
self.formLayout.setObjectName("formLayout")
|
||||
self.label_2 = QtWidgets.QLabel(self.frequencyDockWidgetContents)
|
||||
self.label_2.setObjectName("label_2")
|
||||
self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.label_2)
|
||||
self.startFreqSpinBox = QtWidgets.QDoubleSpinBox(self.frequencyDockWidgetContents)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
self.frequencyDockWidget.setMinimumSize(QtCore.QSize(10, 10))
|
||||
self.frequencyDockWidget.setFeatures(QtGui.QDockWidget.DockWidgetFloatable|QtGui.QDockWidget.DockWidgetMovable)
|
||||
self.frequencyDockWidget.setObjectName(_fromUtf8("frequencyDockWidget"))
|
||||
self.frequencyDockWidgetContents = QtGui.QWidget()
|
||||
self.frequencyDockWidgetContents.setObjectName(_fromUtf8("frequencyDockWidgetContents"))
|
||||
self.formLayout = QtGui.QFormLayout(self.frequencyDockWidgetContents)
|
||||
self.formLayout.setFieldGrowthPolicy(QtGui.QFormLayout.ExpandingFieldsGrow)
|
||||
self.formLayout.setMargin(0)
|
||||
self.formLayout.setObjectName(_fromUtf8("formLayout"))
|
||||
self.label_2 = QtGui.QLabel(self.frequencyDockWidgetContents)
|
||||
self.label_2.setObjectName(_fromUtf8("label_2"))
|
||||
self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.label_2)
|
||||
self.startFreqSpinBox = QtGui.QDoubleSpinBox(self.frequencyDockWidgetContents)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.startFreqSpinBox.sizePolicy().hasHeightForWidth())
|
||||
self.startFreqSpinBox.setSizePolicy(sizePolicy)
|
||||
self.startFreqSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||
self.startFreqSpinBox.setProperty("showGroupSeparator", True)
|
||||
self.startFreqSpinBox.setDecimals(3)
|
||||
self.startFreqSpinBox.setMinimum(0.0)
|
||||
self.startFreqSpinBox.setMaximum(2200.0)
|
||||
self.startFreqSpinBox.setMinimum(24.0)
|
||||
self.startFreqSpinBox.setMaximum(1766.0)
|
||||
self.startFreqSpinBox.setProperty("value", 87.0)
|
||||
self.startFreqSpinBox.setObjectName("startFreqSpinBox")
|
||||
self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.startFreqSpinBox)
|
||||
self.label_3 = QtWidgets.QLabel(self.frequencyDockWidgetContents)
|
||||
self.label_3.setObjectName("label_3")
|
||||
self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label_3)
|
||||
self.stopFreqSpinBox = QtWidgets.QDoubleSpinBox(self.frequencyDockWidgetContents)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
self.startFreqSpinBox.setObjectName(_fromUtf8("startFreqSpinBox"))
|
||||
self.formLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.startFreqSpinBox)
|
||||
self.label_3 = QtGui.QLabel(self.frequencyDockWidgetContents)
|
||||
self.label_3.setObjectName(_fromUtf8("label_3"))
|
||||
self.formLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.label_3)
|
||||
self.stopFreqSpinBox = QtGui.QDoubleSpinBox(self.frequencyDockWidgetContents)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.stopFreqSpinBox.sizePolicy().hasHeightForWidth())
|
||||
self.stopFreqSpinBox.setSizePolicy(sizePolicy)
|
||||
self.stopFreqSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||
self.stopFreqSpinBox.setProperty("showGroupSeparator", True)
|
||||
self.stopFreqSpinBox.setDecimals(3)
|
||||
self.stopFreqSpinBox.setMinimum(0.0)
|
||||
self.stopFreqSpinBox.setMaximum(2200.0)
|
||||
self.stopFreqSpinBox.setMinimum(24.0)
|
||||
self.stopFreqSpinBox.setMaximum(1766.0)
|
||||
self.stopFreqSpinBox.setProperty("value", 108.0)
|
||||
self.stopFreqSpinBox.setObjectName("stopFreqSpinBox")
|
||||
self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.stopFreqSpinBox)
|
||||
self.label = QtWidgets.QLabel(self.frequencyDockWidgetContents)
|
||||
self.label.setObjectName("label")
|
||||
self.formLayout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.label)
|
||||
self.binSizeSpinBox = QtWidgets.QDoubleSpinBox(self.frequencyDockWidgetContents)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
self.stopFreqSpinBox.setObjectName(_fromUtf8("stopFreqSpinBox"))
|
||||
self.formLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.stopFreqSpinBox)
|
||||
self.label = QtGui.QLabel(self.frequencyDockWidgetContents)
|
||||
self.label.setObjectName(_fromUtf8("label"))
|
||||
self.formLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.label)
|
||||
self.binSizeSpinBox = QtGui.QDoubleSpinBox(self.frequencyDockWidgetContents)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.binSizeSpinBox.sizePolicy().hasHeightForWidth())
|
||||
self.binSizeSpinBox.setSizePolicy(sizePolicy)
|
||||
self.binSizeSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||
self.binSizeSpinBox.setProperty("showGroupSeparator", True)
|
||||
self.binSizeSpinBox.setDecimals(3)
|
||||
self.binSizeSpinBox.setMinimum(0.0)
|
||||
self.binSizeSpinBox.setMaximum(10000.0)
|
||||
self.binSizeSpinBox.setMaximum(2800.0)
|
||||
self.binSizeSpinBox.setProperty("value", 10.0)
|
||||
self.binSizeSpinBox.setObjectName("binSizeSpinBox")
|
||||
self.formLayout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.binSizeSpinBox)
|
||||
spacerItem1 = QtWidgets.QSpacerItem(20, 0, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.formLayout.setItem(3, QtWidgets.QFormLayout.SpanningRole, spacerItem1)
|
||||
self.binSizeSpinBox.setObjectName(_fromUtf8("binSizeSpinBox"))
|
||||
self.formLayout.setWidget(2, QtGui.QFormLayout.FieldRole, self.binSizeSpinBox)
|
||||
spacerItem1 = QtGui.QSpacerItem(20, 0, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
||||
self.formLayout.setItem(3, QtGui.QFormLayout.SpanningRole, spacerItem1)
|
||||
self.frequencyDockWidget.setWidget(self.frequencyDockWidgetContents)
|
||||
QSpectrumAnalyzerMainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.frequencyDockWidget)
|
||||
self.settingsDockWidget = QtWidgets.QDockWidget(QSpectrumAnalyzerMainWindow)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding)
|
||||
self.settingsDockWidget = QtGui.QDockWidget(QSpectrumAnalyzerMainWindow)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Expanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.settingsDockWidget.sizePolicy().hasHeightForWidth())
|
||||
self.settingsDockWidget.setSizePolicy(sizePolicy)
|
||||
self.settingsDockWidget.setFeatures(QtWidgets.QDockWidget.DockWidgetFloatable|QtWidgets.QDockWidget.DockWidgetMovable)
|
||||
self.settingsDockWidget.setObjectName("settingsDockWidget")
|
||||
self.settingsDockWidgetContents = QtWidgets.QWidget()
|
||||
self.settingsDockWidgetContents.setObjectName("settingsDockWidgetContents")
|
||||
self.gridLayout = QtWidgets.QGridLayout(self.settingsDockWidgetContents)
|
||||
self.gridLayout.setContentsMargins(0, 0, 0, 0)
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
self.label_4 = QtWidgets.QLabel(self.settingsDockWidgetContents)
|
||||
self.label_4.setObjectName("label_4")
|
||||
self.settingsDockWidget.setFeatures(QtGui.QDockWidget.DockWidgetFloatable|QtGui.QDockWidget.DockWidgetMovable)
|
||||
self.settingsDockWidget.setObjectName(_fromUtf8("settingsDockWidget"))
|
||||
self.settingsDockWidgetContents = QtGui.QWidget()
|
||||
self.settingsDockWidgetContents.setObjectName(_fromUtf8("settingsDockWidgetContents"))
|
||||
self.gridLayout = QtGui.QGridLayout(self.settingsDockWidgetContents)
|
||||
self.gridLayout.setMargin(0)
|
||||
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
|
||||
self.label_4 = QtGui.QLabel(self.settingsDockWidgetContents)
|
||||
self.label_4.setObjectName(_fromUtf8("label_4"))
|
||||
self.gridLayout.addWidget(self.label_4, 0, 0, 1, 1)
|
||||
self.label_6 = QtWidgets.QLabel(self.settingsDockWidgetContents)
|
||||
self.label_6.setObjectName("label_6")
|
||||
self.label_6 = QtGui.QLabel(self.settingsDockWidgetContents)
|
||||
self.label_6.setObjectName(_fromUtf8("label_6"))
|
||||
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.setMaximum(999.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.label_5 = QtWidgets.QLabel(self.settingsDockWidgetContents)
|
||||
self.label_5.setObjectName("label_5")
|
||||
self.gainSpinBox = QtGui.QSpinBox(self.settingsDockWidgetContents)
|
||||
self.gainSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||
self.gainSpinBox.setMinimum(-1)
|
||||
self.gainSpinBox.setMaximum(49)
|
||||
self.gainSpinBox.setProperty("value", -1)
|
||||
self.gainSpinBox.setObjectName(_fromUtf8("gainSpinBox"))
|
||||
self.gridLayout.addWidget(self.gainSpinBox, 1, 1, 1, 2)
|
||||
self.label_5 = QtGui.QLabel(self.settingsDockWidgetContents)
|
||||
self.label_5.setObjectName(_fromUtf8("label_5"))
|
||||
self.gridLayout.addWidget(self.label_5, 2, 0, 1, 1)
|
||||
self.label_7 = QtWidgets.QLabel(self.settingsDockWidgetContents)
|
||||
self.label_7.setObjectName("label_7")
|
||||
self.label_7 = QtGui.QLabel(self.settingsDockWidgetContents)
|
||||
self.label_7.setObjectName(_fromUtf8("label_7"))
|
||||
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.setMinimum(-999)
|
||||
self.ppmSpinBox.setMaximum(999)
|
||||
self.ppmSpinBox.setObjectName("ppmSpinBox")
|
||||
self.ppmSpinBox.setObjectName(_fromUtf8("ppmSpinBox"))
|
||||
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.setObjectName("mainCurveCheckBox")
|
||||
self.mainCurveCheckBox.setObjectName(_fromUtf8("mainCurveCheckBox"))
|
||||
self.gridLayout.addWidget(self.mainCurveCheckBox, 4, 0, 1, 1)
|
||||
self.colorsButton = QtWidgets.QPushButton(self.settingsDockWidgetContents)
|
||||
self.colorsButton.setObjectName("colorsButton")
|
||||
self.colorsButton = QtGui.QPushButton(self.settingsDockWidgetContents)
|
||||
self.colorsButton.setObjectName(_fromUtf8("colorsButton"))
|
||||
self.gridLayout.addWidget(self.colorsButton, 4, 1, 1, 2)
|
||||
self.peakHoldMaxCheckBox = QtWidgets.QCheckBox(self.settingsDockWidgetContents)
|
||||
self.peakHoldMaxCheckBox.setObjectName("peakHoldMaxCheckBox")
|
||||
self.peakHoldMaxCheckBox = QtGui.QCheckBox(self.settingsDockWidgetContents)
|
||||
self.peakHoldMaxCheckBox.setObjectName(_fromUtf8("peakHoldMaxCheckBox"))
|
||||
self.gridLayout.addWidget(self.peakHoldMaxCheckBox, 5, 0, 1, 1)
|
||||
self.peakHoldMinCheckBox = QtWidgets.QCheckBox(self.settingsDockWidgetContents)
|
||||
self.peakHoldMinCheckBox.setObjectName("peakHoldMinCheckBox")
|
||||
self.peakHoldMinCheckBox = QtGui.QCheckBox(self.settingsDockWidgetContents)
|
||||
self.peakHoldMinCheckBox.setObjectName(_fromUtf8("peakHoldMinCheckBox"))
|
||||
self.gridLayout.addWidget(self.peakHoldMinCheckBox, 5, 1, 1, 2)
|
||||
self.averageCheckBox = QtWidgets.QCheckBox(self.settingsDockWidgetContents)
|
||||
self.averageCheckBox.setObjectName("averageCheckBox")
|
||||
self.averageCheckBox = QtGui.QCheckBox(self.settingsDockWidgetContents)
|
||||
self.averageCheckBox.setObjectName(_fromUtf8("averageCheckBox"))
|
||||
self.gridLayout.addWidget(self.averageCheckBox, 6, 0, 1, 1)
|
||||
self.smoothCheckBox = QtWidgets.QCheckBox(self.settingsDockWidgetContents)
|
||||
self.smoothCheckBox.setObjectName("smoothCheckBox")
|
||||
self.smoothCheckBox = QtGui.QCheckBox(self.settingsDockWidgetContents)
|
||||
self.smoothCheckBox.setObjectName(_fromUtf8("smoothCheckBox"))
|
||||
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.setObjectName("smoothButton")
|
||||
self.smoothButton.setObjectName(_fromUtf8("smoothButton"))
|
||||
self.gridLayout.addWidget(self.smoothButton, 7, 2, 1, 1)
|
||||
self.persistenceCheckBox = QtWidgets.QCheckBox(self.settingsDockWidgetContents)
|
||||
self.persistenceCheckBox.setObjectName("persistenceCheckBox")
|
||||
self.persistenceCheckBox = QtGui.QCheckBox(self.settingsDockWidgetContents)
|
||||
self.persistenceCheckBox.setObjectName(_fromUtf8("persistenceCheckBox"))
|
||||
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.setObjectName("persistenceButton")
|
||||
self.persistenceButton.setObjectName(_fromUtf8("persistenceButton"))
|
||||
self.gridLayout.addWidget(self.persistenceButton, 8, 2, 1, 1)
|
||||
spacerItem2 = QtWidgets.QSpacerItem(20, 1, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.gridLayout.addItem(spacerItem2, 11, 0, 1, 1)
|
||||
self.cropSpinBox = QtWidgets.QSpinBox(self.settingsDockWidgetContents)
|
||||
spacerItem2 = QtGui.QSpacerItem(20, 1, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
||||
self.gridLayout.addItem(spacerItem2, 9, 0, 1, 1)
|
||||
self.cropSpinBox = QtGui.QSpinBox(self.settingsDockWidgetContents)
|
||||
self.cropSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||
self.cropSpinBox.setObjectName("cropSpinBox")
|
||||
self.cropSpinBox.setObjectName(_fromUtf8("cropSpinBox"))
|
||||
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)
|
||||
QSpectrumAnalyzerMainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.settingsDockWidget)
|
||||
self.levelsDockWidget = QtWidgets.QDockWidget(QSpectrumAnalyzerMainWindow)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding)
|
||||
self.levelsDockWidget = QtGui.QDockWidget(QSpectrumAnalyzerMainWindow)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Expanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.levelsDockWidget.sizePolicy().hasHeightForWidth())
|
||||
self.levelsDockWidget.setSizePolicy(sizePolicy)
|
||||
self.levelsDockWidget.setFeatures(QtWidgets.QDockWidget.DockWidgetFloatable|QtWidgets.QDockWidget.DockWidgetMovable)
|
||||
self.levelsDockWidget.setObjectName("levelsDockWidget")
|
||||
self.levelsDockWidgetContents = QtWidgets.QWidget()
|
||||
self.levelsDockWidgetContents.setObjectName("levelsDockWidgetContents")
|
||||
self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.levelsDockWidgetContents)
|
||||
self.verticalLayout_6.setContentsMargins(0, 0, 0, 0)
|
||||
self.verticalLayout_6.setObjectName("verticalLayout_6")
|
||||
self.levelsDockWidget.setFeatures(QtGui.QDockWidget.DockWidgetFloatable|QtGui.QDockWidget.DockWidgetMovable)
|
||||
self.levelsDockWidget.setObjectName(_fromUtf8("levelsDockWidget"))
|
||||
self.levelsDockWidgetContents = QtGui.QWidget()
|
||||
self.levelsDockWidgetContents.setObjectName(_fromUtf8("levelsDockWidgetContents"))
|
||||
self.verticalLayout_6 = QtGui.QVBoxLayout(self.levelsDockWidgetContents)
|
||||
self.verticalLayout_6.setMargin(0)
|
||||
self.verticalLayout_6.setObjectName(_fromUtf8("verticalLayout_6"))
|
||||
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.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.histogramPlotLayout.sizePolicy().hasHeightForWidth())
|
||||
self.histogramPlotLayout.setSizePolicy(sizePolicy)
|
||||
self.histogramPlotLayout.setObjectName("histogramPlotLayout")
|
||||
self.histogramPlotLayout.setObjectName(_fromUtf8("histogramPlotLayout"))
|
||||
self.verticalLayout_6.addWidget(self.histogramPlotLayout)
|
||||
self.levelsDockWidget.setWidget(self.levelsDockWidgetContents)
|
||||
QSpectrumAnalyzerMainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.levelsDockWidget)
|
||||
self.action_Settings = QtWidgets.QAction(QSpectrumAnalyzerMainWindow)
|
||||
self.action_Settings.setObjectName("action_Settings")
|
||||
self.action_Quit = QtWidgets.QAction(QSpectrumAnalyzerMainWindow)
|
||||
self.action_Quit.setObjectName("action_Quit")
|
||||
self.action_About = QtWidgets.QAction(QSpectrumAnalyzerMainWindow)
|
||||
self.action_About.setObjectName("action_About")
|
||||
self.action_Settings = QtGui.QAction(QSpectrumAnalyzerMainWindow)
|
||||
self.action_Settings.setObjectName(_fromUtf8("action_Settings"))
|
||||
self.action_Quit = QtGui.QAction(QSpectrumAnalyzerMainWindow)
|
||||
self.action_Quit.setObjectName(_fromUtf8("action_Quit"))
|
||||
self.action_About = QtGui.QAction(QSpectrumAnalyzerMainWindow)
|
||||
self.action_About.setObjectName(_fromUtf8("action_About"))
|
||||
self.menu_File.addAction(self.action_Settings)
|
||||
self.menu_File.addSeparator()
|
||||
self.menu_File.addAction(self.action_Quit)
|
||||
@ -305,51 +303,44 @@ class Ui_QSpectrumAnalyzerMainWindow(object):
|
||||
QSpectrumAnalyzerMainWindow.setTabOrder(self.smoothCheckBox, self.smoothButton)
|
||||
QSpectrumAnalyzerMainWindow.setTabOrder(self.smoothButton, self.persistenceCheckBox)
|
||||
QSpectrumAnalyzerMainWindow.setTabOrder(self.persistenceCheckBox, self.persistenceButton)
|
||||
QSpectrumAnalyzerMainWindow.setTabOrder(self.persistenceButton, self.baselineCheckBox)
|
||||
QSpectrumAnalyzerMainWindow.setTabOrder(self.baselineCheckBox, self.baselineButton)
|
||||
QSpectrumAnalyzerMainWindow.setTabOrder(self.baselineButton, self.subtractBaselineCheckBox)
|
||||
QSpectrumAnalyzerMainWindow.setTabOrder(self.subtractBaselineCheckBox, self.histogramPlotLayout)
|
||||
QSpectrumAnalyzerMainWindow.setTabOrder(self.persistenceButton, self.histogramPlotLayout)
|
||||
QSpectrumAnalyzerMainWindow.setTabOrder(self.histogramPlotLayout, self.mainPlotLayout)
|
||||
QSpectrumAnalyzerMainWindow.setTabOrder(self.mainPlotLayout, self.waterfallPlotLayout)
|
||||
|
||||
def retranslateUi(self, QSpectrumAnalyzerMainWindow):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
QSpectrumAnalyzerMainWindow.setWindowTitle(_translate("QSpectrumAnalyzerMainWindow", "QSpectrumAnalyzer"))
|
||||
self.menu_File.setTitle(_translate("QSpectrumAnalyzerMainWindow", "&File"))
|
||||
self.menu_Help.setTitle(_translate("QSpectrumAnalyzerMainWindow", "&Help"))
|
||||
self.controlsDockWidget.setWindowTitle(_translate("QSpectrumAnalyzerMainWindow", "Controls"))
|
||||
self.startButton.setText(_translate("QSpectrumAnalyzerMainWindow", "&Start"))
|
||||
self.stopButton.setText(_translate("QSpectrumAnalyzerMainWindow", "S&top"))
|
||||
self.singleShotButton.setText(_translate("QSpectrumAnalyzerMainWindow", "Si&ngle shot"))
|
||||
self.frequencyDockWidget.setWindowTitle(_translate("QSpectrumAnalyzerMainWindow", "Frequency"))
|
||||
self.label_2.setText(_translate("QSpectrumAnalyzerMainWindow", "Start:"))
|
||||
self.startFreqSpinBox.setSuffix(_translate("QSpectrumAnalyzerMainWindow", " MHz"))
|
||||
self.label_3.setText(_translate("QSpectrumAnalyzerMainWindow", "Stop:"))
|
||||
self.stopFreqSpinBox.setSuffix(_translate("QSpectrumAnalyzerMainWindow", " MHz"))
|
||||
self.label.setText(_translate("QSpectrumAnalyzerMainWindow", "&Bin size:"))
|
||||
self.binSizeSpinBox.setSuffix(_translate("QSpectrumAnalyzerMainWindow", " kHz"))
|
||||
self.settingsDockWidget.setWindowTitle(_translate("QSpectrumAnalyzerMainWindow", "Settings"))
|
||||
self.label_4.setText(_translate("QSpectrumAnalyzerMainWindow", "&Interval [s]:"))
|
||||
self.label_6.setText(_translate("QSpectrumAnalyzerMainWindow", "&Gain [dB]:"))
|
||||
self.label_5.setText(_translate("QSpectrumAnalyzerMainWindow", "Corr. [ppm]:"))
|
||||
self.label_7.setText(_translate("QSpectrumAnalyzerMainWindow", "Crop [%]:"))
|
||||
self.mainCurveCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Main curve"))
|
||||
self.colorsButton.setText(_translate("QSpectrumAnalyzerMainWindow", "Colors..."))
|
||||
self.peakHoldMaxCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Max. hold"))
|
||||
self.peakHoldMinCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Min. hold"))
|
||||
self.averageCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Average"))
|
||||
self.smoothCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Smoothing"))
|
||||
self.smoothButton.setText(_translate("QSpectrumAnalyzerMainWindow", "..."))
|
||||
self.persistenceCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Persistence"))
|
||||
self.persistenceButton.setText(_translate("QSpectrumAnalyzerMainWindow", "..."))
|
||||
self.gainSpinBox.setSpecialValueText(_translate("QSpectrumAnalyzerMainWindow", "auto"))
|
||||
self.baselineCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Baseline"))
|
||||
self.baselineButton.setText(_translate("QSpectrumAnalyzerMainWindow", "..."))
|
||||
self.subtractBaselineCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Subtract baseline"))
|
||||
self.levelsDockWidget.setWindowTitle(_translate("QSpectrumAnalyzerMainWindow", "Levels"))
|
||||
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"))
|
||||
QSpectrumAnalyzerMainWindow.setWindowTitle(_translate("QSpectrumAnalyzerMainWindow", "QSpectrumAnalyzer", None))
|
||||
self.menu_File.setTitle(_translate("QSpectrumAnalyzerMainWindow", "&File", None))
|
||||
self.menu_Help.setTitle(_translate("QSpectrumAnalyzerMainWindow", "&Help", None))
|
||||
self.controlsDockWidget.setWindowTitle(_translate("QSpectrumAnalyzerMainWindow", "Controls", None))
|
||||
self.startButton.setText(_translate("QSpectrumAnalyzerMainWindow", "&Start", None))
|
||||
self.stopButton.setText(_translate("QSpectrumAnalyzerMainWindow", "S&top", None))
|
||||
self.singleShotButton.setText(_translate("QSpectrumAnalyzerMainWindow", "Si&ngle shot", None))
|
||||
self.frequencyDockWidget.setWindowTitle(_translate("QSpectrumAnalyzerMainWindow", "Frequency", None))
|
||||
self.label_2.setText(_translate("QSpectrumAnalyzerMainWindow", "Start:", None))
|
||||
self.startFreqSpinBox.setSuffix(_translate("QSpectrumAnalyzerMainWindow", " MHz", None))
|
||||
self.label_3.setText(_translate("QSpectrumAnalyzerMainWindow", "Stop:", None))
|
||||
self.stopFreqSpinBox.setSuffix(_translate("QSpectrumAnalyzerMainWindow", " MHz", None))
|
||||
self.label.setText(_translate("QSpectrumAnalyzerMainWindow", "Bin size:", None))
|
||||
self.binSizeSpinBox.setSuffix(_translate("QSpectrumAnalyzerMainWindow", " kHz", None))
|
||||
self.settingsDockWidget.setWindowTitle(_translate("QSpectrumAnalyzerMainWindow", "Settings", None))
|
||||
self.label_4.setText(_translate("QSpectrumAnalyzerMainWindow", "Interval [s]:", None))
|
||||
self.label_6.setText(_translate("QSpectrumAnalyzerMainWindow", "Gain [dB]:", None))
|
||||
self.gainSpinBox.setSpecialValueText(_translate("QSpectrumAnalyzerMainWindow", "auto", None))
|
||||
self.label_5.setText(_translate("QSpectrumAnalyzerMainWindow", "Corr. [ppm]:", None))
|
||||
self.label_7.setText(_translate("QSpectrumAnalyzerMainWindow", "Crop [%]:", None))
|
||||
self.mainCurveCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Main curve", None))
|
||||
self.colorsButton.setText(_translate("QSpectrumAnalyzerMainWindow", "Colors...", None))
|
||||
self.peakHoldMaxCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Max. hold", None))
|
||||
self.peakHoldMinCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Min. hold", None))
|
||||
self.averageCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Average", None))
|
||||
self.smoothCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Smoothing", None))
|
||||
self.smoothButton.setText(_translate("QSpectrumAnalyzerMainWindow", "...", None))
|
||||
self.persistenceCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Persistence", None))
|
||||
self.persistenceButton.setText(_translate("QSpectrumAnalyzerMainWindow", "...", None))
|
||||
self.levelsDockWidget.setWindowTitle(_translate("QSpectrumAnalyzerMainWindow", "Levels", None))
|
||||
self.action_Settings.setText(_translate("QSpectrumAnalyzerMainWindow", "&Settings...", None))
|
||||
self.action_Quit.setText(_translate("QSpectrumAnalyzerMainWindow", "&Quit", None))
|
||||
self.action_Quit.setShortcut(_translate("QSpectrumAnalyzerMainWindow", "Ctrl+Q", None))
|
||||
self.action_About.setText(_translate("QSpectrumAnalyzerMainWindow", "&About", None))
|
||||
|
||||
from pyqtgraph import GraphicsLayoutWidget
|
||||
|
@ -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", "..."))
|
||||
|
@ -2,125 +2,124 @@
|
||||
|
||||
# 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!
|
||||
|
||||
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):
|
||||
def setupUi(self, QSpectrumAnalyzerColors):
|
||||
QSpectrumAnalyzerColors.setObjectName("QSpectrumAnalyzerColors")
|
||||
QSpectrumAnalyzerColors.resize(253, 266)
|
||||
self.verticalLayout = QtWidgets.QVBoxLayout(QSpectrumAnalyzerColors)
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
self.formLayout = QtWidgets.QFormLayout()
|
||||
self.formLayout.setObjectName("formLayout")
|
||||
self.label_2 = QtWidgets.QLabel(QSpectrumAnalyzerColors)
|
||||
self.label_2.setObjectName("label_2")
|
||||
self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.label_2)
|
||||
QSpectrumAnalyzerColors.setObjectName(_fromUtf8("QSpectrumAnalyzerColors"))
|
||||
QSpectrumAnalyzerColors.resize(232, 260)
|
||||
self.verticalLayout = QtGui.QVBoxLayout(QSpectrumAnalyzerColors)
|
||||
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
|
||||
self.formLayout = QtGui.QFormLayout()
|
||||
self.formLayout.setObjectName(_fromUtf8("formLayout"))
|
||||
self.label_2 = QtGui.QLabel(QSpectrumAnalyzerColors)
|
||||
self.label_2.setObjectName(_fromUtf8("label_2"))
|
||||
self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.label_2)
|
||||
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.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.mainColorButton.sizePolicy().hasHeightForWidth())
|
||||
self.mainColorButton.setSizePolicy(sizePolicy)
|
||||
self.mainColorButton.setObjectName("mainColorButton")
|
||||
self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.mainColorButton)
|
||||
self.label_4 = QtWidgets.QLabel(QSpectrumAnalyzerColors)
|
||||
self.label_4.setObjectName("label_4")
|
||||
self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label_4)
|
||||
self.mainColorButton.setObjectName(_fromUtf8("mainColorButton"))
|
||||
self.formLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.mainColorButton)
|
||||
self.label_4 = QtGui.QLabel(QSpectrumAnalyzerColors)
|
||||
self.label_4.setObjectName(_fromUtf8("label_4"))
|
||||
self.formLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.label_4)
|
||||
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.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.peakHoldMaxColorButton.sizePolicy().hasHeightForWidth())
|
||||
self.peakHoldMaxColorButton.setSizePolicy(sizePolicy)
|
||||
self.peakHoldMaxColorButton.setObjectName("peakHoldMaxColorButton")
|
||||
self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.peakHoldMaxColorButton)
|
||||
self.label_6 = QtWidgets.QLabel(QSpectrumAnalyzerColors)
|
||||
self.label_6.setObjectName("label_6")
|
||||
self.formLayout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.label_6)
|
||||
self.peakHoldMaxColorButton.setObjectName(_fromUtf8("peakHoldMaxColorButton"))
|
||||
self.formLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.peakHoldMaxColorButton)
|
||||
self.label_6 = QtGui.QLabel(QSpectrumAnalyzerColors)
|
||||
self.label_6.setObjectName(_fromUtf8("label_6"))
|
||||
self.formLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.label_6)
|
||||
self.peakHoldMinColorButton = ColorButton(QSpectrumAnalyzerColors)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.peakHoldMinColorButton.sizePolicy().hasHeightForWidth())
|
||||
self.peakHoldMinColorButton.setSizePolicy(sizePolicy)
|
||||
self.peakHoldMinColorButton.setObjectName("peakHoldMinColorButton")
|
||||
self.formLayout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.peakHoldMinColorButton)
|
||||
self.label_5 = QtWidgets.QLabel(QSpectrumAnalyzerColors)
|
||||
self.label_5.setObjectName("label_5")
|
||||
self.formLayout.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.label_5)
|
||||
self.peakHoldMinColorButton.setObjectName(_fromUtf8("peakHoldMinColorButton"))
|
||||
self.formLayout.setWidget(2, QtGui.QFormLayout.FieldRole, self.peakHoldMinColorButton)
|
||||
self.label_5 = QtGui.QLabel(QSpectrumAnalyzerColors)
|
||||
self.label_5.setObjectName(_fromUtf8("label_5"))
|
||||
self.formLayout.setWidget(3, QtGui.QFormLayout.LabelRole, self.label_5)
|
||||
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.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.averageColorButton.sizePolicy().hasHeightForWidth())
|
||||
self.averageColorButton.setSizePolicy(sizePolicy)
|
||||
self.averageColorButton.setObjectName("averageColorButton")
|
||||
self.formLayout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.averageColorButton)
|
||||
self.label_3 = QtWidgets.QLabel(QSpectrumAnalyzerColors)
|
||||
self.label_3.setObjectName("label_3")
|
||||
self.formLayout.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.label_3)
|
||||
self.averageColorButton.setObjectName(_fromUtf8("averageColorButton"))
|
||||
self.formLayout.setWidget(3, QtGui.QFormLayout.FieldRole, self.averageColorButton)
|
||||
self.label_3 = QtGui.QLabel(QSpectrumAnalyzerColors)
|
||||
self.label_3.setObjectName(_fromUtf8("label_3"))
|
||||
self.formLayout.setWidget(4, QtGui.QFormLayout.LabelRole, self.label_3)
|
||||
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.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.persistenceColorButton.sizePolicy().hasHeightForWidth())
|
||||
self.persistenceColorButton.setSizePolicy(sizePolicy)
|
||||
self.persistenceColorButton.setObjectName("persistenceColorButton")
|
||||
self.formLayout.setWidget(4, QtWidgets.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.persistenceColorButton.setObjectName(_fromUtf8("persistenceColorButton"))
|
||||
self.formLayout.setWidget(4, QtGui.QFormLayout.FieldRole, self.persistenceColorButton)
|
||||
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.buttonBox = QtWidgets.QDialogButtonBox(QSpectrumAnalyzerColors)
|
||||
self.buttonBox = QtGui.QDialogButtonBox(QSpectrumAnalyzerColors)
|
||||
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
|
||||
self.buttonBox.setObjectName("buttonBox")
|
||||
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
|
||||
self.buttonBox.setObjectName(_fromUtf8("buttonBox"))
|
||||
self.verticalLayout.addWidget(self.buttonBox)
|
||||
self.label_2.setBuddy(self.mainColorButton)
|
||||
self.label_4.setBuddy(self.peakHoldMaxColorButton)
|
||||
self.label_6.setBuddy(self.peakHoldMinColorButton)
|
||||
self.label_5.setBuddy(self.averageColorButton)
|
||||
self.label_3.setBuddy(self.persistenceColorButton)
|
||||
self.label.setBuddy(self.baselineColorButton)
|
||||
|
||||
self.retranslateUi(QSpectrumAnalyzerColors)
|
||||
self.buttonBox.accepted.connect(QSpectrumAnalyzerColors.accept)
|
||||
self.buttonBox.rejected.connect(QSpectrumAnalyzerColors.reject)
|
||||
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), QSpectrumAnalyzerColors.accept)
|
||||
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), QSpectrumAnalyzerColors.reject)
|
||||
QtCore.QMetaObject.connectSlotsByName(QSpectrumAnalyzerColors)
|
||||
QSpectrumAnalyzerColors.setTabOrder(self.mainColorButton, self.peakHoldMaxColorButton)
|
||||
QSpectrumAnalyzerColors.setTabOrder(self.peakHoldMaxColorButton, self.peakHoldMinColorButton)
|
||||
QSpectrumAnalyzerColors.setTabOrder(self.peakHoldMinColorButton, self.averageColorButton)
|
||||
QSpectrumAnalyzerColors.setTabOrder(self.averageColorButton, self.persistenceColorButton)
|
||||
QSpectrumAnalyzerColors.setTabOrder(self.persistenceColorButton, self.baselineColorButton)
|
||||
QSpectrumAnalyzerColors.setTabOrder(self.persistenceColorButton, self.buttonBox)
|
||||
|
||||
def retranslateUi(self, QSpectrumAnalyzerColors):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
QSpectrumAnalyzerColors.setWindowTitle(_translate("QSpectrumAnalyzerColors", "Colors - QSpectrumAnalyzer"))
|
||||
self.label_2.setText(_translate("QSpectrumAnalyzerColors", "&Main curve color:"))
|
||||
self.mainColorButton.setText(_translate("QSpectrumAnalyzerColors", "..."))
|
||||
self.label_4.setText(_translate("QSpectrumAnalyzerColors", "Max. peak &hold color:"))
|
||||
self.peakHoldMaxColorButton.setText(_translate("QSpectrumAnalyzerColors", "..."))
|
||||
self.label_6.setText(_translate("QSpectrumAnalyzerColors", "M&in. peak hold color:"))
|
||||
self.peakHoldMinColorButton.setText(_translate("QSpectrumAnalyzerColors", "..."))
|
||||
self.label_5.setText(_translate("QSpectrumAnalyzerColors", "Average &color:"))
|
||||
self.averageColorButton.setText(_translate("QSpectrumAnalyzerColors", "..."))
|
||||
self.label_3.setText(_translate("QSpectrumAnalyzerColors", "Persistence co&lor:"))
|
||||
self.persistenceColorButton.setText(_translate("QSpectrumAnalyzerColors", "..."))
|
||||
self.label.setText(_translate("QSpectrumAnalyzerColors", "&Baseline color:"))
|
||||
self.baselineColorButton.setText(_translate("QSpectrumAnalyzerColors", "..."))
|
||||
QSpectrumAnalyzerColors.setWindowTitle(_translate("QSpectrumAnalyzerColors", "Colors - QSpectrumAnalyzer", None))
|
||||
self.label_2.setText(_translate("QSpectrumAnalyzerColors", "Main curve color:", None))
|
||||
self.mainColorButton.setText(_translate("QSpectrumAnalyzerColors", "...", None))
|
||||
self.label_4.setText(_translate("QSpectrumAnalyzerColors", "Max. peak hold color:", None))
|
||||
self.peakHoldMaxColorButton.setText(_translate("QSpectrumAnalyzerColors", "...", None))
|
||||
self.label_6.setText(_translate("QSpectrumAnalyzerColors", "Min. peak hold color:", None))
|
||||
self.peakHoldMinColorButton.setText(_translate("QSpectrumAnalyzerColors", "...", None))
|
||||
self.label_5.setText(_translate("QSpectrumAnalyzerColors", "Average color:", None))
|
||||
self.averageColorButton.setText(_translate("QSpectrumAnalyzerColors", "...", None))
|
||||
self.label_3.setText(_translate("QSpectrumAnalyzerColors", "Persistence color:", None))
|
||||
self.persistenceColorButton.setText(_translate("QSpectrumAnalyzerColors", "...", None))
|
||||
|
||||
from pyqtgraph import ColorButton
|
||||
|
@ -2,59 +2,72 @@
|
||||
|
||||
# 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!
|
||||
|
||||
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):
|
||||
def setupUi(self, QSpectrumAnalyzerPersistence):
|
||||
QSpectrumAnalyzerPersistence.setObjectName("QSpectrumAnalyzerPersistence")
|
||||
QSpectrumAnalyzerPersistence.setObjectName(_fromUtf8("QSpectrumAnalyzerPersistence"))
|
||||
QSpectrumAnalyzerPersistence.resize(250, 130)
|
||||
self.verticalLayout = QtWidgets.QVBoxLayout(QSpectrumAnalyzerPersistence)
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
self.formLayout = QtWidgets.QFormLayout()
|
||||
self.formLayout.setObjectName("formLayout")
|
||||
self.label_2 = QtWidgets.QLabel(QSpectrumAnalyzerPersistence)
|
||||
self.label_2.setObjectName("label_2")
|
||||
self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.label_2)
|
||||
self.decayFunctionComboBox = QtWidgets.QComboBox(QSpectrumAnalyzerPersistence)
|
||||
self.decayFunctionComboBox.setObjectName("decayFunctionComboBox")
|
||||
self.decayFunctionComboBox.addItem("")
|
||||
self.decayFunctionComboBox.addItem("")
|
||||
self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.decayFunctionComboBox)
|
||||
self.label = QtWidgets.QLabel(QSpectrumAnalyzerPersistence)
|
||||
self.label.setObjectName("label")
|
||||
self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label)
|
||||
self.persistenceLengthSpinBox = QtWidgets.QSpinBox(QSpectrumAnalyzerPersistence)
|
||||
self.verticalLayout = QtGui.QVBoxLayout(QSpectrumAnalyzerPersistence)
|
||||
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
|
||||
self.formLayout = QtGui.QFormLayout()
|
||||
self.formLayout.setObjectName(_fromUtf8("formLayout"))
|
||||
self.label_2 = QtGui.QLabel(QSpectrumAnalyzerPersistence)
|
||||
self.label_2.setObjectName(_fromUtf8("label_2"))
|
||||
self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.label_2)
|
||||
self.decayFunctionComboBox = QtGui.QComboBox(QSpectrumAnalyzerPersistence)
|
||||
self.decayFunctionComboBox.setObjectName(_fromUtf8("decayFunctionComboBox"))
|
||||
self.decayFunctionComboBox.addItem(_fromUtf8(""))
|
||||
self.decayFunctionComboBox.addItem(_fromUtf8(""))
|
||||
self.formLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.decayFunctionComboBox)
|
||||
self.label = QtGui.QLabel(QSpectrumAnalyzerPersistence)
|
||||
self.label.setObjectName(_fromUtf8("label"))
|
||||
self.formLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.label)
|
||||
self.persistenceLengthSpinBox = QtGui.QSpinBox(QSpectrumAnalyzerPersistence)
|
||||
self.persistenceLengthSpinBox.setProperty("value", 5)
|
||||
self.persistenceLengthSpinBox.setObjectName("persistenceLengthSpinBox")
|
||||
self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.persistenceLengthSpinBox)
|
||||
self.persistenceLengthSpinBox.setObjectName(_fromUtf8("persistenceLengthSpinBox"))
|
||||
self.formLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.persistenceLengthSpinBox)
|
||||
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.buttonBox = QtWidgets.QDialogButtonBox(QSpectrumAnalyzerPersistence)
|
||||
self.buttonBox = QtGui.QDialogButtonBox(QSpectrumAnalyzerPersistence)
|
||||
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
|
||||
self.buttonBox.setObjectName("buttonBox")
|
||||
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
|
||||
self.buttonBox.setObjectName(_fromUtf8("buttonBox"))
|
||||
self.verticalLayout.addWidget(self.buttonBox)
|
||||
self.label_2.setBuddy(self.decayFunctionComboBox)
|
||||
self.label.setBuddy(self.persistenceLengthSpinBox)
|
||||
|
||||
self.retranslateUi(QSpectrumAnalyzerPersistence)
|
||||
self.decayFunctionComboBox.setCurrentIndex(1)
|
||||
self.buttonBox.accepted.connect(QSpectrumAnalyzerPersistence.accept)
|
||||
self.buttonBox.rejected.connect(QSpectrumAnalyzerPersistence.reject)
|
||||
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), QSpectrumAnalyzerPersistence.accept)
|
||||
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), QSpectrumAnalyzerPersistence.reject)
|
||||
QtCore.QMetaObject.connectSlotsByName(QSpectrumAnalyzerPersistence)
|
||||
QSpectrumAnalyzerPersistence.setTabOrder(self.decayFunctionComboBox, self.persistenceLengthSpinBox)
|
||||
QSpectrumAnalyzerPersistence.setTabOrder(self.persistenceLengthSpinBox, self.buttonBox)
|
||||
|
||||
def retranslateUi(self, QSpectrumAnalyzerPersistence):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
QSpectrumAnalyzerPersistence.setWindowTitle(_translate("QSpectrumAnalyzerPersistence", "Persistence - QSpectrumAnalyzer"))
|
||||
self.label_2.setText(_translate("QSpectrumAnalyzerPersistence", "Decay function:"))
|
||||
self.decayFunctionComboBox.setItemText(0, _translate("QSpectrumAnalyzerPersistence", "linear"))
|
||||
self.decayFunctionComboBox.setItemText(1, _translate("QSpectrumAnalyzerPersistence", "exponential"))
|
||||
self.label.setText(_translate("QSpectrumAnalyzerPersistence", "Persistence length:"))
|
||||
QSpectrumAnalyzerPersistence.setWindowTitle(_translate("QSpectrumAnalyzerPersistence", "Persistence - QSpectrumAnalyzer", None))
|
||||
self.label_2.setText(_translate("QSpectrumAnalyzerPersistence", "Decay function:", None))
|
||||
self.decayFunctionComboBox.setItemText(0, _translate("QSpectrumAnalyzerPersistence", "linear", None))
|
||||
self.decayFunctionComboBox.setItemText(1, _translate("QSpectrumAnalyzerPersistence", "exponential", None))
|
||||
self.label.setText(_translate("QSpectrumAnalyzerPersistence", "Persistence length:", None))
|
||||
|
||||
|
@ -2,170 +2,119 @@
|
||||
|
||||
# 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!
|
||||
|
||||
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):
|
||||
def setupUi(self, QSpectrumAnalyzerSettings):
|
||||
QSpectrumAnalyzerSettings.setObjectName("QSpectrumAnalyzerSettings")
|
||||
QSpectrumAnalyzerSettings.resize(600, 388)
|
||||
self.verticalLayout = QtWidgets.QVBoxLayout(QSpectrumAnalyzerSettings)
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
self.formLayout = QtWidgets.QFormLayout()
|
||||
self.formLayout.setObjectName("formLayout")
|
||||
self.label_3 = QtWidgets.QLabel(QSpectrumAnalyzerSettings)
|
||||
self.label_3.setObjectName("label_3")
|
||||
self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.label_3)
|
||||
self.backendComboBox = QtWidgets.QComboBox(QSpectrumAnalyzerSettings)
|
||||
self.backendComboBox.setObjectName("backendComboBox")
|
||||
self.backendComboBox.addItem("")
|
||||
self.backendComboBox.addItem("")
|
||||
self.backendComboBox.addItem("")
|
||||
self.backendComboBox.addItem("")
|
||||
self.backendComboBox.addItem("")
|
||||
self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.backendComboBox)
|
||||
self.label = QtWidgets.QLabel(QSpectrumAnalyzerSettings)
|
||||
self.label.setObjectName("label")
|
||||
self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label)
|
||||
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
self.executableEdit = QtWidgets.QLineEdit(QSpectrumAnalyzerSettings)
|
||||
self.executableEdit.setObjectName("executableEdit")
|
||||
QSpectrumAnalyzerSettings.setObjectName(_fromUtf8("QSpectrumAnalyzerSettings"))
|
||||
QSpectrumAnalyzerSettings.resize(420, 255)
|
||||
self.verticalLayout = QtGui.QVBoxLayout(QSpectrumAnalyzerSettings)
|
||||
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
|
||||
self.formLayout = QtGui.QFormLayout()
|
||||
self.formLayout.setObjectName(_fromUtf8("formLayout"))
|
||||
self.label_3 = QtGui.QLabel(QSpectrumAnalyzerSettings)
|
||||
self.label_3.setObjectName(_fromUtf8("label_3"))
|
||||
self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.label_3)
|
||||
self.backendComboBox = QtGui.QComboBox(QSpectrumAnalyzerSettings)
|
||||
self.backendComboBox.setObjectName(_fromUtf8("backendComboBox"))
|
||||
self.backendComboBox.addItem(_fromUtf8(""))
|
||||
self.backendComboBox.addItem(_fromUtf8(""))
|
||||
self.backendComboBox.addItem(_fromUtf8(""))
|
||||
self.backendComboBox.addItem(_fromUtf8(""))
|
||||
self.backendComboBox.addItem(_fromUtf8(""))
|
||||
self.formLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.backendComboBox)
|
||||
self.label = QtGui.QLabel(QSpectrumAnalyzerSettings)
|
||||
self.label.setObjectName(_fromUtf8("label"))
|
||||
self.formLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.label)
|
||||
self.horizontalLayout = QtGui.QHBoxLayout()
|
||||
self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
|
||||
self.executableEdit = QtGui.QLineEdit(QSpectrumAnalyzerSettings)
|
||||
self.executableEdit.setObjectName(_fromUtf8("executableEdit"))
|
||||
self.horizontalLayout.addWidget(self.executableEdit)
|
||||
self.executableButton = QtWidgets.QToolButton(QSpectrumAnalyzerSettings)
|
||||
self.executableButton.setMinimumSize(QtCore.QSize(50, 0))
|
||||
self.executableButton.setObjectName("executableButton")
|
||||
self.executableButton = QtGui.QToolButton(QSpectrumAnalyzerSettings)
|
||||
self.executableButton.setObjectName(_fromUtf8("executableButton"))
|
||||
self.horizontalLayout.addWidget(self.executableButton)
|
||||
self.formLayout.setLayout(1, QtWidgets.QFormLayout.FieldRole, self.horizontalLayout)
|
||||
self.label_5 = QtWidgets.QLabel(QSpectrumAnalyzerSettings)
|
||||
self.label_5.setObjectName("label_5")
|
||||
self.formLayout.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.label_5)
|
||||
self.label_4 = QtWidgets.QLabel(QSpectrumAnalyzerSettings)
|
||||
self.label_4.setObjectName("label_4")
|
||||
self.formLayout.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.label_4)
|
||||
self.label_2 = QtWidgets.QLabel(QSpectrumAnalyzerSettings)
|
||||
self.label_2.setObjectName("label_2")
|
||||
self.formLayout.setWidget(7, QtWidgets.QFormLayout.LabelRole, self.label_2)
|
||||
self.waterfallHistorySizeSpinBox = QtWidgets.QSpinBox(QSpectrumAnalyzerSettings)
|
||||
self.formLayout.setLayout(1, QtGui.QFormLayout.FieldRole, self.horizontalLayout)
|
||||
self.label_5 = QtGui.QLabel(QSpectrumAnalyzerSettings)
|
||||
self.label_5.setObjectName(_fromUtf8("label_5"))
|
||||
self.formLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.label_5)
|
||||
self.deviceEdit = QtGui.QLineEdit(QSpectrumAnalyzerSettings)
|
||||
self.deviceEdit.setObjectName(_fromUtf8("deviceEdit"))
|
||||
self.formLayout.setWidget(2, QtGui.QFormLayout.FieldRole, self.deviceEdit)
|
||||
self.label_4 = QtGui.QLabel(QSpectrumAnalyzerSettings)
|
||||
self.label_4.setObjectName(_fromUtf8("label_4"))
|
||||
self.formLayout.setWidget(3, QtGui.QFormLayout.LabelRole, self.label_4)
|
||||
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.setMaximum(10000000)
|
||||
self.waterfallHistorySizeSpinBox.setProperty("value", 100)
|
||||
self.waterfallHistorySizeSpinBox.setObjectName("waterfallHistorySizeSpinBox")
|
||||
self.formLayout.setWidget(7, QtWidgets.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.waterfallHistorySizeSpinBox.setObjectName(_fromUtf8("waterfallHistorySizeSpinBox"))
|
||||
self.formLayout.setWidget(4, QtGui.QFormLayout.FieldRole, self.waterfallHistorySizeSpinBox)
|
||||
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.buttonBox = QtWidgets.QDialogButtonBox(QSpectrumAnalyzerSettings)
|
||||
self.buttonBox = QtGui.QDialogButtonBox(QSpectrumAnalyzerSettings)
|
||||
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
|
||||
self.buttonBox.setObjectName("buttonBox")
|
||||
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
|
||||
self.buttonBox.setObjectName(_fromUtf8("buttonBox"))
|
||||
self.verticalLayout.addWidget(self.buttonBox)
|
||||
self.label_3.setBuddy(self.backendComboBox)
|
||||
self.label.setBuddy(self.executableEdit)
|
||||
self.label_5.setBuddy(self.deviceEdit)
|
||||
self.label_4.setBuddy(self.sampleRateSpinBox)
|
||||
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.buttonBox.accepted.connect(QSpectrumAnalyzerSettings.accept)
|
||||
self.buttonBox.rejected.connect(QSpectrumAnalyzerSettings.reject)
|
||||
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), QSpectrumAnalyzerSettings.accept)
|
||||
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), QSpectrumAnalyzerSettings.reject)
|
||||
QtCore.QMetaObject.connectSlotsByName(QSpectrumAnalyzerSettings)
|
||||
QSpectrumAnalyzerSettings.setTabOrder(self.backendComboBox, self.executableEdit)
|
||||
QSpectrumAnalyzerSettings.setTabOrder(self.executableEdit, self.executableButton)
|
||||
QSpectrumAnalyzerSettings.setTabOrder(self.executableButton, self.paramsEdit)
|
||||
QSpectrumAnalyzerSettings.setTabOrder(self.paramsEdit, self.paramsHelpButton)
|
||||
QSpectrumAnalyzerSettings.setTabOrder(self.paramsHelpButton, self.deviceEdit)
|
||||
QSpectrumAnalyzerSettings.setTabOrder(self.deviceEdit, self.deviceHelpButton)
|
||||
QSpectrumAnalyzerSettings.setTabOrder(self.deviceHelpButton, self.sampleRateSpinBox)
|
||||
QSpectrumAnalyzerSettings.setTabOrder(self.sampleRateSpinBox, self.bandwidthSpinBox)
|
||||
QSpectrumAnalyzerSettings.setTabOrder(self.bandwidthSpinBox, self.lnbSpinBox)
|
||||
QSpectrumAnalyzerSettings.setTabOrder(self.lnbSpinBox, self.waterfallHistorySizeSpinBox)
|
||||
QSpectrumAnalyzerSettings.setTabOrder(self.executableButton, self.deviceEdit)
|
||||
QSpectrumAnalyzerSettings.setTabOrder(self.deviceEdit, self.sampleRateSpinBox)
|
||||
QSpectrumAnalyzerSettings.setTabOrder(self.sampleRateSpinBox, self.waterfallHistorySizeSpinBox)
|
||||
QSpectrumAnalyzerSettings.setTabOrder(self.waterfallHistorySizeSpinBox, self.buttonBox)
|
||||
|
||||
def retranslateUi(self, QSpectrumAnalyzerSettings):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
QSpectrumAnalyzerSettings.setWindowTitle(_translate("QSpectrumAnalyzerSettings", "Settings - QSpectrumAnalyzer"))
|
||||
self.label_3.setText(_translate("QSpectrumAnalyzerSettings", "&Backend:"))
|
||||
self.backendComboBox.setItemText(0, _translate("QSpectrumAnalyzerSettings", "soapy_power"))
|
||||
self.backendComboBox.setItemText(1, _translate("QSpectrumAnalyzerSettings", "rx_power"))
|
||||
self.backendComboBox.setItemText(2, _translate("QSpectrumAnalyzerSettings", "rtl_power_fftw"))
|
||||
self.backendComboBox.setItemText(3, _translate("QSpectrumAnalyzerSettings", "rtl_power"))
|
||||
self.backendComboBox.setItemText(4, _translate("QSpectrumAnalyzerSettings", "hackrf_sweep"))
|
||||
self.label.setText(_translate("QSpectrumAnalyzerSettings", "E&xecutable:"))
|
||||
self.executableEdit.setText(_translate("QSpectrumAnalyzerSettings", "soapy_power"))
|
||||
self.executableButton.setText(_translate("QSpectrumAnalyzerSettings", "..."))
|
||||
self.label_5.setText(_translate("QSpectrumAnalyzerSettings", "&Device:"))
|
||||
self.label_4.setText(_translate("QSpectrumAnalyzerSettings", "Sa&mple rate:"))
|
||||
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"))
|
||||
QSpectrumAnalyzerSettings.setWindowTitle(_translate("QSpectrumAnalyzerSettings", "Settings - QSpectrumAnalyzer", None))
|
||||
self.label_3.setText(_translate("QSpectrumAnalyzerSettings", "&Backend:", None))
|
||||
self.backendComboBox.setItemText(0, _translate("QSpectrumAnalyzerSettings", "soapy_power", None))
|
||||
self.backendComboBox.setItemText(1, _translate("QSpectrumAnalyzerSettings", "rx_power", None))
|
||||
self.backendComboBox.setItemText(2, _translate("QSpectrumAnalyzerSettings", "rtl_power_fftw", None))
|
||||
self.backendComboBox.setItemText(3, _translate("QSpectrumAnalyzerSettings", "rtl_power", None))
|
||||
self.backendComboBox.setItemText(4, _translate("QSpectrumAnalyzerSettings", "hackrf_sweep", None))
|
||||
self.label.setText(_translate("QSpectrumAnalyzerSettings", "E&xecutable:", None))
|
||||
self.executableEdit.setText(_translate("QSpectrumAnalyzerSettings", "soapy_power", None))
|
||||
self.executableButton.setText(_translate("QSpectrumAnalyzerSettings", "...", None))
|
||||
self.label_5.setText(_translate("QSpectrumAnalyzerSettings", "Device:", None))
|
||||
self.label_4.setText(_translate("QSpectrumAnalyzerSettings", "Sa&mple rate:", None))
|
||||
self.label_2.setText(_translate("QSpectrumAnalyzerSettings", "&Waterfall history size:", None))
|
||||
|
||||
|
@ -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"))
|
||||
|
81
qspectrumanalyzer/ui_qspectrumanalyzer_smooth.py
Normal file
81
qspectrumanalyzer/ui_qspectrumanalyzer_smooth.py
Normal 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>h:", None))
|
||||
|
@ -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>h:"))
|
||||
|
@ -1,6 +1,6 @@
|
||||
import numpy as np
|
||||
|
||||
from Qt import QtGui
|
||||
from PyQt4 import QtGui
|
||||
|
||||
|
||||
def smooth(x, window_len=11, window='hanning'):
|
||||
@ -35,19 +35,3 @@ def str_to_color(color_string):
|
||||
def color_to_str(color):
|
||||
"""Create comma separated RGBA string from QColor"""
|
||||
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
|
||||
|
@ -1 +1 @@
|
||||
__version__ = "2.2.0"
|
||||
__version__ = "1.4.0"
|
||||
|
@ -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
26
setup-qt.py
Executable 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))
|
82
setup.py
82
setup.py
@ -1,90 +1,36 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import setuptools
|
||||
from setuptools import setup
|
||||
|
||||
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(
|
||||
name="QSpectrumAnalyzer",
|
||||
version=__version__,
|
||||
description=("Spectrum analyzer for multiple SDR platforms "
|
||||
"(PyQtGraph based GUI for soapy_power, hackrf_sweep, rtl_power, rx_power and other backends)"),
|
||||
long_description=open('README.rst').read(),
|
||||
description="Spectrum analyzer for RTL-SDR (GUI for rtl_power based on PyQtGraph)",
|
||||
author="Michal Krenek (Mikos)",
|
||||
author_email="m.krenek@gmail.com",
|
||||
url="https://github.com/xmikos/qspectrumanalyzer",
|
||||
license="GNU GPLv3",
|
||||
packages=["qspectrumanalyzer", "qspectrumanalyzer.backends"],
|
||||
packages=["qspectrumanalyzer"],
|
||||
package_data={
|
||||
"qspectrumanalyzer": [
|
||||
"qspectrumanalyzer.svg",
|
||||
"*.ui",
|
||||
"languages/*.qm",
|
||||
"languages/*.ts",
|
||||
],
|
||||
"languages/*.ts"
|
||||
]
|
||||
},
|
||||
data_files=[
|
||||
("share/applications", ["qspectrumanalyzer.desktop"]),
|
||||
("share/pixmaps", ["qspectrumanalyzer.png"]),
|
||||
("share/pixmaps", ["qspectrumanalyzer.png"])
|
||||
],
|
||||
entry_points={
|
||||
"gui_scripts": [
|
||||
"qspectrumanalyzer=qspectrumanalyzer.__main__:main"
|
||||
],
|
||||
},
|
||||
install_requires=[
|
||||
"soapy_power>=1.6.0",
|
||||
"pyqtgraph>=0.10.0",
|
||||
"Qt.py",
|
||||
"pyqtgraph"
|
||||
],
|
||||
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',
|
||||
],
|
||||
},
|
||||
},
|
||||
classifiers=[
|
||||
"Development Status :: 4 - Beta",
|
||||
"Environment :: MacOS X",
|
||||
@ -98,8 +44,6 @@ setup(
|
||||
"Operating System :: OS Independent",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Topic :: Communications :: Ham Radio",
|
||||
"Topic :: Scientific/Engineering :: Visualization",
|
||||
],
|
||||
entry_points=setup_entry_points,
|
||||
cmdclass=setup_cmdclass,
|
||||
"Topic :: Scientific/Engineering :: Visualization"
|
||||
]
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user