Compare commits
57 Commits
hackrf_swe
...
master
Author | SHA1 | Date | |
---|---|---|---|
![]() |
625ba9d698 | ||
![]() |
6800f5bd8e | ||
![]() |
4571075bd9 | ||
![]() |
5505f0dfd7 | ||
![]() |
2544b9a164 | ||
![]() |
8aa6d50bb8 | ||
![]() |
31471b3386 | ||
![]() |
1c9e7681b8 | ||
![]() |
edf8ae17e2 | ||
![]() |
c6e305343c | ||
![]() |
c140e9313e | ||
![]() |
c93bbf3de5 | ||
![]() |
36be8e8371 | ||
![]() |
06956c4c1f | ||
![]() |
9b04a924f2 | ||
![]() |
415687685a | ||
![]() |
9d21d49157 | ||
![]() |
e9391aedc0 | ||
![]() |
05f4a59b66 | ||
![]() |
fa462f885d | ||
![]() |
9ee6f631dc | ||
![]() |
9271e42766 | ||
![]() |
e75f9a98d9 | ||
![]() |
5985cb4bfe | ||
![]() |
bc3319ba82 | ||
![]() |
a49f1a3187 | ||
![]() |
12da1d6626 | ||
![]() |
9dc1433bdf | ||
![]() |
8109c537f6 | ||
![]() |
87585c106b | ||
![]() |
02859deccf | ||
![]() |
2385c228c6 | ||
![]() |
11979ba641 | ||
![]() |
9135dc58e4 | ||
![]() |
92e1771db5 | ||
![]() |
8ac3346c1e | ||
![]() |
7e84cd7a1c | ||
![]() |
5d41c6c4a8 | ||
![]() |
07d504ab30 | ||
![]() |
d8d158c100 | ||
![]() |
c574761a8c | ||
![]() |
ea969b89e2 | ||
![]() |
b8666417b0 | ||
![]() |
e0f7202ff9 | ||
![]() |
9de4c25269 | ||
![]() |
50ff8d517d | ||
![]() |
58ea054d70 | ||
![]() |
228255b7e1 | ||
![]() |
d1c6ca4d14 | ||
![]() |
47ea0b99b5 | ||
![]() |
dc27e90653 | ||
![]() |
e7b998f69d | ||
![]() |
98a8b6bd1d | ||
![]() |
e9264886e8 | ||
![]() |
d351a858da | ||
![]() |
e73e921440 | ||
![]() |
7fa0985133 |
@ -2,4 +2,3 @@ include LICENSE
|
|||||||
include README.rst
|
include README.rst
|
||||||
include qspectrumanalyzer.desktop
|
include qspectrumanalyzer.desktop
|
||||||
include qspectrumanalyzer.png
|
include qspectrumanalyzer.png
|
||||||
include qspectrumanalyzer.svg
|
|
||||||
|
14
PKGBUILD
14
PKGBUILD
@ -1,14 +1,20 @@
|
|||||||
# Maintainer: Michal Krenek (Mikos) <m.krenek@gmail.com>
|
# Maintainer: Michal Krenek (Mikos) <m.krenek@gmail.com>
|
||||||
pkgname=qspectrumanalyzer
|
pkgname=qspectrumanalyzer
|
||||||
pkgver=1.4.0
|
pkgver=2.2.0
|
||||||
pkgrel=1
|
pkgrel=1
|
||||||
pkgdesc="Spectrum analyzer for RTL-SDR (GUI for rtl_power based on PyQtGraph)"
|
pkgdesc="Spectrum analyzer for multiple SDR platforms (PyQtGraph based GUI for soapy_power, hackrf_sweep, rtl_power, rx_power and other backends)"
|
||||||
arch=('any')
|
arch=('any')
|
||||||
url="https://github.com/xmikos/qspectrumanalyzer"
|
url="https://github.com/xmikos/qspectrumanalyzer"
|
||||||
license=('GPL3')
|
license=('GPL3')
|
||||||
depends=('python-pyqt4' 'python-pyqtgraph' 'rtl-sdr')
|
depends=('python-qt.py' 'python-pyqt5' 'python-pyqtgraph' 'soapy_power>=1.6.0')
|
||||||
makedepends=('python-setuptools')
|
makedepends=('python-setuptools')
|
||||||
optdepends=('rtl_power_fftw-git: alternative rtl_power implementation using FFTW library')
|
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)'
|
||||||
|
)
|
||||||
source=(https://github.com/xmikos/qspectrumanalyzer/archive/v$pkgver.tar.gz)
|
source=(https://github.com/xmikos/qspectrumanalyzer/archive/v$pkgver.tar.gz)
|
||||||
|
|
||||||
build() {
|
build() {
|
||||||
|
155
README.rst
155
README.rst
@ -1,7 +1,8 @@
|
|||||||
QSpectrumAnalyzer
|
QSpectrumAnalyzer
|
||||||
=================
|
=================
|
||||||
|
|
||||||
Spectrum analyzer for RTL-SDR (GUI for rtl_power based on PyQtGraph)
|
Spectrum analyzer for multiple SDR platforms (PyQtGraph based GUI for soapy_power,
|
||||||
|
hackrf_sweep, rtl_power, rx_power and other backends)
|
||||||
|
|
||||||
Screenshots
|
Screenshots
|
||||||
-----------
|
-----------
|
||||||
@ -14,37 +15,73 @@ Requirements
|
|||||||
------------
|
------------
|
||||||
|
|
||||||
- Python >= 3.3
|
- Python >= 3.3
|
||||||
- PyQt >= 4.5
|
- PyQt4 / PyQt5 / PySide / PySide2
|
||||||
|
- Qt.py (https://github.com/mottosso/Qt.py)
|
||||||
- PyQtGraph (http://www.pyqtgraph.org)
|
- PyQtGraph (http://www.pyqtgraph.org)
|
||||||
- rtl-sdr (https://github.com/keenerd/rtl-sdr)
|
- soapy_power (https://github.com/xmikos/soapy_power)
|
||||||
- Optional: rtl_power_fftw (https://github.com/AD-Vega/rtl-power-fftw)
|
- Optional: hackrf / rtl-sdr / rtl_power_fftw / rx_tools
|
||||||
|
|
||||||
You should use `Keenerds fork of rtl-sdr <https://github.com/keenerd/rtl-sdr>`_
|
Backends
|
||||||
(latest Git revision), because ``rtl_power`` in original rtl-sdr (from osmocom.org)
|
--------
|
||||||
|
|
||||||
|
Default backend
|
||||||
|
***************
|
||||||
|
|
||||||
|
- **soapy_power** (https://github.com/xmikos/soapy_power)
|
||||||
|
|
||||||
|
``soapy_power`` is the default and recommended universal SDR backend in QSpectrumAnalyzer.
|
||||||
|
It is based on `SoapySDR <https://github.com/pothosware/SoapySDR>`_ and supports
|
||||||
|
nearly all SDR platforms (RTL-SDR, HackRF, Airspy, SDRplay, LimeSDR, bladeRF,
|
||||||
|
USRP and some other SDR devices). It is highly configurable (see additional parameters
|
||||||
|
help in *Settings* menu) and supports short acquisition time for
|
||||||
|
near real-time continuous measurement.
|
||||||
|
|
||||||
|
Other backends
|
||||||
|
**************
|
||||||
|
|
||||||
|
- **hackrf_sweep** (https://github.com/mossmann/hackrf)
|
||||||
|
|
||||||
|
``hackrf_sweep`` backend enables wideband spectrum monitoring by rapidly retuning the radio
|
||||||
|
without requiring individual tuning requests from the host computer. This allows unprecedented
|
||||||
|
sweep rate of 8 GHz per second. Only HackRF is supported.
|
||||||
|
|
||||||
|
- **rtl_power_fftw** (https://github.com/AD-Vega/rtl-power-fftw)
|
||||||
|
|
||||||
|
``rtl_power_fftw`` is alternative backend for RTL-SDR devices and has various
|
||||||
|
benefits over ``rtl_power``. E.g. better FFT performance (thanks to
|
||||||
|
use of ``fftw`` library) and possibility to use short acquisition time
|
||||||
|
for near real-time continuous measurement (minimum interval in original
|
||||||
|
``rtl_power`` is 1 second).
|
||||||
|
|
||||||
|
- **rtl_power** (https://github.com/keenerd/rtl-sdr)
|
||||||
|
|
||||||
|
``rtl_power`` is original backend for RTL-SDR devices. There are better alternatives now, but
|
||||||
|
if you want to use it, you should use `Keenerds fork of rtl-sdr <https://github.com/keenerd/rtl-sdr>`_
|
||||||
|
(latest Git revision), because ``rtl_power`` in original rtl-sdr package (from osmocom.org)
|
||||||
is broken (especially when used with cropping).
|
is broken (especially when used with cropping).
|
||||||
|
|
||||||
Another alternative is
|
- **rx_power** (https://github.com/rxseger/rx_tools) *[unsupported]*
|
||||||
`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
|
``rx_power`` (part of ``rx_tools``) is also based on SoapySDR (like default ``soapy_power`` backend)
|
||||||
use of ``fftw`` library) and possibility to use much shorter acquisition time
|
and therefore supports nearly all SDR platforms. But it is much slower than soapy_power, doesn't support
|
||||||
for more real-time continuous measurement (minimum interval in original
|
near real-time continuous measurement (minimum interval is 1 second, same as ``rtl_power``)
|
||||||
``rtl_power`` is 1 second, but in ``rtl_power_fftw`` you are only limited
|
and is buggy. Backend is currently unsupported, if you want to fix it, patches are welcome.
|
||||||
by number of frequency hops).
|
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
-----
|
-----
|
||||||
|
|
||||||
Start QSpectrumAnalyzer by running ``qspectrumanalyzer``.
|
Start QSpectrumAnalyzer by running ``qspectrumanalyzer``.
|
||||||
|
|
||||||
You can choose if you want to use ``rtl_power`` or ``rtl_power_fftw`` backend in
|
You can choose which backend you want to use in *File* -> *Settings*
|
||||||
*File* -> *Settings* (default is ``rtl_power``). Path to ``rtl_power``
|
(or *Application menu* -> *Preferences* on Mac OS X), default is
|
||||||
(or ``rtl_power_fftw``) executable can be also manually specified there. You can also
|
``soapy_power``. Device, sample rate, bandwidth, LNB LO, path to backend executable
|
||||||
set waterfall plot history size in there. Default is 100 lines, be aware that
|
and additional backend parameters can be also manually specified there. You can
|
||||||
really large sweeps (with a lot of bins) would require a lot of system memory, so
|
also set waterfall plot history size. Default is 100 lines, be aware that
|
||||||
don't make this number too big.
|
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
|
Controls should be intuitive, but if you want consistent results, you should
|
||||||
turn off automatic gain control (set it to some fixed number) and also set
|
turn off automatic gain control (set gain to some fixed number) and also set
|
||||||
crop to 20% or more. For finding out ppm correction factor for your rtl-sdr
|
crop to 20% or more. For finding out ppm correction factor for your rtl-sdr
|
||||||
stick, use `kalibrate-rtl <https://github.com/steve-m/kalibrate-rtl>`_.
|
stick, use `kalibrate-rtl <https://github.com/steve-m/kalibrate-rtl>`_.
|
||||||
|
|
||||||
@ -55,39 +92,93 @@ table can be changed in mini-histogram widget (on *Levels* tab).
|
|||||||
Installation
|
Installation
|
||||||
------------
|
------------
|
||||||
|
|
||||||
**Arch Linux:**
|
Arch Linux:
|
||||||
|
***********
|
||||||
|
|
||||||
|
Stable version:
|
||||||
::
|
::
|
||||||
|
|
||||||
git clone https://aur.archlinux.org/qspectrumanalyzer.git
|
git clone https://aur.archlinux.org/qspectrumanalyzer.git
|
||||||
cd qspectrumanalyzer
|
cd qspectrumanalyzer
|
||||||
makepkg -sri
|
makepkg -sri
|
||||||
|
|
||||||
Or simply use `pacaur <https://aur.archlinux.org/packages/pacaur>`_ (or any other AUR helper):
|
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:
|
||||||
::
|
::
|
||||||
|
|
||||||
pacaur -S qspectrumanalyzer
|
pacaur -S qspectrumanalyzer
|
||||||
|
pacaur -S qspectrumanalyzer-git
|
||||||
|
|
||||||
**Debian / Ubuntu:**
|
Ubuntu:
|
||||||
|
*******
|
||||||
::
|
::
|
||||||
|
|
||||||
sudo apt-get install python3-pip python3-pyqt4 python3-numpy
|
# Add SoapySDR PPA to your system
|
||||||
sudo pip3 install qspectrumanalyzer
|
sudo add-apt-repository -y ppa:myriadrf/drivers
|
||||||
|
|
||||||
Warning! ``pip`` will install packages system-wide by default, but you
|
# Update list of packages
|
||||||
should always use your distribution package manager for this.
|
sudo apt-get update
|
||||||
|
|
||||||
You can install it locally only for your current user by running this (without ``sudo``):
|
# Install basic dependencies
|
||||||
::
|
sudo apt-get install python3-pip python3-pyqt5 python3-numpy python3-scipy soapysdr python3-soapysdr
|
||||||
|
|
||||||
|
# Install SoapySDR drivers for your hardware (e.g. RTL-SDR, Airspy, HackRF, LimeSDR, etc.)
|
||||||
|
sudo apt-get install soapysdr-module-rtlsdr soapysdr-module-airspy soapysdr-module-hackrf soapysdr-module-lms7
|
||||||
|
|
||||||
|
# Install QSpectrumAnalyzer locally for your current user
|
||||||
pip3 install --user qspectrumanalyzer
|
pip3 install --user qspectrumanalyzer
|
||||||
|
|
||||||
Executables will be then placed in ``~/.local/bin`` directory, you can add it to your
|
``qspectrumanalyzer`` and ``soapy_power`` executables will be then placed in
|
||||||
PATH in ``~/.bashrc``.
|
``~/.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).
|
||||||
|
|
||||||
Todo:
|
Todo:
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
- save FFT history (allow big waterfall plot saved to file)
|
||||||
- automatic peak detection / highlighting
|
- automatic peak detection / highlighting
|
||||||
- display average noise level
|
- display average noise level
|
||||||
- frequency markers / bookmarks with notes (even importing / exporting .csv file with
|
- frequency markers / bookmarks with notes (even importing and exporting .csv file with
|
||||||
predefined channels, etc.)
|
predefined channels, etc.)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[Desktop Entry]
|
[Desktop Entry]
|
||||||
Name=QSpectrumAnalyzer
|
Name=QSpectrumAnalyzer
|
||||||
GenericName=Spectrum analyzer
|
GenericName=Spectrum analyzer
|
||||||
Comment=Spectrum analyzer for RTL-SDR (GUI for rtl_power based on PyQtGraph)
|
Comment=Spectrum analyzer for multiple SDR platforms (PyQtGraph based GUI for soapy_power, hackrf_sweep, rtl_power, rx_power and other backends)
|
||||||
Exec=qspectrumanalyzer
|
Exec=qspectrumanalyzer
|
||||||
Icon=qspectrumanalyzer
|
Icon=qspectrumanalyzer
|
||||||
StartupNotify=true
|
StartupNotify=true
|
||||||
|
BIN
qspectrumanalyzer.ico
Normal file
BIN
qspectrumanalyzer.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
483
qspectrumanalyzer/__main__.py
Executable file → Normal file
483
qspectrumanalyzer/__main__.py
Executable file → Normal file
@ -1,167 +1,47 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
import sys, signal, time
|
import sys, os, signal, time, argparse
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from Qt import QtCore, QtGui, QtWidgets
|
||||||
|
|
||||||
|
from qspectrumanalyzer import backends
|
||||||
from qspectrumanalyzer.version import __version__
|
from qspectrumanalyzer.version import __version__
|
||||||
from qspectrumanalyzer.backend import RtlPowerThread, RtlPowerFftwThread, SoapyPowerThread, RxPowerThread, HackRFSweepThread
|
|
||||||
from qspectrumanalyzer.data import DataStorage
|
from qspectrumanalyzer.data import DataStorage
|
||||||
from qspectrumanalyzer.plot import SpectrumPlotWidget, WaterfallPlotWidget
|
from qspectrumanalyzer.plot import SpectrumPlotWidget, WaterfallPlotWidget
|
||||||
from qspectrumanalyzer.utils import color_to_str, str_to_color
|
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.ui_qspectrumanalyzer_settings import Ui_QSpectrumAnalyzerSettings
|
|
||||||
from qspectrumanalyzer.ui_qspectrumanalyzer_smooth import Ui_QSpectrumAnalyzerSmooth
|
|
||||||
from qspectrumanalyzer.ui_qspectrumanalyzer_persistence import Ui_QSpectrumAnalyzerPersistence
|
|
||||||
from qspectrumanalyzer.ui_qspectrumanalyzer_colors import Ui_QSpectrumAnalyzerColors
|
|
||||||
from qspectrumanalyzer.ui_qspectrumanalyzer import Ui_QSpectrumAnalyzerMainWindow
|
from qspectrumanalyzer.ui_qspectrumanalyzer import Ui_QSpectrumAnalyzerMainWindow
|
||||||
|
|
||||||
|
debug = False
|
||||||
|
|
||||||
# Allow CTRL+C and/or SIGTERM to kill us (PyQt blocks it otherwise)
|
# Allow CTRL+C and/or SIGTERM to kill us (PyQt blocks it otherwise)
|
||||||
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
||||||
signal.signal(signal.SIGTERM, signal.SIG_DFL)
|
signal.signal(signal.SIGTERM, signal.SIG_DFL)
|
||||||
|
|
||||||
|
|
||||||
class QSpectrumAnalyzerSettings(QtGui.QDialog, Ui_QSpectrumAnalyzerSettings):
|
class QSpectrumAnalyzerMainWindow(QtWidgets.QMainWindow, Ui_QSpectrumAnalyzerMainWindow):
|
||||||
"""QSpectrumAnalyzer settings dialog"""
|
|
||||||
def __init__(self, parent=None):
|
|
||||||
# Initialize UI
|
|
||||||
super().__init__(parent)
|
|
||||||
self.setupUi(self)
|
|
||||||
|
|
||||||
# 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))
|
|
||||||
|
|
||||||
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"""
|
"""QSpectrumAnalyzer main window"""
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
# Initialize UI
|
# Initialize UI
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
|
|
||||||
|
# Set window icon
|
||||||
|
icon_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "qspectrumanalyzer.svg")
|
||||||
|
self.setWindowIcon(QtGui.QIcon(icon_path))
|
||||||
|
|
||||||
|
# Create progress bar
|
||||||
|
self.progressbar = QtWidgets.QProgressBar()
|
||||||
|
self.progressbar.setMaximumWidth(250)
|
||||||
|
self.progressbar.setVisible(False)
|
||||||
|
self.statusbar.addPermanentWidget(self.progressbar)
|
||||||
|
|
||||||
# Create plot widgets and update UI
|
# Create plot widgets and update UI
|
||||||
self.spectrumPlotWidget = SpectrumPlotWidget(self.mainPlotLayout)
|
self.spectrumPlotWidget = SpectrumPlotWidget(self.mainPlotLayout)
|
||||||
self.waterfallPlotWidget = WaterfallPlotWidget(self.waterfallPlotLayout, self.histogramPlotLayout)
|
self.waterfallPlotWidget = WaterfallPlotWidget(self.waterfallPlotLayout, self.histogramPlotLayout)
|
||||||
@ -170,9 +50,14 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin
|
|||||||
self.spectrumPlotWidget.plot.setXLink(self.waterfallPlotWidget.plot)
|
self.spectrumPlotWidget.plot.setXLink(self.waterfallPlotWidget.plot)
|
||||||
|
|
||||||
# Setup power thread and connect signals
|
# Setup power thread and connect signals
|
||||||
|
self.update_status_timer = QtCore.QTimer()
|
||||||
|
self.update_status_timer.timeout.connect(self.update_status)
|
||||||
|
self.prev_sweep_time = None
|
||||||
self.prev_data_timestamp = None
|
self.prev_data_timestamp = None
|
||||||
|
self.start_timestamp = None
|
||||||
self.data_storage = None
|
self.data_storage = None
|
||||||
self.power_thread = None
|
self.power_thread = None
|
||||||
|
self.backend = None
|
||||||
self.setup_power_thread()
|
self.setup_power_thread()
|
||||||
|
|
||||||
self.update_buttons()
|
self.update_buttons()
|
||||||
@ -191,45 +76,66 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin
|
|||||||
self.data_storage.data_recalculated.connect(self.spectrumPlotWidget.recalculate_plot)
|
self.data_storage.data_recalculated.connect(self.spectrumPlotWidget.recalculate_plot)
|
||||||
self.data_storage.data_recalculated.connect(self.spectrumPlotWidget.recalculate_persistence)
|
self.data_storage.data_recalculated.connect(self.spectrumPlotWidget.recalculate_persistence)
|
||||||
self.data_storage.history_updated.connect(self.waterfallPlotWidget.update_plot)
|
self.data_storage.history_updated.connect(self.waterfallPlotWidget.update_plot)
|
||||||
|
self.data_storage.history_recalculated.connect(self.waterfallPlotWidget.recalculate_plot)
|
||||||
self.data_storage.average_updated.connect(self.spectrumPlotWidget.update_average)
|
self.data_storage.average_updated.connect(self.spectrumPlotWidget.update_average)
|
||||||
|
self.data_storage.baseline_updated.connect(self.spectrumPlotWidget.update_baseline)
|
||||||
self.data_storage.peak_hold_max_updated.connect(self.spectrumPlotWidget.update_peak_hold_max)
|
self.data_storage.peak_hold_max_updated.connect(self.spectrumPlotWidget.update_peak_hold_max)
|
||||||
self.data_storage.peak_hold_min_updated.connect(self.spectrumPlotWidget.update_peak_hold_min)
|
self.data_storage.peak_hold_min_updated.connect(self.spectrumPlotWidget.update_peak_hold_min)
|
||||||
|
|
||||||
|
# Setup default values and limits in case that backend is changed
|
||||||
backend = settings.value("backend", "soapy_power")
|
backend = settings.value("backend", "soapy_power")
|
||||||
if backend == "soapy_power":
|
try:
|
||||||
self.power_thread = SoapyPowerThread(self.data_storage)
|
backend_module = getattr(backends, backend)
|
||||||
elif backend == "rx_power":
|
except AttributeError:
|
||||||
self.power_thread = RxPowerThread(self.data_storage)
|
backend_module = backends.soapy_power
|
||||||
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)
|
|
||||||
|
|
||||||
self.power_thread.powerThreadStarted.connect(self.update_buttons)
|
if self.backend is None or backend != self.backend:
|
||||||
self.power_thread.powerThreadStopped.connect(self.update_buttons)
|
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)
|
||||||
|
|
||||||
def set_dock_size(self, dock, width, height):
|
def set_dock_size(self, dock, width, height):
|
||||||
"""Ugly hack for resizing QDockWidget (because it doesn't respect minimumSize / sizePolicy set in Designer)
|
"""Ugly hack for resizing QDockWidget (because it doesn't respect minimumSize / sizePolicy set in Designer)
|
||||||
@ -263,7 +169,7 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin
|
|||||||
self.stopFreqSpinBox.setValue(settings.value("stop_freq", 108.0, float))
|
self.stopFreqSpinBox.setValue(settings.value("stop_freq", 108.0, float))
|
||||||
self.binSizeSpinBox.setValue(settings.value("bin_size", 10.0, float))
|
self.binSizeSpinBox.setValue(settings.value("bin_size", 10.0, float))
|
||||||
self.intervalSpinBox.setValue(settings.value("interval", 10.0, float))
|
self.intervalSpinBox.setValue(settings.value("interval", 10.0, float))
|
||||||
self.gainSpinBox.setValue(settings.value("gain", 0, int))
|
self.gainSpinBox.setValue(settings.value("gain", 0, float))
|
||||||
self.ppmSpinBox.setValue(settings.value("ppm", 0, int))
|
self.ppmSpinBox.setValue(settings.value("ppm", 0, int))
|
||||||
self.cropSpinBox.setValue(settings.value("crop", 0, int))
|
self.cropSpinBox.setValue(settings.value("crop", 0, int))
|
||||||
self.mainCurveCheckBox.setChecked(settings.value("main_curve", 1, int))
|
self.mainCurveCheckBox.setChecked(settings.value("main_curve", 1, int))
|
||||||
@ -272,6 +178,8 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin
|
|||||||
self.averageCheckBox.setChecked(settings.value("average", 0, int))
|
self.averageCheckBox.setChecked(settings.value("average", 0, int))
|
||||||
self.smoothCheckBox.setChecked(settings.value("smooth", 0, int))
|
self.smoothCheckBox.setChecked(settings.value("smooth", 0, int))
|
||||||
self.persistenceCheckBox.setChecked(settings.value("persistence", 0, int))
|
self.persistenceCheckBox.setChecked(settings.value("persistence", 0, int))
|
||||||
|
self.baselineCheckBox.setChecked(settings.value("baseline", 0, int))
|
||||||
|
self.subtractBaselineCheckBox.setChecked(settings.value("subtract_baseline", 0, int))
|
||||||
|
|
||||||
# Restore window state
|
# Restore window state
|
||||||
if settings.value("window_state"):
|
if settings.value("window_state"):
|
||||||
@ -311,6 +219,8 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin
|
|||||||
settings.setValue("average", int(self.averageCheckBox.isChecked()))
|
settings.setValue("average", int(self.averageCheckBox.isChecked()))
|
||||||
settings.setValue("smooth", int(self.smoothCheckBox.isChecked()))
|
settings.setValue("smooth", int(self.smoothCheckBox.isChecked()))
|
||||||
settings.setValue("persistence", int(self.persistenceCheckBox.isChecked()))
|
settings.setValue("persistence", int(self.persistenceCheckBox.isChecked()))
|
||||||
|
settings.setValue("baseline", int(self.baselineCheckBox.isChecked()))
|
||||||
|
settings.setValue("subtract_baseline", int(self.subtractBaselineCheckBox.isChecked()))
|
||||||
|
|
||||||
# Save window state and geometry
|
# Save window state and geometry
|
||||||
settings.setValue("window_geometry", self.saveGeometry())
|
settings.setValue("window_geometry", self.saveGeometry())
|
||||||
@ -329,32 +239,72 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin
|
|||||||
|
|
||||||
def update_data(self, data_storage):
|
def update_data(self, data_storage):
|
||||||
"""Update GUI when new data is received"""
|
"""Update GUI when new data is received"""
|
||||||
# Show number of hops and how much time did the sweep really take
|
|
||||||
timestamp = time.time()
|
timestamp = time.time()
|
||||||
sweep_time = timestamp - self.prev_data_timestamp
|
self.prev_sweep_time = timestamp - self.prev_data_timestamp
|
||||||
self.prev_data_timestamp = timestamp
|
self.prev_data_timestamp = timestamp
|
||||||
|
self.update_status()
|
||||||
|
|
||||||
self.show_status(
|
def update_status(self):
|
||||||
self.tr("Frequency hops: {} | Sweep time: {:.2f} s | FPS: {:.2f}").format(
|
"""Update status bar"""
|
||||||
self.power_thread.params["hops"] or self.tr("N/A"),
|
timestamp = time.time()
|
||||||
sweep_time,
|
status = []
|
||||||
1 / sweep_time
|
|
||||||
),
|
if self.power_thread.params["hops"]:
|
||||||
timeout=0
|
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)
|
||||||
|
|
||||||
def start(self, single_shot=False):
|
def start(self, single_shot=False):
|
||||||
"""Start power thread"""
|
"""Start power thread"""
|
||||||
settings = QtCore.QSettings()
|
settings = QtCore.QSettings()
|
||||||
self.prev_data_timestamp = time.time()
|
|
||||||
|
|
||||||
self.data_storage.reset()
|
self.prev_sweep_time = 0
|
||||||
self.data_storage.set_smooth(
|
self.prev_data_timestamp = time.time()
|
||||||
bool(self.smoothCheckBox.isChecked()),
|
self.start_timestamp = self.prev_data_timestamp
|
||||||
settings.value("smooth_length", 11, int),
|
|
||||||
settings.value("smooth_window", "hanning"),
|
if self.intervalSpinBox.value() >= 1:
|
||||||
recalculate=False
|
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.waterfallPlotWidget.history_size = settings.value("waterfall_history_size", 100, int)
|
self.waterfallPlotWidget.history_size = settings.value("waterfall_history_size", 100, int)
|
||||||
self.waterfallPlotWidget.clear_plot()
|
self.waterfallPlotWidget.clear_plot()
|
||||||
@ -367,6 +317,8 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin
|
|||||||
self.spectrumPlotWidget.peak_hold_min_color = str_to_color(settings.value("peak_hold_min_color", "0, 0, 255, 255"))
|
self.spectrumPlotWidget.peak_hold_min_color = str_to_color(settings.value("peak_hold_min_color", "0, 0, 255, 255"))
|
||||||
self.spectrumPlotWidget.average = bool(self.averageCheckBox.isChecked())
|
self.spectrumPlotWidget.average = bool(self.averageCheckBox.isChecked())
|
||||||
self.spectrumPlotWidget.average_color = str_to_color(settings.value("average_color", "0, 255, 255, 255"))
|
self.spectrumPlotWidget.average_color = str_to_color(settings.value("average_color", "0, 255, 255, 255"))
|
||||||
|
self.spectrumPlotWidget.baseline = bool(self.baselineCheckBox.isChecked())
|
||||||
|
self.spectrumPlotWidget.baseline_color = str_to_color(settings.value("baseline_color", "255, 0, 255, 255"))
|
||||||
self.spectrumPlotWidget.persistence = bool(self.persistenceCheckBox.isChecked())
|
self.spectrumPlotWidget.persistence = bool(self.persistenceCheckBox.isChecked())
|
||||||
self.spectrumPlotWidget.persistence_length = settings.value("persistence_length", 5, int)
|
self.spectrumPlotWidget.persistence_length = settings.value("persistence_length", 5, int)
|
||||||
self.spectrumPlotWidget.persistence_decay = settings.value("persistence_decay", "exponential")
|
self.spectrumPlotWidget.persistence_decay = settings.value("persistence_decay", "exponential")
|
||||||
@ -375,19 +327,35 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin
|
|||||||
self.spectrumPlotWidget.clear_peak_hold_max()
|
self.spectrumPlotWidget.clear_peak_hold_max()
|
||||||
self.spectrumPlotWidget.clear_peak_hold_min()
|
self.spectrumPlotWidget.clear_peak_hold_min()
|
||||||
self.spectrumPlotWidget.clear_average()
|
self.spectrumPlotWidget.clear_average()
|
||||||
|
self.spectrumPlotWidget.clear_baseline()
|
||||||
self.spectrumPlotWidget.clear_persistence()
|
self.spectrumPlotWidget.clear_persistence()
|
||||||
|
|
||||||
|
self.data_storage.reset()
|
||||||
|
self.data_storage.set_smooth(
|
||||||
|
bool(self.smoothCheckBox.isChecked()),
|
||||||
|
settings.value("smooth_length", 11, int),
|
||||||
|
settings.value("smooth_window", "hanning")
|
||||||
|
)
|
||||||
|
self.data_storage.set_subtract_baseline(
|
||||||
|
bool(self.subtractBaselineCheckBox.isChecked()),
|
||||||
|
settings.value("baseline_file", None)
|
||||||
|
)
|
||||||
|
|
||||||
if not self.power_thread.alive:
|
if not self.power_thread.alive:
|
||||||
self.power_thread.setup(float(self.startFreqSpinBox.value()),
|
self.power_thread.setup(
|
||||||
float(self.stopFreqSpinBox.value()),
|
float(self.startFreqSpinBox.value()),
|
||||||
float(self.binSizeSpinBox.value()),
|
float(self.stopFreqSpinBox.value()),
|
||||||
interval=float(self.intervalSpinBox.value()),
|
float(self.binSizeSpinBox.value()),
|
||||||
gain=int(self.gainSpinBox.value()),
|
interval=float(self.intervalSpinBox.value()),
|
||||||
ppm=int(self.ppmSpinBox.value()),
|
gain=float(self.gainSpinBox.value()),
|
||||||
crop=int(self.cropSpinBox.value()) / 100.0,
|
ppm=int(self.ppmSpinBox.value()),
|
||||||
single_shot=single_shot,
|
crop=int(self.cropSpinBox.value()) / 100.0,
|
||||||
device=settings.value("device", ""),
|
single_shot=single_shot,
|
||||||
sample_rate=settings.value("sample_rate", 2560000, int))
|
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)
|
||||||
|
)
|
||||||
self.power_thread.start()
|
self.power_thread.start()
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
@ -395,47 +363,47 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin
|
|||||||
if self.power_thread.alive:
|
if self.power_thread.alive:
|
||||||
self.power_thread.stop()
|
self.power_thread.stop()
|
||||||
|
|
||||||
@QtCore.pyqtSlot()
|
@QtCore.Slot()
|
||||||
def on_startButton_clicked(self):
|
def on_startButton_clicked(self):
|
||||||
self.start()
|
self.start()
|
||||||
|
|
||||||
@QtCore.pyqtSlot()
|
@QtCore.Slot()
|
||||||
def on_singleShotButton_clicked(self):
|
def on_singleShotButton_clicked(self):
|
||||||
self.start(single_shot=True)
|
self.start(single_shot=True)
|
||||||
|
|
||||||
@QtCore.pyqtSlot()
|
@QtCore.Slot()
|
||||||
def on_stopButton_clicked(self):
|
def on_stopButton_clicked(self):
|
||||||
self.stop()
|
self.stop()
|
||||||
|
|
||||||
@QtCore.pyqtSlot(bool)
|
@QtCore.Slot(bool)
|
||||||
def on_mainCurveCheckBox_toggled(self, checked):
|
def on_mainCurveCheckBox_toggled(self, checked):
|
||||||
self.spectrumPlotWidget.main_curve = checked
|
self.spectrumPlotWidget.main_curve = checked
|
||||||
if self.spectrumPlotWidget.curve.xData is None:
|
if self.spectrumPlotWidget.curve.xData is None:
|
||||||
self.spectrumPlotWidget.update_plot(self.data_storage)
|
self.spectrumPlotWidget.update_plot(self.data_storage)
|
||||||
self.spectrumPlotWidget.curve.setVisible(checked)
|
self.spectrumPlotWidget.curve.setVisible(checked)
|
||||||
|
|
||||||
@QtCore.pyqtSlot(bool)
|
@QtCore.Slot(bool)
|
||||||
def on_peakHoldMaxCheckBox_toggled(self, checked):
|
def on_peakHoldMaxCheckBox_toggled(self, checked):
|
||||||
self.spectrumPlotWidget.peak_hold_max = checked
|
self.spectrumPlotWidget.peak_hold_max = checked
|
||||||
if self.spectrumPlotWidget.curve_peak_hold_max.xData is None:
|
if self.spectrumPlotWidget.curve_peak_hold_max.xData is None:
|
||||||
self.spectrumPlotWidget.update_peak_hold_max(self.data_storage)
|
self.spectrumPlotWidget.update_peak_hold_max(self.data_storage)
|
||||||
self.spectrumPlotWidget.curve_peak_hold_max.setVisible(checked)
|
self.spectrumPlotWidget.curve_peak_hold_max.setVisible(checked)
|
||||||
|
|
||||||
@QtCore.pyqtSlot(bool)
|
@QtCore.Slot(bool)
|
||||||
def on_peakHoldMinCheckBox_toggled(self, checked):
|
def on_peakHoldMinCheckBox_toggled(self, checked):
|
||||||
self.spectrumPlotWidget.peak_hold_min = checked
|
self.spectrumPlotWidget.peak_hold_min = checked
|
||||||
if self.spectrumPlotWidget.curve_peak_hold_min.xData is None:
|
if self.spectrumPlotWidget.curve_peak_hold_min.xData is None:
|
||||||
self.spectrumPlotWidget.update_peak_hold_min(self.data_storage)
|
self.spectrumPlotWidget.update_peak_hold_min(self.data_storage)
|
||||||
self.spectrumPlotWidget.curve_peak_hold_min.setVisible(checked)
|
self.spectrumPlotWidget.curve_peak_hold_min.setVisible(checked)
|
||||||
|
|
||||||
@QtCore.pyqtSlot(bool)
|
@QtCore.Slot(bool)
|
||||||
def on_averageCheckBox_toggled(self, checked):
|
def on_averageCheckBox_toggled(self, checked):
|
||||||
self.spectrumPlotWidget.average = checked
|
self.spectrumPlotWidget.average = checked
|
||||||
if self.spectrumPlotWidget.curve_average.xData is None:
|
if self.spectrumPlotWidget.curve_average.xData is None:
|
||||||
self.spectrumPlotWidget.update_average(self.data_storage)
|
self.spectrumPlotWidget.update_average(self.data_storage)
|
||||||
self.spectrumPlotWidget.curve_average.setVisible(checked)
|
self.spectrumPlotWidget.curve_average.setVisible(checked)
|
||||||
|
|
||||||
@QtCore.pyqtSlot(bool)
|
@QtCore.Slot(bool)
|
||||||
def on_persistenceCheckBox_toggled(self, checked):
|
def on_persistenceCheckBox_toggled(self, checked):
|
||||||
self.spectrumPlotWidget.persistence = checked
|
self.spectrumPlotWidget.persistence = checked
|
||||||
if self.spectrumPlotWidget.persistence_curves[0].xData is None:
|
if self.spectrumPlotWidget.persistence_curves[0].xData is None:
|
||||||
@ -443,29 +411,52 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin
|
|||||||
for curve in self.spectrumPlotWidget.persistence_curves:
|
for curve in self.spectrumPlotWidget.persistence_curves:
|
||||||
curve.setVisible(checked)
|
curve.setVisible(checked)
|
||||||
|
|
||||||
@QtCore.pyqtSlot(bool)
|
@QtCore.Slot(bool)
|
||||||
def on_smoothCheckBox_toggled(self, checked):
|
def on_smoothCheckBox_toggled(self, checked):
|
||||||
settings = QtCore.QSettings()
|
settings = QtCore.QSettings()
|
||||||
self.data_storage.set_smooth(
|
self.data_storage.set_smooth(
|
||||||
checked,
|
checked,
|
||||||
settings.value("smooth_length", 11, int),
|
settings.value("smooth_length", 11, int),
|
||||||
settings.value("smooth_window", "hanning"),
|
settings.value("smooth_window", "hanning")
|
||||||
recalculate=True
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@QtCore.pyqtSlot()
|
@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()
|
||||||
def on_smoothButton_clicked(self):
|
def on_smoothButton_clicked(self):
|
||||||
dialog = QSpectrumAnalyzerSmooth(self)
|
dialog = QSpectrumAnalyzerSmoothing(self)
|
||||||
if dialog.exec_():
|
if dialog.exec_():
|
||||||
settings = QtCore.QSettings()
|
settings = QtCore.QSettings()
|
||||||
self.data_storage.set_smooth(
|
self.data_storage.set_smooth(
|
||||||
bool(self.smoothCheckBox.isChecked()),
|
bool(self.smoothCheckBox.isChecked()),
|
||||||
settings.value("smooth_length", 11, int),
|
settings.value("smooth_length", 11, int),
|
||||||
settings.value("smooth_window", "hanning"),
|
settings.value("smooth_window", "hanning")
|
||||||
recalculate=True
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@QtCore.pyqtSlot()
|
@QtCore.Slot()
|
||||||
def on_persistenceButton_clicked(self):
|
def on_persistenceButton_clicked(self):
|
||||||
prev_persistence_length = self.spectrumPlotWidget.persistence_length
|
prev_persistence_length = self.spectrumPlotWidget.persistence_length
|
||||||
dialog = QSpectrumAnalyzerPersistence(self)
|
dialog = QSpectrumAnalyzerPersistence(self)
|
||||||
@ -481,7 +472,7 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin
|
|||||||
else:
|
else:
|
||||||
self.spectrumPlotWidget.recalculate_persistence(self.data_storage)
|
self.spectrumPlotWidget.recalculate_persistence(self.data_storage)
|
||||||
|
|
||||||
@QtCore.pyqtSlot()
|
@QtCore.Slot()
|
||||||
def on_colorsButton_clicked(self):
|
def on_colorsButton_clicked(self):
|
||||||
dialog = QSpectrumAnalyzerColors(self)
|
dialog = QSpectrumAnalyzerColors(self)
|
||||||
if dialog.exec_():
|
if dialog.exec_():
|
||||||
@ -491,20 +482,21 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin
|
|||||||
self.spectrumPlotWidget.peak_hold_min_color = str_to_color(settings.value("peak_hold_min_color", "0, 0, 255, 255"))
|
self.spectrumPlotWidget.peak_hold_min_color = str_to_color(settings.value("peak_hold_min_color", "0, 0, 255, 255"))
|
||||||
self.spectrumPlotWidget.average_color = str_to_color(settings.value("average_color", "0, 255, 255, 255"))
|
self.spectrumPlotWidget.average_color = str_to_color(settings.value("average_color", "0, 255, 255, 255"))
|
||||||
self.spectrumPlotWidget.persistence_color = str_to_color(settings.value("persistence_color", "0, 255, 0, 255"))
|
self.spectrumPlotWidget.persistence_color = str_to_color(settings.value("persistence_color", "0, 255, 0, 255"))
|
||||||
|
self.spectrumPlotWidget.baseline_color = str_to_color(settings.value("baseline_color", "255, 0, 255, 255"))
|
||||||
self.spectrumPlotWidget.set_colors()
|
self.spectrumPlotWidget.set_colors()
|
||||||
|
|
||||||
@QtCore.pyqtSlot()
|
@QtCore.Slot()
|
||||||
def on_action_Settings_triggered(self):
|
def on_action_Settings_triggered(self):
|
||||||
dialog = QSpectrumAnalyzerSettings(self)
|
dialog = QSpectrumAnalyzerSettings(self)
|
||||||
if dialog.exec_():
|
if dialog.exec_():
|
||||||
self.setup_power_thread()
|
self.setup_power_thread()
|
||||||
|
|
||||||
@QtCore.pyqtSlot()
|
@QtCore.Slot()
|
||||||
def on_action_About_triggered(self):
|
def on_action_About_triggered(self):
|
||||||
QtGui.QMessageBox.information(self, self.tr("About - QSpectrumAnalyzer"),
|
QtWidgets.QMessageBox.information(self, self.tr("About - QSpectrumAnalyzer"),
|
||||||
self.tr("QSpectrumAnalyzer {}").format(__version__))
|
self.tr("QSpectrumAnalyzer {}").format(__version__))
|
||||||
|
|
||||||
@QtCore.pyqtSlot()
|
@QtCore.Slot()
|
||||||
def on_action_Quit_triggered(self):
|
def on_action_Quit_triggered(self):
|
||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
@ -515,12 +507,37 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
app = QtGui.QApplication(sys.argv)
|
global debug
|
||||||
app.setOrganizationName("QSpectrumAnalyzer")
|
|
||||||
app.setOrganizationDomain("qspectrumanalyzer.eutopia.cz")
|
# Parse command line arguments
|
||||||
app.setApplicationName("QSpectrumAnalyzer")
|
parser = argparse.ArgumentParser(
|
||||||
window = QSpectrumAnalyzerMainWindow()
|
prog="qspectrumanalyzer",
|
||||||
sys.exit(app.exec_())
|
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.setOrganizationName("QSpectrumAnalyzer")
|
||||||
|
app.setOrganizationDomain("qspectrumanalyzer.eutopia.cz")
|
||||||
|
app.setApplicationName("QSpectrumAnalyzer")
|
||||||
|
window = QSpectrumAnalyzerMainWindow()
|
||||||
|
sys.exit(app.exec_())
|
||||||
|
finally:
|
||||||
|
# Unhide console window on Windows (we don't want to leave zombies behind)
|
||||||
|
if sys.platform == 'win32' and not debug:
|
||||||
|
windows.set_attached_console_visible(True)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
@ -1,566 +0,0 @@
|
|||||||
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()
|
|
117
qspectrumanalyzer/backends/__init__.py
Normal file
117
qspectrumanalyzer/backends/__init__.py
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
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
|
171
qspectrumanalyzer/backends/hackrf_sweep.py
Normal file
171
qspectrumanalyzer/backends/hackrf_sweep.py
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
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()
|
104
qspectrumanalyzer/backends/rtl_power.py
Normal file
104
qspectrumanalyzer/backends/rtl_power.py
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
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)
|
145
qspectrumanalyzer/backends/rtl_power_fftw.py
Normal file
145
qspectrumanalyzer/backends/rtl_power_fftw.py
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
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
|
109
qspectrumanalyzer/backends/rx_power.py
Normal file
109
qspectrumanalyzer/backends/rx_power.py
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
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)
|
254
qspectrumanalyzer/backends/soapy_power.py
Normal file
254
qspectrumanalyzer/backends/soapy_power.py
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
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)
|
28
qspectrumanalyzer/baseline.py
Normal file
28
qspectrumanalyzer/baseline.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
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)
|
33
qspectrumanalyzer/colors.py
Normal file
33
qspectrumanalyzer/colors.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
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,9 +1,10 @@
|
|||||||
import time, sys
|
import time, sys, os
|
||||||
|
|
||||||
from PyQt4 import QtCore
|
from Qt import QtCore
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from qspectrumanalyzer.utils import smooth
|
from qspectrumanalyzer.utils import smooth
|
||||||
|
from qspectrumanalyzer.backends import soapy_power
|
||||||
|
|
||||||
|
|
||||||
class HistoryBuffer:
|
class HistoryBuffer:
|
||||||
@ -36,7 +37,7 @@ class HistoryBuffer:
|
|||||||
|
|
||||||
class TaskSignals(QtCore.QObject):
|
class TaskSignals(QtCore.QObject):
|
||||||
"""Task signals emitter"""
|
"""Task signals emitter"""
|
||||||
result = QtCore.pyqtSignal(object)
|
result = QtCore.Signal(object)
|
||||||
|
|
||||||
|
|
||||||
class Task(QtCore.QRunnable):
|
class Task(QtCore.QRunnable):
|
||||||
@ -57,12 +58,14 @@ class Task(QtCore.QRunnable):
|
|||||||
|
|
||||||
class DataStorage(QtCore.QObject):
|
class DataStorage(QtCore.QObject):
|
||||||
"""Data storage for spectrum measurements"""
|
"""Data storage for spectrum measurements"""
|
||||||
history_updated = QtCore.pyqtSignal(object)
|
history_updated = QtCore.Signal(object)
|
||||||
data_updated = QtCore.pyqtSignal(object)
|
data_updated = QtCore.Signal(object)
|
||||||
data_recalculated = QtCore.pyqtSignal(object)
|
history_recalculated = QtCore.Signal(object)
|
||||||
average_updated = QtCore.pyqtSignal(object)
|
data_recalculated = QtCore.Signal(object)
|
||||||
peak_hold_max_updated = QtCore.pyqtSignal(object)
|
average_updated = QtCore.Signal(object)
|
||||||
peak_hold_min_updated = QtCore.pyqtSignal(object)
|
baseline_updated = QtCore.Signal(object)
|
||||||
|
peak_hold_max_updated = QtCore.Signal(object)
|
||||||
|
peak_hold_min_updated = QtCore.Signal(object)
|
||||||
|
|
||||||
def __init__(self, max_history_size=100, parent=None):
|
def __init__(self, max_history_size=100, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
@ -70,6 +73,10 @@ class DataStorage(QtCore.QObject):
|
|||||||
self.smooth = False
|
self.smooth = False
|
||||||
self.smooth_length = 11
|
self.smooth_length = 11
|
||||||
self.smooth_window = "hanning"
|
self.smooth_window = "hanning"
|
||||||
|
self.subtract_baseline = False
|
||||||
|
self.prev_baseline = None
|
||||||
|
self.baseline = None
|
||||||
|
self.baseline_x = None
|
||||||
|
|
||||||
# Use only one worker thread because it is not faster
|
# Use only one worker thread because it is not faster
|
||||||
# with more threads (and memory consumption is much higher)
|
# with more threads (and memory consumption is much higher)
|
||||||
@ -105,11 +112,20 @@ class DataStorage(QtCore.QObject):
|
|||||||
|
|
||||||
def update(self, data):
|
def update(self, data):
|
||||||
"""Update data storage"""
|
"""Update data storage"""
|
||||||
|
if self.y is not None and len(data["y"]) != len(self.y):
|
||||||
|
print("{:d} bins coming from backend, expected {:d}".format(len(data["y"]), len(self.y)))
|
||||||
|
return
|
||||||
|
|
||||||
self.average_counter += 1
|
self.average_counter += 1
|
||||||
|
|
||||||
if self.x is None:
|
if self.x is None:
|
||||||
self.x = data["x"]
|
self.x = data["x"]
|
||||||
|
|
||||||
|
# Subtract baseline from data
|
||||||
|
data["y"] = np.asarray(data["y"])
|
||||||
|
if self.subtract_baseline and self.baseline is not None and len(data["y"]) == len(self.baseline):
|
||||||
|
data["y"] -= self.baseline
|
||||||
|
|
||||||
self.start_task(self.update_history, data.copy())
|
self.start_task(self.update_history, data.copy())
|
||||||
self.start_task(self.update_data, data)
|
self.start_task(self.update_data, data)
|
||||||
|
|
||||||
@ -161,16 +177,63 @@ class DataStorage(QtCore.QObject):
|
|||||||
"""Apply smoothing function to data"""
|
"""Apply smoothing function to data"""
|
||||||
return smooth(y, window_len=self.smooth_length, window=self.smooth_window)
|
return smooth(y, window_len=self.smooth_length, window=self.smooth_window)
|
||||||
|
|
||||||
def set_smooth(self, toggle, length=11, window="hanning", recalculate=False):
|
def set_smooth(self, toggle, length=11, window="hanning"):
|
||||||
"""Toggle smoothing and set smoothing params"""
|
"""Toggle smoothing and set smoothing params"""
|
||||||
if toggle != self.smooth or length != self.smooth_length or window != self.smooth_window:
|
if toggle != self.smooth or length != self.smooth_length or window != self.smooth_window:
|
||||||
self.smooth = toggle
|
self.smooth = toggle
|
||||||
self.smooth_length = length
|
self.smooth_length = length
|
||||||
self.smooth_window = window
|
self.smooth_window = window
|
||||||
if recalculate:
|
self.start_task(self.recalculate_data)
|
||||||
self.start_task(self.recalculate_data)
|
|
||||||
else:
|
def set_subtract_baseline(self, toggle, baseline_file=None):
|
||||||
self.reset_data()
|
"""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)
|
||||||
|
|
||||||
def recalculate_data(self):
|
def recalculate_data(self):
|
||||||
"""Recalculate current data from history"""
|
"""Recalculate current data from history"""
|
||||||
|
@ -1,250 +1,288 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!DOCTYPE TS><TS version="2.0">
|
<!DOCTYPE TS><TS version="2.0">
|
||||||
|
<context>
|
||||||
|
<name>QSpectrumAnalyzerBaseline</name>
|
||||||
|
<message>
|
||||||
|
<location filename="../baseline.py" line="20"/>
|
||||||
|
<source>Select baseline file - QSpectrumAnalyzer</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui_qspectrumanalyzer_baseline.py" line="50"/>
|
||||||
|
<source>Baseline - QSpectrumAnalyzer</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui_qspectrumanalyzer_baseline.py" line="51"/>
|
||||||
|
<source>Baseline &file:</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui_qspectrumanalyzer_baseline.py" line="52"/>
|
||||||
|
<source>...</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>QSpectrumAnalyzerColors</name>
|
<name>QSpectrumAnalyzerColors</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer_colors.py" line="113"/>
|
<location filename="../ui_qspectrumanalyzer_colors.py" line="112"/>
|
||||||
<source>Colors - QSpectrumAnalyzer</source>
|
<source>Colors - QSpectrumAnalyzer</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer_colors.py" line="114"/>
|
<location filename="../ui_qspectrumanalyzer_colors.py" line="124"/>
|
||||||
<source>Main curve color:</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../ui_qspectrumanalyzer_colors.py" line="123"/>
|
|
||||||
<source>...</source>
|
<source>...</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer_colors.py" line="120"/>
|
<location filename="../ui_qspectrumanalyzer_colors.py" line="113"/>
|
||||||
<source>Average color:</source>
|
<source>&Main curve color:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer_colors.py" line="122"/>
|
<location filename="../ui_qspectrumanalyzer_colors.py" line="115"/>
|
||||||
<source>Persistence color:</source>
|
<source>Max. peak &hold color:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer_colors.py" line="116"/>
|
<location filename="../ui_qspectrumanalyzer_colors.py" line="117"/>
|
||||||
<source>Max. peak hold color:</source>
|
<source>M&in. peak hold color:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer_colors.py" line="118"/>
|
<location filename="../ui_qspectrumanalyzer_colors.py" line="119"/>
|
||||||
<source>Min. peak hold color:</source>
|
<source>Average &color:</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui_qspectrumanalyzer_colors.py" line="121"/>
|
||||||
|
<source>Persistence co&lor:</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui_qspectrumanalyzer_colors.py" line="123"/>
|
||||||
|
<source>&Baseline color:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>QSpectrumAnalyzerMainWindow</name>
|
<name>QSpectrumAnalyzerMainWindow</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer.py" line="311"/>
|
<location filename="../ui_qspectrumanalyzer.py" line="317"/>
|
||||||
<source>QSpectrumAnalyzer</source>
|
<source>QSpectrumAnalyzer</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer.py" line="325"/>
|
<location filename="../__main__.py" line="496"/>
|
||||||
<source>Settings</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<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>
|
<source>About - QSpectrumAnalyzer</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../__main__.py" line="504"/>
|
<location filename="../__main__.py" line="496"/>
|
||||||
<source>QSpectrumAnalyzer {}</source>
|
<source>QSpectrumAnalyzer {}</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer.py" line="312"/>
|
<location filename="../ui_qspectrumanalyzer.py" line="318"/>
|
||||||
<source>&File</source>
|
<source>&File</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer.py" line="313"/>
|
<location filename="../ui_qspectrumanalyzer.py" line="319"/>
|
||||||
<source>&Help</source>
|
<source>&Help</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer.py" line="315"/>
|
<location filename="../ui_qspectrumanalyzer.py" line="350"/>
|
||||||
<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>
|
<source>&Settings...</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer.py" line="342"/>
|
<location filename="../ui_qspectrumanalyzer.py" line="351"/>
|
||||||
<source>&Quit</source>
|
<source>&Quit</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer.py" line="343"/>
|
<location filename="../ui_qspectrumanalyzer.py" line="352"/>
|
||||||
<source>Ctrl+Q</source>
|
<source>Ctrl+Q</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer.py" line="344"/>
|
<location filename="../ui_qspectrumanalyzer.py" line="353"/>
|
||||||
<source>&About</source>
|
<source>&About</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</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"/>
|
||||||
|
<source>Levels</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>QSpectrumAnalyzerPersistence</name>
|
<name>QSpectrumAnalyzerPersistence</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer_persistence.py" line="68"/>
|
<location filename="../ui_qspectrumanalyzer_persistence.py" line="55"/>
|
||||||
<source>Persistence - QSpectrumAnalyzer</source>
|
<source>Persistence - QSpectrumAnalyzer</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer_persistence.py" line="69"/>
|
<location filename="../ui_qspectrumanalyzer_persistence.py" line="56"/>
|
||||||
<source>Decay function:</source>
|
<source>Decay function:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer_persistence.py" line="70"/>
|
<location filename="../ui_qspectrumanalyzer_persistence.py" line="57"/>
|
||||||
<source>linear</source>
|
<source>linear</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer_persistence.py" line="71"/>
|
<location filename="../ui_qspectrumanalyzer_persistence.py" line="58"/>
|
||||||
<source>exponential</source>
|
<source>exponential</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer_persistence.py" line="72"/>
|
<location filename="../ui_qspectrumanalyzer_persistence.py" line="59"/>
|
||||||
<source>Persistence length:</source>
|
<source>Persistence length:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@ -252,110 +290,148 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>QSpectrumAnalyzerSettings</name>
|
<name>QSpectrumAnalyzerSettings</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../__main__.py" line="50"/>
|
<location filename="../settings.py" line="57"/>
|
||||||
<source>Select executable - QSpectrumAnalyzer</source>
|
<source>Select executable - QSpectrumAnalyzer</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="107"/>
|
<location filename="../ui_qspectrumanalyzer_settings.py" line="148"/>
|
||||||
<source>Settings - QSpectrumAnalyzer</source>
|
<source>Settings - QSpectrumAnalyzer</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="108"/>
|
<location filename="../ui_qspectrumanalyzer_settings.py" line="149"/>
|
||||||
<source>&Backend:</source>
|
<source>&Backend:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="115"/>
|
<location filename="../ui_qspectrumanalyzer_settings.py" line="156"/>
|
||||||
<source>soapy_power</source>
|
<source>soapy_power</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="110"/>
|
<location filename="../ui_qspectrumanalyzer_settings.py" line="151"/>
|
||||||
<source>rx_power</source>
|
<source>rx_power</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="111"/>
|
<location filename="../ui_qspectrumanalyzer_settings.py" line="152"/>
|
||||||
<source>rtl_power_fftw</source>
|
<source>rtl_power_fftw</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="112"/>
|
<location filename="../ui_qspectrumanalyzer_settings.py" line="153"/>
|
||||||
<source>rtl_power</source>
|
<source>rtl_power</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="113"/>
|
<location filename="../ui_qspectrumanalyzer_settings.py" line="154"/>
|
||||||
<source>hackrf_sweep</source>
|
<source>hackrf_sweep</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="114"/>
|
<location filename="../ui_qspectrumanalyzer_settings.py" line="155"/>
|
||||||
<source>E&xecutable:</source>
|
<source>E&xecutable:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="116"/>
|
<location filename="../ui_qspectrumanalyzer_settings.py" line="157"/>
|
||||||
<source>...</source>
|
<source>...</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="117"/>
|
<location filename="../ui_qspectrumanalyzer_settings.py" line="159"/>
|
||||||
<source>Device:</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="118"/>
|
|
||||||
<source>Sa&mple rate:</source>
|
<source>Sa&mple rate:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="119"/>
|
<location filename="../ui_qspectrumanalyzer_settings.py" line="160"/>
|
||||||
<source>&Waterfall history size:</source>
|
<source>&Waterfall history size:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</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>
|
||||||
<context>
|
<context>
|
||||||
<name>QSpectrumAnalyzerSmooth</name>
|
<name>QSpectrumAnalyzerSettingsHelp</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer_smooth.py" line="73"/>
|
<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"/>
|
||||||
<source>Smoothing - QSpectrumAnalyzer</source>
|
<source>Smoothing - QSpectrumAnalyzer</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer_smooth.py" line="74"/>
|
<location filename="../ui_qspectrumanalyzer_smoothing.py" line="61"/>
|
||||||
<source>&Window function:</source>
|
<source>&Window function:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer_smooth.py" line="75"/>
|
<location filename="../ui_qspectrumanalyzer_smoothing.py" line="62"/>
|
||||||
<source>rectangular</source>
|
<source>rectangular</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer_smooth.py" line="76"/>
|
<location filename="../ui_qspectrumanalyzer_smoothing.py" line="63"/>
|
||||||
<source>hanning</source>
|
<source>hanning</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer_smooth.py" line="77"/>
|
<location filename="../ui_qspectrumanalyzer_smoothing.py" line="64"/>
|
||||||
<source>hamming</source>
|
<source>hamming</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer_smooth.py" line="78"/>
|
<location filename="../ui_qspectrumanalyzer_smoothing.py" line="65"/>
|
||||||
<source>bartlett</source>
|
<source>bartlett</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer_smooth.py" line="79"/>
|
<location filename="../ui_qspectrumanalyzer_smoothing.py" line="66"/>
|
||||||
<source>blackman</source>
|
<source>blackman</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer_smooth.py" line="80"/>
|
<location filename="../ui_qspectrumanalyzer_smoothing.py" line="67"/>
|
||||||
<source>Window len&gth:</source>
|
<source>Window len&gth:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
29
qspectrumanalyzer/persistence.py
Normal file
29
qspectrumanalyzer/persistence.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
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
|
import collections, math
|
||||||
|
|
||||||
from PyQt4 import QtCore
|
from Qt import QtCore
|
||||||
import pyqtgraph as pg
|
import pyqtgraph as pg
|
||||||
|
|
||||||
# Basic PyQtGraph settings
|
# Basic PyQtGraph settings
|
||||||
@ -29,6 +29,8 @@ class SpectrumPlotWidget:
|
|||||||
self.peak_hold_min_color = pg.mkColor("b")
|
self.peak_hold_min_color = pg.mkColor("b")
|
||||||
self.average = False
|
self.average = False
|
||||||
self.average_color = pg.mkColor("c")
|
self.average_color = pg.mkColor("c")
|
||||||
|
self.baseline = False
|
||||||
|
self.baseline_color = pg.mkColor("m")
|
||||||
|
|
||||||
self.create_plot()
|
self.create_plot()
|
||||||
|
|
||||||
@ -42,6 +44,10 @@ class SpectrumPlotWidget:
|
|||||||
self.plot.setLimits(xMin=0)
|
self.plot.setLimits(xMin=0)
|
||||||
self.plot.showButtons()
|
self.plot.showButtons()
|
||||||
|
|
||||||
|
#self.plot.setDownsampling(mode="peak")
|
||||||
|
#self.plot.setClipToView(True)
|
||||||
|
|
||||||
|
self.create_baseline_curve()
|
||||||
self.create_persistence_curves()
|
self.create_persistence_curves()
|
||||||
self.create_average_curve()
|
self.create_average_curve()
|
||||||
self.create_peak_hold_min_curve()
|
self.create_peak_hold_min_curve()
|
||||||
@ -78,6 +84,11 @@ class SpectrumPlotWidget:
|
|||||||
self.curve_average = self.plot.plot(pen=self.average_color)
|
self.curve_average = self.plot.plot(pen=self.average_color)
|
||||||
self.curve_average.setZValue(700)
|
self.curve_average.setZValue(700)
|
||||||
|
|
||||||
|
def create_baseline_curve(self):
|
||||||
|
"""Create baseline curve"""
|
||||||
|
self.curve_baseline = self.plot.plot(pen=self.baseline_color)
|
||||||
|
self.curve_baseline.setZValue(500)
|
||||||
|
|
||||||
def create_persistence_curves(self):
|
def create_persistence_curves(self):
|
||||||
"""Create spectrum persistence curves"""
|
"""Create spectrum persistence curves"""
|
||||||
z_index_base = 600
|
z_index_base = 600
|
||||||
@ -96,6 +107,7 @@ class SpectrumPlotWidget:
|
|||||||
self.curve_peak_hold_max.setPen(self.peak_hold_max_color)
|
self.curve_peak_hold_max.setPen(self.peak_hold_max_color)
|
||||||
self.curve_peak_hold_min.setPen(self.peak_hold_min_color)
|
self.curve_peak_hold_min.setPen(self.peak_hold_min_color)
|
||||||
self.curve_average.setPen(self.average_color)
|
self.curve_average.setPen(self.average_color)
|
||||||
|
self.curve_baseline.setPen(self.baseline_color)
|
||||||
|
|
||||||
decay = self.get_decay()
|
decay = self.get_decay()
|
||||||
for i, curve in enumerate(self.persistence_curves):
|
for i, curve in enumerate(self.persistence_curves):
|
||||||
@ -158,6 +170,17 @@ class SpectrumPlotWidget:
|
|||||||
if force:
|
if force:
|
||||||
self.curve_average.setVisible(self.average)
|
self.curve_average.setVisible(self.average)
|
||||||
|
|
||||||
|
def update_baseline(self, data_storage, force=False):
|
||||||
|
"""Update baseline curve"""
|
||||||
|
if data_storage.baseline_x is None or data_storage.baseline is None:
|
||||||
|
self.curve_baseline.clear()
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.baseline or force:
|
||||||
|
self.curve_baseline.setData(data_storage.baseline_x, data_storage.baseline)
|
||||||
|
if force:
|
||||||
|
self.curve_baseline.setVisible(self.baseline)
|
||||||
|
|
||||||
def update_persistence(self, data_storage, force=False):
|
def update_persistence(self, data_storage, force=False):
|
||||||
"""Update persistence curves"""
|
"""Update persistence curves"""
|
||||||
if data_storage.x is None:
|
if data_storage.x is None:
|
||||||
@ -181,6 +204,7 @@ class SpectrumPlotWidget:
|
|||||||
|
|
||||||
QtCore.QTimer.singleShot(0, lambda: self.update_plot(data_storage, force=True))
|
QtCore.QTimer.singleShot(0, lambda: self.update_plot(data_storage, force=True))
|
||||||
QtCore.QTimer.singleShot(0, lambda: self.update_average(data_storage, force=True))
|
QtCore.QTimer.singleShot(0, lambda: self.update_average(data_storage, force=True))
|
||||||
|
QtCore.QTimer.singleShot(0, lambda: self.update_baseline(data_storage, force=True))
|
||||||
QtCore.QTimer.singleShot(0, lambda: self.update_peak_hold_max(data_storage, force=True))
|
QtCore.QTimer.singleShot(0, lambda: self.update_peak_hold_max(data_storage, force=True))
|
||||||
QtCore.QTimer.singleShot(0, lambda: self.update_peak_hold_min(data_storage, force=True))
|
QtCore.QTimer.singleShot(0, lambda: self.update_peak_hold_min(data_storage, force=True))
|
||||||
|
|
||||||
@ -228,6 +252,10 @@ class SpectrumPlotWidget:
|
|||||||
"""Clear average curve"""
|
"""Clear average curve"""
|
||||||
self.curve_average.clear()
|
self.curve_average.clear()
|
||||||
|
|
||||||
|
def clear_baseline(self):
|
||||||
|
"""Clear baseline curve"""
|
||||||
|
self.curve_baseline.clear()
|
||||||
|
|
||||||
def clear_persistence(self):
|
def clear_persistence(self):
|
||||||
"""Clear spectrum persistence curves"""
|
"""Clear spectrum persistence curves"""
|
||||||
self.persistence_data = None
|
self.persistence_data = None
|
||||||
@ -264,6 +292,7 @@ class WaterfallPlotWidget:
|
|||||||
self.plot.setLimits(xMin=0, yMax=0)
|
self.plot.setLimits(xMin=0, yMax=0)
|
||||||
self.plot.showButtons()
|
self.plot.showButtons()
|
||||||
#self.plot.setAspectLocked(True)
|
#self.plot.setAspectLocked(True)
|
||||||
|
|
||||||
#self.plot.setDownsampling(mode="peak")
|
#self.plot.setDownsampling(mode="peak")
|
||||||
#self.plot.setClipToView(True)
|
#self.plot.setClipToView(True)
|
||||||
|
|
||||||
@ -304,3 +333,16 @@ class WaterfallPlotWidget:
|
|||||||
def clear_plot(self):
|
def clear_plot(self):
|
||||||
"""Clear waterfall plot"""
|
"""Clear waterfall plot"""
|
||||||
self.counter = 0
|
self.counter = 0
|
||||||
|
|
||||||
|
def recalculate_plot(self, data_storage):
|
||||||
|
"""Recalculate waterfall plot"""
|
||||||
|
if data_storage.x is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.waterfallImg.setImage(data_storage.history.buffer[-self.counter:].T,
|
||||||
|
autoLevels=False, autoRange=False)
|
||||||
|
self.waterfallImg.setPos(
|
||||||
|
data_storage.x[0],
|
||||||
|
-self.counter if self.counter < self.history_size else -self.history_size
|
||||||
|
)
|
||||||
|
self.histogram.setImageItem(self.waterfallImg)
|
||||||
|
133
qspectrumanalyzer/qspectrumanalyzer.svg
Normal file
133
qspectrumanalyzer/qspectrumanalyzer.svg
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
<?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>
|
After Width: | Height: | Size: 4.3 KiB |
@ -7,7 +7,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>1200</width>
|
<width>1200</width>
|
||||||
<height>810</height>
|
<height>892</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
@ -52,7 +52,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>1200</width>
|
<width>1200</width>
|
||||||
<height>30</height>
|
<height>32</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QMenu" name="menu_File">
|
<widget class="QMenu" name="menu_File">
|
||||||
@ -82,8 +82,8 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>10</width>
|
<width>190</width>
|
||||||
<height>10</height>
|
<height>130</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="features">
|
<property name="features">
|
||||||
@ -143,8 +143,8 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>10</width>
|
<width>208</width>
|
||||||
<height>10</height>
|
<height>166</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="features">
|
<property name="features">
|
||||||
@ -182,6 +182,9 @@
|
|||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="showGroupSeparator" stdset="0">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string> MHz</string>
|
<string> MHz</string>
|
||||||
</property>
|
</property>
|
||||||
@ -189,10 +192,10 @@
|
|||||||
<number>3</number>
|
<number>3</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
<double>24.000000000000000</double>
|
<double>0.000000000000000</double>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<double>1766.000000000000000</double>
|
<double>2200.000000000000000</double>
|
||||||
</property>
|
</property>
|
||||||
<property name="value">
|
<property name="value">
|
||||||
<double>87.000000000000000</double>
|
<double>87.000000000000000</double>
|
||||||
@ -220,6 +223,9 @@
|
|||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="showGroupSeparator" stdset="0">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string> MHz</string>
|
<string> MHz</string>
|
||||||
</property>
|
</property>
|
||||||
@ -227,10 +233,10 @@
|
|||||||
<number>3</number>
|
<number>3</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
<double>24.000000000000000</double>
|
<double>0.000000000000000</double>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<double>1766.000000000000000</double>
|
<double>2200.000000000000000</double>
|
||||||
</property>
|
</property>
|
||||||
<property name="value">
|
<property name="value">
|
||||||
<double>108.000000000000000</double>
|
<double>108.000000000000000</double>
|
||||||
@ -240,7 +246,7 @@
|
|||||||
<item row="2" column="0">
|
<item row="2" column="0">
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLabel" name="label">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Bin size:</string>
|
<string>&Bin size:</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="buddy">
|
<property name="buddy">
|
||||||
<cstring>binSizeSpinBox</cstring>
|
<cstring>binSizeSpinBox</cstring>
|
||||||
@ -258,14 +264,20 @@
|
|||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="showGroupSeparator" stdset="0">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string> kHz</string>
|
<string> kHz</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="decimals">
|
<property name="decimals">
|
||||||
<number>3</number>
|
<number>3</number>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<double>0.000000000000000</double>
|
||||||
|
</property>
|
||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<double>2800.000000000000000</double>
|
<double>10000.000000000000000</double>
|
||||||
</property>
|
</property>
|
||||||
<property name="value">
|
<property name="value">
|
||||||
<double>10.000000000000000</double>
|
<double>10.000000000000000</double>
|
||||||
@ -309,7 +321,7 @@
|
|||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="label_4">
|
<widget class="QLabel" name="label_4">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Interval [s]:</string>
|
<string>&Interval [s]:</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="buddy">
|
<property name="buddy">
|
||||||
<cstring>intervalSpinBox</cstring>
|
<cstring>intervalSpinBox</cstring>
|
||||||
@ -319,7 +331,7 @@
|
|||||||
<item row="0" column="1">
|
<item row="0" column="1">
|
||||||
<widget class="QLabel" name="label_6">
|
<widget class="QLabel" name="label_6">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Gain [dB]:</string>
|
<string>&Gain [dB]:</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="buddy">
|
<property name="buddy">
|
||||||
<cstring>gainSpinBox</cstring>
|
<cstring>gainSpinBox</cstring>
|
||||||
@ -339,25 +351,6 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1" colspan="2">
|
|
||||||
<widget class="QSpinBox" name="gainSpinBox">
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
|
||||||
</property>
|
|
||||||
<property name="specialValueText">
|
|
||||||
<string>auto</string>
|
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<number>-1</number>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>49</number>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<number>-1</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
<item row="2" column="0">
|
||||||
<widget class="QLabel" name="label_5">
|
<widget class="QLabel" name="label_5">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@ -463,7 +456,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="9" column="0">
|
<item row="11" column="0">
|
||||||
<spacer name="verticalSpacer_2">
|
<spacer name="verticalSpacer_2">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
@ -483,6 +476,55 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="1" column="1" colspan="2">
|
||||||
|
<widget class="QDoubleSpinBox" name="gainSpinBox">
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
<property name="specialValueText">
|
||||||
|
<string>auto</string>
|
||||||
|
</property>
|
||||||
|
<property name="decimals">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<double>-1.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<double>999.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<double>1.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<double>-1.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="9" column="0">
|
||||||
|
<widget class="QCheckBox" name="baselineCheckBox">
|
||||||
|
<property name="text">
|
||||||
|
<string>Baseline</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="9" column="2">
|
||||||
|
<widget class="QToolButton" name="baselineButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>...</string>
|
||||||
|
</property>
|
||||||
|
<property name="autoRaise">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="10" column="0">
|
||||||
|
<widget class="QCheckBox" name="subtractBaselineCheckBox">
|
||||||
|
<property name="text">
|
||||||
|
<string>Subtract baseline</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
@ -563,6 +605,9 @@
|
|||||||
<tabstop>smoothButton</tabstop>
|
<tabstop>smoothButton</tabstop>
|
||||||
<tabstop>persistenceCheckBox</tabstop>
|
<tabstop>persistenceCheckBox</tabstop>
|
||||||
<tabstop>persistenceButton</tabstop>
|
<tabstop>persistenceButton</tabstop>
|
||||||
|
<tabstop>baselineCheckBox</tabstop>
|
||||||
|
<tabstop>baselineButton</tabstop>
|
||||||
|
<tabstop>subtractBaselineCheckBox</tabstop>
|
||||||
<tabstop>histogramPlotLayout</tabstop>
|
<tabstop>histogramPlotLayout</tabstop>
|
||||||
<tabstop>mainPlotLayout</tabstop>
|
<tabstop>mainPlotLayout</tabstop>
|
||||||
<tabstop>waterfallPlotLayout</tabstop>
|
<tabstop>waterfallPlotLayout</tabstop>
|
||||||
|
115
qspectrumanalyzer/qspectrumanalyzer_baseline.ui
Normal file
115
qspectrumanalyzer/qspectrumanalyzer_baseline.ui
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
<?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>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>232</width>
|
<width>253</width>
|
||||||
<height>260</height>
|
<height>266</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
@ -19,7 +19,7 @@
|
|||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="label_2">
|
<widget class="QLabel" name="label_2">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Main curve color:</string>
|
<string>&Main curve color:</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="buddy">
|
<property name="buddy">
|
||||||
<cstring>mainColorButton</cstring>
|
<cstring>mainColorButton</cstring>
|
||||||
@ -42,7 +42,7 @@
|
|||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="label_4">
|
<widget class="QLabel" name="label_4">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Max. peak hold color:</string>
|
<string>Max. peak &hold color:</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="buddy">
|
<property name="buddy">
|
||||||
<cstring>peakHoldMaxColorButton</cstring>
|
<cstring>peakHoldMaxColorButton</cstring>
|
||||||
@ -65,7 +65,7 @@
|
|||||||
<item row="2" column="0">
|
<item row="2" column="0">
|
||||||
<widget class="QLabel" name="label_6">
|
<widget class="QLabel" name="label_6">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Min. peak hold color:</string>
|
<string>M&in. peak hold color:</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="buddy">
|
<property name="buddy">
|
||||||
<cstring>peakHoldMinColorButton</cstring>
|
<cstring>peakHoldMinColorButton</cstring>
|
||||||
@ -88,7 +88,7 @@
|
|||||||
<item row="3" column="0">
|
<item row="3" column="0">
|
||||||
<widget class="QLabel" name="label_5">
|
<widget class="QLabel" name="label_5">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Average color:</string>
|
<string>Average &color:</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="buddy">
|
<property name="buddy">
|
||||||
<cstring>averageColorButton</cstring>
|
<cstring>averageColorButton</cstring>
|
||||||
@ -111,7 +111,7 @@
|
|||||||
<item row="4" column="0">
|
<item row="4" column="0">
|
||||||
<widget class="QLabel" name="label_3">
|
<widget class="QLabel" name="label_3">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Persistence color:</string>
|
<string>Persistence co&lor:</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="buddy">
|
<property name="buddy">
|
||||||
<cstring>persistenceColorButton</cstring>
|
<cstring>persistenceColorButton</cstring>
|
||||||
@ -131,6 +131,29 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</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>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
@ -171,7 +194,7 @@
|
|||||||
<tabstop>peakHoldMinColorButton</tabstop>
|
<tabstop>peakHoldMinColorButton</tabstop>
|
||||||
<tabstop>averageColorButton</tabstop>
|
<tabstop>averageColorButton</tabstop>
|
||||||
<tabstop>persistenceColorButton</tabstop>
|
<tabstop>persistenceColorButton</tabstop>
|
||||||
<tabstop>buttonBox</tabstop>
|
<tabstop>baselineColorButton</tabstop>
|
||||||
</tabstops>
|
</tabstops>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections>
|
<connections>
|
||||||
@ -182,12 +205,12 @@
|
|||||||
<slot>accept()</slot>
|
<slot>accept()</slot>
|
||||||
<hints>
|
<hints>
|
||||||
<hint type="sourcelabel">
|
<hint type="sourcelabel">
|
||||||
<x>248</x>
|
<x>246</x>
|
||||||
<y>254</y>
|
<y>259</y>
|
||||||
</hint>
|
</hint>
|
||||||
<hint type="destinationlabel">
|
<hint type="destinationlabel">
|
||||||
<x>157</x>
|
<x>157</x>
|
||||||
<y>274</y>
|
<y>265</y>
|
||||||
</hint>
|
</hint>
|
||||||
</hints>
|
</hints>
|
||||||
</connection>
|
</connection>
|
||||||
@ -198,12 +221,12 @@
|
|||||||
<slot>reject()</slot>
|
<slot>reject()</slot>
|
||||||
<hints>
|
<hints>
|
||||||
<hint type="sourcelabel">
|
<hint type="sourcelabel">
|
||||||
<x>316</x>
|
<x>246</x>
|
||||||
<y>260</y>
|
<y>259</y>
|
||||||
</hint>
|
</hint>
|
||||||
<hint type="destinationlabel">
|
<hint type="destinationlabel">
|
||||||
<x>286</x>
|
<x>252</x>
|
||||||
<y>274</y>
|
<y>265</y>
|
||||||
</hint>
|
</hint>
|
||||||
</hints>
|
</hints>
|
||||||
</connection>
|
</connection>
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>420</width>
|
<width>600</width>
|
||||||
<height>255</height>
|
<height>388</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
@ -76,6 +76,12 @@
|
|||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QToolButton" name="executableButton">
|
<widget class="QToolButton" name="executableButton">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>50</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>...</string>
|
<string>...</string>
|
||||||
</property>
|
</property>
|
||||||
@ -83,20 +89,17 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0">
|
<item row="3" column="0">
|
||||||
<widget class="QLabel" name="label_5">
|
<widget class="QLabel" name="label_5">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Device:</string>
|
<string>&Device:</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="buddy">
|
<property name="buddy">
|
||||||
<cstring>deviceEdit</cstring>
|
<cstring>deviceEdit</cstring>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1">
|
<item row="4" column="0">
|
||||||
<widget class="QLineEdit" name="deviceEdit"/>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QLabel" name="label_4">
|
<widget class="QLabel" name="label_4">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Sa&mple rate:</string>
|
<string>Sa&mple rate:</string>
|
||||||
@ -106,23 +109,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="1">
|
<item row="7" column="0">
|
||||||
<widget class="QSpinBox" name="sampleRateSpinBox">
|
|
||||||
<property name="minimum">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>25000000</number>
|
|
||||||
</property>
|
|
||||||
<property name="singleStep">
|
|
||||||
<number>10000</number>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<number>2560000</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="0">
|
|
||||||
<widget class="QLabel" name="label_2">
|
<widget class="QLabel" name="label_2">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&Waterfall history size:</string>
|
<string>&Waterfall history size:</string>
|
||||||
@ -132,7 +119,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="1">
|
<item row="7" column="1">
|
||||||
<widget class="QSpinBox" name="waterfallHistorySizeSpinBox">
|
<widget class="QSpinBox" name="waterfallHistorySizeSpinBox">
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
<number>1</number>
|
<number>1</number>
|
||||||
@ -145,6 +132,157 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</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>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
@ -176,10 +314,14 @@
|
|||||||
<tabstop>backendComboBox</tabstop>
|
<tabstop>backendComboBox</tabstop>
|
||||||
<tabstop>executableEdit</tabstop>
|
<tabstop>executableEdit</tabstop>
|
||||||
<tabstop>executableButton</tabstop>
|
<tabstop>executableButton</tabstop>
|
||||||
|
<tabstop>paramsEdit</tabstop>
|
||||||
|
<tabstop>paramsHelpButton</tabstop>
|
||||||
<tabstop>deviceEdit</tabstop>
|
<tabstop>deviceEdit</tabstop>
|
||||||
|
<tabstop>deviceHelpButton</tabstop>
|
||||||
<tabstop>sampleRateSpinBox</tabstop>
|
<tabstop>sampleRateSpinBox</tabstop>
|
||||||
|
<tabstop>bandwidthSpinBox</tabstop>
|
||||||
|
<tabstop>lnbSpinBox</tabstop>
|
||||||
<tabstop>waterfallHistorySizeSpinBox</tabstop>
|
<tabstop>waterfallHistorySizeSpinBox</tabstop>
|
||||||
<tabstop>buttonBox</tabstop>
|
|
||||||
</tabstops>
|
</tabstops>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections>
|
<connections>
|
||||||
@ -190,8 +332,8 @@
|
|||||||
<slot>accept()</slot>
|
<slot>accept()</slot>
|
||||||
<hints>
|
<hints>
|
||||||
<hint type="sourcelabel">
|
<hint type="sourcelabel">
|
||||||
<x>242</x>
|
<x>254</x>
|
||||||
<y>248</y>
|
<y>377</y>
|
||||||
</hint>
|
</hint>
|
||||||
<hint type="destinationlabel">
|
<hint type="destinationlabel">
|
||||||
<x>157</x>
|
<x>157</x>
|
||||||
@ -206,8 +348,8 @@
|
|||||||
<slot>reject()</slot>
|
<slot>reject()</slot>
|
||||||
<hints>
|
<hints>
|
||||||
<hint type="sourcelabel">
|
<hint type="sourcelabel">
|
||||||
<x>310</x>
|
<x>322</x>
|
||||||
<y>248</y>
|
<y>377</y>
|
||||||
</hint>
|
</hint>
|
||||||
<hint type="destinationlabel">
|
<hint type="destinationlabel">
|
||||||
<x>286</x>
|
<x>286</x>
|
||||||
|
78
qspectrumanalyzer/qspectrumanalyzer_settings_help.ui
Normal file
78
qspectrumanalyzer/qspectrumanalyzer_settings_help.ui
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
<?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"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<ui version="4.0">
|
<ui version="4.0">
|
||||||
<class>QSpectrumAnalyzerSmooth</class>
|
<class>QSpectrumAnalyzerSmoothing</class>
|
||||||
<widget class="QDialog" name="QSpectrumAnalyzerSmooth">
|
<widget class="QDialog" name="QSpectrumAnalyzerSmoothing">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
@ -118,7 +118,7 @@
|
|||||||
<connection>
|
<connection>
|
||||||
<sender>buttonBox</sender>
|
<sender>buttonBox</sender>
|
||||||
<signal>accepted()</signal>
|
<signal>accepted()</signal>
|
||||||
<receiver>QSpectrumAnalyzerSmooth</receiver>
|
<receiver>QSpectrumAnalyzerSmoothing</receiver>
|
||||||
<slot>accept()</slot>
|
<slot>accept()</slot>
|
||||||
<hints>
|
<hints>
|
||||||
<hint type="sourcelabel">
|
<hint type="sourcelabel">
|
||||||
@ -134,7 +134,7 @@
|
|||||||
<connection>
|
<connection>
|
||||||
<sender>buttonBox</sender>
|
<sender>buttonBox</sender>
|
||||||
<signal>rejected()</signal>
|
<signal>rejected()</signal>
|
||||||
<receiver>QSpectrumAnalyzerSmooth</receiver>
|
<receiver>QSpectrumAnalyzerSmoothing</receiver>
|
||||||
<slot>reject()</slot>
|
<slot>reject()</slot>
|
||||||
<hints>
|
<hints>
|
||||||
<hint type="sourcelabel">
|
<hint type="sourcelabel">
|
139
qspectrumanalyzer/settings.py
Normal file
139
qspectrumanalyzer/settings.py
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
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)
|
29
qspectrumanalyzer/smoothing.py
Normal file
29
qspectrumanalyzer/smoothing.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
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)
|
81
qspectrumanalyzer/subprocess.py
Normal file
81
qspectrumanalyzer/subprocess.py
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
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,273 +2,275 @@
|
|||||||
|
|
||||||
# Form implementation generated from reading ui file 'qspectrumanalyzer/qspectrumanalyzer.ui'
|
# Form implementation generated from reading ui file 'qspectrumanalyzer/qspectrumanalyzer.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt4 UI code generator 4.12
|
# Created by: PyQt5 UI code generator 5.8
|
||||||
#
|
#
|
||||||
# WARNING! All changes made in this file will be lost!
|
# WARNING! All changes made in this file will be lost!
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from Qt import QtCore, QtGui, QtWidgets
|
||||||
|
|
||||||
try:
|
|
||||||
_fromUtf8 = QtCore.QString.fromUtf8
|
|
||||||
except AttributeError:
|
|
||||||
def _fromUtf8(s):
|
|
||||||
return s
|
|
||||||
|
|
||||||
try:
|
|
||||||
_encoding = QtGui.QApplication.UnicodeUTF8
|
|
||||||
def _translate(context, text, disambig):
|
|
||||||
return QtGui.QApplication.translate(context, text, disambig, _encoding)
|
|
||||||
except AttributeError:
|
|
||||||
def _translate(context, text, disambig):
|
|
||||||
return QtGui.QApplication.translate(context, text, disambig)
|
|
||||||
|
|
||||||
class Ui_QSpectrumAnalyzerMainWindow(object):
|
class Ui_QSpectrumAnalyzerMainWindow(object):
|
||||||
def setupUi(self, QSpectrumAnalyzerMainWindow):
|
def setupUi(self, QSpectrumAnalyzerMainWindow):
|
||||||
QSpectrumAnalyzerMainWindow.setObjectName(_fromUtf8("QSpectrumAnalyzerMainWindow"))
|
QSpectrumAnalyzerMainWindow.setObjectName("QSpectrumAnalyzerMainWindow")
|
||||||
QSpectrumAnalyzerMainWindow.resize(1200, 810)
|
QSpectrumAnalyzerMainWindow.resize(1200, 892)
|
||||||
self.centralwidget = QtGui.QWidget(QSpectrumAnalyzerMainWindow)
|
self.centralwidget = QtWidgets.QWidget(QSpectrumAnalyzerMainWindow)
|
||||||
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
|
self.centralwidget.setObjectName("centralwidget")
|
||||||
self.horizontalLayout = QtGui.QHBoxLayout(self.centralwidget)
|
self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget)
|
||||||
self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
|
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||||
self.plotSplitter = QtGui.QSplitter(self.centralwidget)
|
self.plotSplitter = QtWidgets.QSplitter(self.centralwidget)
|
||||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
|
||||||
sizePolicy.setHorizontalStretch(0)
|
sizePolicy.setHorizontalStretch(0)
|
||||||
sizePolicy.setVerticalStretch(0)
|
sizePolicy.setVerticalStretch(0)
|
||||||
sizePolicy.setHeightForWidth(self.plotSplitter.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.plotSplitter.sizePolicy().hasHeightForWidth())
|
||||||
self.plotSplitter.setSizePolicy(sizePolicy)
|
self.plotSplitter.setSizePolicy(sizePolicy)
|
||||||
self.plotSplitter.setOrientation(QtCore.Qt.Vertical)
|
self.plotSplitter.setOrientation(QtCore.Qt.Vertical)
|
||||||
self.plotSplitter.setObjectName(_fromUtf8("plotSplitter"))
|
self.plotSplitter.setObjectName("plotSplitter")
|
||||||
self.mainPlotLayout = GraphicsLayoutWidget(self.plotSplitter)
|
self.mainPlotLayout = GraphicsLayoutWidget(self.plotSplitter)
|
||||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
|
||||||
sizePolicy.setHorizontalStretch(0)
|
sizePolicy.setHorizontalStretch(0)
|
||||||
sizePolicy.setVerticalStretch(0)
|
sizePolicy.setVerticalStretch(0)
|
||||||
sizePolicy.setHeightForWidth(self.mainPlotLayout.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.mainPlotLayout.sizePolicy().hasHeightForWidth())
|
||||||
self.mainPlotLayout.setSizePolicy(sizePolicy)
|
self.mainPlotLayout.setSizePolicy(sizePolicy)
|
||||||
self.mainPlotLayout.setObjectName(_fromUtf8("mainPlotLayout"))
|
self.mainPlotLayout.setObjectName("mainPlotLayout")
|
||||||
self.waterfallPlotLayout = GraphicsLayoutWidget(self.plotSplitter)
|
self.waterfallPlotLayout = GraphicsLayoutWidget(self.plotSplitter)
|
||||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
|
||||||
sizePolicy.setHorizontalStretch(0)
|
sizePolicy.setHorizontalStretch(0)
|
||||||
sizePolicy.setVerticalStretch(0)
|
sizePolicy.setVerticalStretch(0)
|
||||||
sizePolicy.setHeightForWidth(self.waterfallPlotLayout.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.waterfallPlotLayout.sizePolicy().hasHeightForWidth())
|
||||||
self.waterfallPlotLayout.setSizePolicy(sizePolicy)
|
self.waterfallPlotLayout.setSizePolicy(sizePolicy)
|
||||||
self.waterfallPlotLayout.setObjectName(_fromUtf8("waterfallPlotLayout"))
|
self.waterfallPlotLayout.setObjectName("waterfallPlotLayout")
|
||||||
self.horizontalLayout.addWidget(self.plotSplitter)
|
self.horizontalLayout.addWidget(self.plotSplitter)
|
||||||
QSpectrumAnalyzerMainWindow.setCentralWidget(self.centralwidget)
|
QSpectrumAnalyzerMainWindow.setCentralWidget(self.centralwidget)
|
||||||
self.menubar = QtGui.QMenuBar(QSpectrumAnalyzerMainWindow)
|
self.menubar = QtWidgets.QMenuBar(QSpectrumAnalyzerMainWindow)
|
||||||
self.menubar.setGeometry(QtCore.QRect(0, 0, 1200, 30))
|
self.menubar.setGeometry(QtCore.QRect(0, 0, 1200, 32))
|
||||||
self.menubar.setObjectName(_fromUtf8("menubar"))
|
self.menubar.setObjectName("menubar")
|
||||||
self.menu_File = QtGui.QMenu(self.menubar)
|
self.menu_File = QtWidgets.QMenu(self.menubar)
|
||||||
self.menu_File.setObjectName(_fromUtf8("menu_File"))
|
self.menu_File.setObjectName("menu_File")
|
||||||
self.menu_Help = QtGui.QMenu(self.menubar)
|
self.menu_Help = QtWidgets.QMenu(self.menubar)
|
||||||
self.menu_Help.setObjectName(_fromUtf8("menu_Help"))
|
self.menu_Help.setObjectName("menu_Help")
|
||||||
QSpectrumAnalyzerMainWindow.setMenuBar(self.menubar)
|
QSpectrumAnalyzerMainWindow.setMenuBar(self.menubar)
|
||||||
self.statusbar = QtGui.QStatusBar(QSpectrumAnalyzerMainWindow)
|
self.statusbar = QtWidgets.QStatusBar(QSpectrumAnalyzerMainWindow)
|
||||||
self.statusbar.setObjectName(_fromUtf8("statusbar"))
|
self.statusbar.setObjectName("statusbar")
|
||||||
QSpectrumAnalyzerMainWindow.setStatusBar(self.statusbar)
|
QSpectrumAnalyzerMainWindow.setStatusBar(self.statusbar)
|
||||||
self.controlsDockWidget = QtGui.QDockWidget(QSpectrumAnalyzerMainWindow)
|
self.controlsDockWidget = QtWidgets.QDockWidget(QSpectrumAnalyzerMainWindow)
|
||||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Minimum)
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
|
||||||
sizePolicy.setHorizontalStretch(0)
|
sizePolicy.setHorizontalStretch(0)
|
||||||
sizePolicy.setVerticalStretch(0)
|
sizePolicy.setVerticalStretch(0)
|
||||||
sizePolicy.setHeightForWidth(self.controlsDockWidget.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.controlsDockWidget.sizePolicy().hasHeightForWidth())
|
||||||
self.controlsDockWidget.setSizePolicy(sizePolicy)
|
self.controlsDockWidget.setSizePolicy(sizePolicy)
|
||||||
self.controlsDockWidget.setMinimumSize(QtCore.QSize(10, 10))
|
self.controlsDockWidget.setMinimumSize(QtCore.QSize(190, 130))
|
||||||
self.controlsDockWidget.setFeatures(QtGui.QDockWidget.DockWidgetFloatable|QtGui.QDockWidget.DockWidgetMovable)
|
self.controlsDockWidget.setFeatures(QtWidgets.QDockWidget.DockWidgetFloatable|QtWidgets.QDockWidget.DockWidgetMovable)
|
||||||
self.controlsDockWidget.setObjectName(_fromUtf8("controlsDockWidget"))
|
self.controlsDockWidget.setObjectName("controlsDockWidget")
|
||||||
self.controlsDockWidgetContents = QtGui.QWidget()
|
self.controlsDockWidgetContents = QtWidgets.QWidget()
|
||||||
self.controlsDockWidgetContents.setObjectName(_fromUtf8("controlsDockWidgetContents"))
|
self.controlsDockWidgetContents.setObjectName("controlsDockWidgetContents")
|
||||||
self.gridLayout_2 = QtGui.QGridLayout(self.controlsDockWidgetContents)
|
self.gridLayout_2 = QtWidgets.QGridLayout(self.controlsDockWidgetContents)
|
||||||
self.gridLayout_2.setMargin(0)
|
self.gridLayout_2.setContentsMargins(0, 0, 0, 0)
|
||||||
self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
|
self.gridLayout_2.setObjectName("gridLayout_2")
|
||||||
self.startButton = QtGui.QPushButton(self.controlsDockWidgetContents)
|
self.startButton = QtWidgets.QPushButton(self.controlsDockWidgetContents)
|
||||||
self.startButton.setObjectName(_fromUtf8("startButton"))
|
self.startButton.setObjectName("startButton")
|
||||||
self.gridLayout_2.addWidget(self.startButton, 0, 0, 1, 1)
|
self.gridLayout_2.addWidget(self.startButton, 0, 0, 1, 1)
|
||||||
self.stopButton = QtGui.QPushButton(self.controlsDockWidgetContents)
|
self.stopButton = QtWidgets.QPushButton(self.controlsDockWidgetContents)
|
||||||
self.stopButton.setObjectName(_fromUtf8("stopButton"))
|
self.stopButton.setObjectName("stopButton")
|
||||||
self.gridLayout_2.addWidget(self.stopButton, 0, 1, 1, 1)
|
self.gridLayout_2.addWidget(self.stopButton, 0, 1, 1, 1)
|
||||||
self.singleShotButton = QtGui.QPushButton(self.controlsDockWidgetContents)
|
self.singleShotButton = QtWidgets.QPushButton(self.controlsDockWidgetContents)
|
||||||
self.singleShotButton.setObjectName(_fromUtf8("singleShotButton"))
|
self.singleShotButton.setObjectName("singleShotButton")
|
||||||
self.gridLayout_2.addWidget(self.singleShotButton, 1, 0, 1, 2)
|
self.gridLayout_2.addWidget(self.singleShotButton, 1, 0, 1, 2)
|
||||||
spacerItem = QtGui.QSpacerItem(20, 561, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
spacerItem = QtWidgets.QSpacerItem(20, 561, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||||
self.gridLayout_2.addItem(spacerItem, 2, 0, 1, 1)
|
self.gridLayout_2.addItem(spacerItem, 2, 0, 1, 1)
|
||||||
self.controlsDockWidget.setWidget(self.controlsDockWidgetContents)
|
self.controlsDockWidget.setWidget(self.controlsDockWidgetContents)
|
||||||
QSpectrumAnalyzerMainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.controlsDockWidget)
|
QSpectrumAnalyzerMainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.controlsDockWidget)
|
||||||
self.frequencyDockWidget = QtGui.QDockWidget(QSpectrumAnalyzerMainWindow)
|
self.frequencyDockWidget = QtWidgets.QDockWidget(QSpectrumAnalyzerMainWindow)
|
||||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Minimum)
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
|
||||||
sizePolicy.setHorizontalStretch(0)
|
sizePolicy.setHorizontalStretch(0)
|
||||||
sizePolicy.setVerticalStretch(0)
|
sizePolicy.setVerticalStretch(0)
|
||||||
sizePolicy.setHeightForWidth(self.frequencyDockWidget.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.frequencyDockWidget.sizePolicy().hasHeightForWidth())
|
||||||
self.frequencyDockWidget.setSizePolicy(sizePolicy)
|
self.frequencyDockWidget.setSizePolicy(sizePolicy)
|
||||||
self.frequencyDockWidget.setMinimumSize(QtCore.QSize(10, 10))
|
self.frequencyDockWidget.setMinimumSize(QtCore.QSize(208, 166))
|
||||||
self.frequencyDockWidget.setFeatures(QtGui.QDockWidget.DockWidgetFloatable|QtGui.QDockWidget.DockWidgetMovable)
|
self.frequencyDockWidget.setFeatures(QtWidgets.QDockWidget.DockWidgetFloatable|QtWidgets.QDockWidget.DockWidgetMovable)
|
||||||
self.frequencyDockWidget.setObjectName(_fromUtf8("frequencyDockWidget"))
|
self.frequencyDockWidget.setObjectName("frequencyDockWidget")
|
||||||
self.frequencyDockWidgetContents = QtGui.QWidget()
|
self.frequencyDockWidgetContents = QtWidgets.QWidget()
|
||||||
self.frequencyDockWidgetContents.setObjectName(_fromUtf8("frequencyDockWidgetContents"))
|
self.frequencyDockWidgetContents.setObjectName("frequencyDockWidgetContents")
|
||||||
self.formLayout = QtGui.QFormLayout(self.frequencyDockWidgetContents)
|
self.formLayout = QtWidgets.QFormLayout(self.frequencyDockWidgetContents)
|
||||||
self.formLayout.setFieldGrowthPolicy(QtGui.QFormLayout.ExpandingFieldsGrow)
|
self.formLayout.setFieldGrowthPolicy(QtWidgets.QFormLayout.ExpandingFieldsGrow)
|
||||||
self.formLayout.setMargin(0)
|
self.formLayout.setContentsMargins(0, 0, 0, 0)
|
||||||
self.formLayout.setObjectName(_fromUtf8("formLayout"))
|
self.formLayout.setObjectName("formLayout")
|
||||||
self.label_2 = QtGui.QLabel(self.frequencyDockWidgetContents)
|
self.label_2 = QtWidgets.QLabel(self.frequencyDockWidgetContents)
|
||||||
self.label_2.setObjectName(_fromUtf8("label_2"))
|
self.label_2.setObjectName("label_2")
|
||||||
self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.label_2)
|
self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.label_2)
|
||||||
self.startFreqSpinBox = QtGui.QDoubleSpinBox(self.frequencyDockWidgetContents)
|
self.startFreqSpinBox = QtWidgets.QDoubleSpinBox(self.frequencyDockWidgetContents)
|
||||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||||
sizePolicy.setHorizontalStretch(0)
|
sizePolicy.setHorizontalStretch(0)
|
||||||
sizePolicy.setVerticalStretch(0)
|
sizePolicy.setVerticalStretch(0)
|
||||||
sizePolicy.setHeightForWidth(self.startFreqSpinBox.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.startFreqSpinBox.sizePolicy().hasHeightForWidth())
|
||||||
self.startFreqSpinBox.setSizePolicy(sizePolicy)
|
self.startFreqSpinBox.setSizePolicy(sizePolicy)
|
||||||
self.startFreqSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
self.startFreqSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||||
|
self.startFreqSpinBox.setProperty("showGroupSeparator", True)
|
||||||
self.startFreqSpinBox.setDecimals(3)
|
self.startFreqSpinBox.setDecimals(3)
|
||||||
self.startFreqSpinBox.setMinimum(24.0)
|
self.startFreqSpinBox.setMinimum(0.0)
|
||||||
self.startFreqSpinBox.setMaximum(1766.0)
|
self.startFreqSpinBox.setMaximum(2200.0)
|
||||||
self.startFreqSpinBox.setProperty("value", 87.0)
|
self.startFreqSpinBox.setProperty("value", 87.0)
|
||||||
self.startFreqSpinBox.setObjectName(_fromUtf8("startFreqSpinBox"))
|
self.startFreqSpinBox.setObjectName("startFreqSpinBox")
|
||||||
self.formLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.startFreqSpinBox)
|
self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.startFreqSpinBox)
|
||||||
self.label_3 = QtGui.QLabel(self.frequencyDockWidgetContents)
|
self.label_3 = QtWidgets.QLabel(self.frequencyDockWidgetContents)
|
||||||
self.label_3.setObjectName(_fromUtf8("label_3"))
|
self.label_3.setObjectName("label_3")
|
||||||
self.formLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.label_3)
|
self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label_3)
|
||||||
self.stopFreqSpinBox = QtGui.QDoubleSpinBox(self.frequencyDockWidgetContents)
|
self.stopFreqSpinBox = QtWidgets.QDoubleSpinBox(self.frequencyDockWidgetContents)
|
||||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||||
sizePolicy.setHorizontalStretch(0)
|
sizePolicy.setHorizontalStretch(0)
|
||||||
sizePolicy.setVerticalStretch(0)
|
sizePolicy.setVerticalStretch(0)
|
||||||
sizePolicy.setHeightForWidth(self.stopFreqSpinBox.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.stopFreqSpinBox.sizePolicy().hasHeightForWidth())
|
||||||
self.stopFreqSpinBox.setSizePolicy(sizePolicy)
|
self.stopFreqSpinBox.setSizePolicy(sizePolicy)
|
||||||
self.stopFreqSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
self.stopFreqSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||||
|
self.stopFreqSpinBox.setProperty("showGroupSeparator", True)
|
||||||
self.stopFreqSpinBox.setDecimals(3)
|
self.stopFreqSpinBox.setDecimals(3)
|
||||||
self.stopFreqSpinBox.setMinimum(24.0)
|
self.stopFreqSpinBox.setMinimum(0.0)
|
||||||
self.stopFreqSpinBox.setMaximum(1766.0)
|
self.stopFreqSpinBox.setMaximum(2200.0)
|
||||||
self.stopFreqSpinBox.setProperty("value", 108.0)
|
self.stopFreqSpinBox.setProperty("value", 108.0)
|
||||||
self.stopFreqSpinBox.setObjectName(_fromUtf8("stopFreqSpinBox"))
|
self.stopFreqSpinBox.setObjectName("stopFreqSpinBox")
|
||||||
self.formLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.stopFreqSpinBox)
|
self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.stopFreqSpinBox)
|
||||||
self.label = QtGui.QLabel(self.frequencyDockWidgetContents)
|
self.label = QtWidgets.QLabel(self.frequencyDockWidgetContents)
|
||||||
self.label.setObjectName(_fromUtf8("label"))
|
self.label.setObjectName("label")
|
||||||
self.formLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.label)
|
self.formLayout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.label)
|
||||||
self.binSizeSpinBox = QtGui.QDoubleSpinBox(self.frequencyDockWidgetContents)
|
self.binSizeSpinBox = QtWidgets.QDoubleSpinBox(self.frequencyDockWidgetContents)
|
||||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||||
sizePolicy.setHorizontalStretch(0)
|
sizePolicy.setHorizontalStretch(0)
|
||||||
sizePolicy.setVerticalStretch(0)
|
sizePolicy.setVerticalStretch(0)
|
||||||
sizePolicy.setHeightForWidth(self.binSizeSpinBox.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.binSizeSpinBox.sizePolicy().hasHeightForWidth())
|
||||||
self.binSizeSpinBox.setSizePolicy(sizePolicy)
|
self.binSizeSpinBox.setSizePolicy(sizePolicy)
|
||||||
self.binSizeSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
self.binSizeSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||||
|
self.binSizeSpinBox.setProperty("showGroupSeparator", True)
|
||||||
self.binSizeSpinBox.setDecimals(3)
|
self.binSizeSpinBox.setDecimals(3)
|
||||||
self.binSizeSpinBox.setMaximum(2800.0)
|
self.binSizeSpinBox.setMinimum(0.0)
|
||||||
|
self.binSizeSpinBox.setMaximum(10000.0)
|
||||||
self.binSizeSpinBox.setProperty("value", 10.0)
|
self.binSizeSpinBox.setProperty("value", 10.0)
|
||||||
self.binSizeSpinBox.setObjectName(_fromUtf8("binSizeSpinBox"))
|
self.binSizeSpinBox.setObjectName("binSizeSpinBox")
|
||||||
self.formLayout.setWidget(2, QtGui.QFormLayout.FieldRole, self.binSizeSpinBox)
|
self.formLayout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.binSizeSpinBox)
|
||||||
spacerItem1 = QtGui.QSpacerItem(20, 0, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
spacerItem1 = QtWidgets.QSpacerItem(20, 0, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||||
self.formLayout.setItem(3, QtGui.QFormLayout.SpanningRole, spacerItem1)
|
self.formLayout.setItem(3, QtWidgets.QFormLayout.SpanningRole, spacerItem1)
|
||||||
self.frequencyDockWidget.setWidget(self.frequencyDockWidgetContents)
|
self.frequencyDockWidget.setWidget(self.frequencyDockWidgetContents)
|
||||||
QSpectrumAnalyzerMainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.frequencyDockWidget)
|
QSpectrumAnalyzerMainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.frequencyDockWidget)
|
||||||
self.settingsDockWidget = QtGui.QDockWidget(QSpectrumAnalyzerMainWindow)
|
self.settingsDockWidget = QtWidgets.QDockWidget(QSpectrumAnalyzerMainWindow)
|
||||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Expanding)
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding)
|
||||||
sizePolicy.setHorizontalStretch(0)
|
sizePolicy.setHorizontalStretch(0)
|
||||||
sizePolicy.setVerticalStretch(0)
|
sizePolicy.setVerticalStretch(0)
|
||||||
sizePolicy.setHeightForWidth(self.settingsDockWidget.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.settingsDockWidget.sizePolicy().hasHeightForWidth())
|
||||||
self.settingsDockWidget.setSizePolicy(sizePolicy)
|
self.settingsDockWidget.setSizePolicy(sizePolicy)
|
||||||
self.settingsDockWidget.setFeatures(QtGui.QDockWidget.DockWidgetFloatable|QtGui.QDockWidget.DockWidgetMovable)
|
self.settingsDockWidget.setFeatures(QtWidgets.QDockWidget.DockWidgetFloatable|QtWidgets.QDockWidget.DockWidgetMovable)
|
||||||
self.settingsDockWidget.setObjectName(_fromUtf8("settingsDockWidget"))
|
self.settingsDockWidget.setObjectName("settingsDockWidget")
|
||||||
self.settingsDockWidgetContents = QtGui.QWidget()
|
self.settingsDockWidgetContents = QtWidgets.QWidget()
|
||||||
self.settingsDockWidgetContents.setObjectName(_fromUtf8("settingsDockWidgetContents"))
|
self.settingsDockWidgetContents.setObjectName("settingsDockWidgetContents")
|
||||||
self.gridLayout = QtGui.QGridLayout(self.settingsDockWidgetContents)
|
self.gridLayout = QtWidgets.QGridLayout(self.settingsDockWidgetContents)
|
||||||
self.gridLayout.setMargin(0)
|
self.gridLayout.setContentsMargins(0, 0, 0, 0)
|
||||||
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
|
self.gridLayout.setObjectName("gridLayout")
|
||||||
self.label_4 = QtGui.QLabel(self.settingsDockWidgetContents)
|
self.label_4 = QtWidgets.QLabel(self.settingsDockWidgetContents)
|
||||||
self.label_4.setObjectName(_fromUtf8("label_4"))
|
self.label_4.setObjectName("label_4")
|
||||||
self.gridLayout.addWidget(self.label_4, 0, 0, 1, 1)
|
self.gridLayout.addWidget(self.label_4, 0, 0, 1, 1)
|
||||||
self.label_6 = QtGui.QLabel(self.settingsDockWidgetContents)
|
self.label_6 = QtWidgets.QLabel(self.settingsDockWidgetContents)
|
||||||
self.label_6.setObjectName(_fromUtf8("label_6"))
|
self.label_6.setObjectName("label_6")
|
||||||
self.gridLayout.addWidget(self.label_6, 0, 1, 1, 1)
|
self.gridLayout.addWidget(self.label_6, 0, 1, 1, 1)
|
||||||
self.intervalSpinBox = QtGui.QDoubleSpinBox(self.settingsDockWidgetContents)
|
self.intervalSpinBox = QtWidgets.QDoubleSpinBox(self.settingsDockWidgetContents)
|
||||||
self.intervalSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
self.intervalSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||||
self.intervalSpinBox.setMaximum(999.0)
|
self.intervalSpinBox.setMaximum(999.0)
|
||||||
self.intervalSpinBox.setProperty("value", 1.0)
|
self.intervalSpinBox.setProperty("value", 1.0)
|
||||||
self.intervalSpinBox.setObjectName(_fromUtf8("intervalSpinBox"))
|
self.intervalSpinBox.setObjectName("intervalSpinBox")
|
||||||
self.gridLayout.addWidget(self.intervalSpinBox, 1, 0, 1, 1)
|
self.gridLayout.addWidget(self.intervalSpinBox, 1, 0, 1, 1)
|
||||||
self.gainSpinBox = QtGui.QSpinBox(self.settingsDockWidgetContents)
|
self.label_5 = QtWidgets.QLabel(self.settingsDockWidgetContents)
|
||||||
self.gainSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
self.label_5.setObjectName("label_5")
|
||||||
self.gainSpinBox.setMinimum(-1)
|
|
||||||
self.gainSpinBox.setMaximum(49)
|
|
||||||
self.gainSpinBox.setProperty("value", -1)
|
|
||||||
self.gainSpinBox.setObjectName(_fromUtf8("gainSpinBox"))
|
|
||||||
self.gridLayout.addWidget(self.gainSpinBox, 1, 1, 1, 2)
|
|
||||||
self.label_5 = QtGui.QLabel(self.settingsDockWidgetContents)
|
|
||||||
self.label_5.setObjectName(_fromUtf8("label_5"))
|
|
||||||
self.gridLayout.addWidget(self.label_5, 2, 0, 1, 1)
|
self.gridLayout.addWidget(self.label_5, 2, 0, 1, 1)
|
||||||
self.label_7 = QtGui.QLabel(self.settingsDockWidgetContents)
|
self.label_7 = QtWidgets.QLabel(self.settingsDockWidgetContents)
|
||||||
self.label_7.setObjectName(_fromUtf8("label_7"))
|
self.label_7.setObjectName("label_7")
|
||||||
self.gridLayout.addWidget(self.label_7, 2, 1, 1, 1)
|
self.gridLayout.addWidget(self.label_7, 2, 1, 1, 1)
|
||||||
self.ppmSpinBox = QtGui.QSpinBox(self.settingsDockWidgetContents)
|
self.ppmSpinBox = QtWidgets.QSpinBox(self.settingsDockWidgetContents)
|
||||||
self.ppmSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
self.ppmSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||||
self.ppmSpinBox.setMinimum(-999)
|
self.ppmSpinBox.setMinimum(-999)
|
||||||
self.ppmSpinBox.setMaximum(999)
|
self.ppmSpinBox.setMaximum(999)
|
||||||
self.ppmSpinBox.setObjectName(_fromUtf8("ppmSpinBox"))
|
self.ppmSpinBox.setObjectName("ppmSpinBox")
|
||||||
self.gridLayout.addWidget(self.ppmSpinBox, 3, 0, 1, 1)
|
self.gridLayout.addWidget(self.ppmSpinBox, 3, 0, 1, 1)
|
||||||
self.mainCurveCheckBox = QtGui.QCheckBox(self.settingsDockWidgetContents)
|
self.mainCurveCheckBox = QtWidgets.QCheckBox(self.settingsDockWidgetContents)
|
||||||
self.mainCurveCheckBox.setChecked(True)
|
self.mainCurveCheckBox.setChecked(True)
|
||||||
self.mainCurveCheckBox.setObjectName(_fromUtf8("mainCurveCheckBox"))
|
self.mainCurveCheckBox.setObjectName("mainCurveCheckBox")
|
||||||
self.gridLayout.addWidget(self.mainCurveCheckBox, 4, 0, 1, 1)
|
self.gridLayout.addWidget(self.mainCurveCheckBox, 4, 0, 1, 1)
|
||||||
self.colorsButton = QtGui.QPushButton(self.settingsDockWidgetContents)
|
self.colorsButton = QtWidgets.QPushButton(self.settingsDockWidgetContents)
|
||||||
self.colorsButton.setObjectName(_fromUtf8("colorsButton"))
|
self.colorsButton.setObjectName("colorsButton")
|
||||||
self.gridLayout.addWidget(self.colorsButton, 4, 1, 1, 2)
|
self.gridLayout.addWidget(self.colorsButton, 4, 1, 1, 2)
|
||||||
self.peakHoldMaxCheckBox = QtGui.QCheckBox(self.settingsDockWidgetContents)
|
self.peakHoldMaxCheckBox = QtWidgets.QCheckBox(self.settingsDockWidgetContents)
|
||||||
self.peakHoldMaxCheckBox.setObjectName(_fromUtf8("peakHoldMaxCheckBox"))
|
self.peakHoldMaxCheckBox.setObjectName("peakHoldMaxCheckBox")
|
||||||
self.gridLayout.addWidget(self.peakHoldMaxCheckBox, 5, 0, 1, 1)
|
self.gridLayout.addWidget(self.peakHoldMaxCheckBox, 5, 0, 1, 1)
|
||||||
self.peakHoldMinCheckBox = QtGui.QCheckBox(self.settingsDockWidgetContents)
|
self.peakHoldMinCheckBox = QtWidgets.QCheckBox(self.settingsDockWidgetContents)
|
||||||
self.peakHoldMinCheckBox.setObjectName(_fromUtf8("peakHoldMinCheckBox"))
|
self.peakHoldMinCheckBox.setObjectName("peakHoldMinCheckBox")
|
||||||
self.gridLayout.addWidget(self.peakHoldMinCheckBox, 5, 1, 1, 2)
|
self.gridLayout.addWidget(self.peakHoldMinCheckBox, 5, 1, 1, 2)
|
||||||
self.averageCheckBox = QtGui.QCheckBox(self.settingsDockWidgetContents)
|
self.averageCheckBox = QtWidgets.QCheckBox(self.settingsDockWidgetContents)
|
||||||
self.averageCheckBox.setObjectName(_fromUtf8("averageCheckBox"))
|
self.averageCheckBox.setObjectName("averageCheckBox")
|
||||||
self.gridLayout.addWidget(self.averageCheckBox, 6, 0, 1, 1)
|
self.gridLayout.addWidget(self.averageCheckBox, 6, 0, 1, 1)
|
||||||
self.smoothCheckBox = QtGui.QCheckBox(self.settingsDockWidgetContents)
|
self.smoothCheckBox = QtWidgets.QCheckBox(self.settingsDockWidgetContents)
|
||||||
self.smoothCheckBox.setObjectName(_fromUtf8("smoothCheckBox"))
|
self.smoothCheckBox.setObjectName("smoothCheckBox")
|
||||||
self.gridLayout.addWidget(self.smoothCheckBox, 7, 0, 1, 1)
|
self.gridLayout.addWidget(self.smoothCheckBox, 7, 0, 1, 1)
|
||||||
self.smoothButton = QtGui.QToolButton(self.settingsDockWidgetContents)
|
self.smoothButton = QtWidgets.QToolButton(self.settingsDockWidgetContents)
|
||||||
self.smoothButton.setAutoRaise(False)
|
self.smoothButton.setAutoRaise(False)
|
||||||
self.smoothButton.setObjectName(_fromUtf8("smoothButton"))
|
self.smoothButton.setObjectName("smoothButton")
|
||||||
self.gridLayout.addWidget(self.smoothButton, 7, 2, 1, 1)
|
self.gridLayout.addWidget(self.smoothButton, 7, 2, 1, 1)
|
||||||
self.persistenceCheckBox = QtGui.QCheckBox(self.settingsDockWidgetContents)
|
self.persistenceCheckBox = QtWidgets.QCheckBox(self.settingsDockWidgetContents)
|
||||||
self.persistenceCheckBox.setObjectName(_fromUtf8("persistenceCheckBox"))
|
self.persistenceCheckBox.setObjectName("persistenceCheckBox")
|
||||||
self.gridLayout.addWidget(self.persistenceCheckBox, 8, 0, 1, 1)
|
self.gridLayout.addWidget(self.persistenceCheckBox, 8, 0, 1, 1)
|
||||||
self.persistenceButton = QtGui.QToolButton(self.settingsDockWidgetContents)
|
self.persistenceButton = QtWidgets.QToolButton(self.settingsDockWidgetContents)
|
||||||
self.persistenceButton.setAutoRaise(False)
|
self.persistenceButton.setAutoRaise(False)
|
||||||
self.persistenceButton.setObjectName(_fromUtf8("persistenceButton"))
|
self.persistenceButton.setObjectName("persistenceButton")
|
||||||
self.gridLayout.addWidget(self.persistenceButton, 8, 2, 1, 1)
|
self.gridLayout.addWidget(self.persistenceButton, 8, 2, 1, 1)
|
||||||
spacerItem2 = QtGui.QSpacerItem(20, 1, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
spacerItem2 = QtWidgets.QSpacerItem(20, 1, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||||
self.gridLayout.addItem(spacerItem2, 9, 0, 1, 1)
|
self.gridLayout.addItem(spacerItem2, 11, 0, 1, 1)
|
||||||
self.cropSpinBox = QtGui.QSpinBox(self.settingsDockWidgetContents)
|
self.cropSpinBox = QtWidgets.QSpinBox(self.settingsDockWidgetContents)
|
||||||
self.cropSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
self.cropSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||||
self.cropSpinBox.setObjectName(_fromUtf8("cropSpinBox"))
|
self.cropSpinBox.setObjectName("cropSpinBox")
|
||||||
self.gridLayout.addWidget(self.cropSpinBox, 3, 1, 1, 2)
|
self.gridLayout.addWidget(self.cropSpinBox, 3, 1, 1, 2)
|
||||||
|
self.gainSpinBox = QtWidgets.QDoubleSpinBox(self.settingsDockWidgetContents)
|
||||||
|
self.gainSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||||
|
self.gainSpinBox.setDecimals(1)
|
||||||
|
self.gainSpinBox.setMinimum(-1.0)
|
||||||
|
self.gainSpinBox.setMaximum(999.0)
|
||||||
|
self.gainSpinBox.setSingleStep(1.0)
|
||||||
|
self.gainSpinBox.setProperty("value", -1.0)
|
||||||
|
self.gainSpinBox.setObjectName("gainSpinBox")
|
||||||
|
self.gridLayout.addWidget(self.gainSpinBox, 1, 1, 1, 2)
|
||||||
|
self.baselineCheckBox = QtWidgets.QCheckBox(self.settingsDockWidgetContents)
|
||||||
|
self.baselineCheckBox.setObjectName("baselineCheckBox")
|
||||||
|
self.gridLayout.addWidget(self.baselineCheckBox, 9, 0, 1, 1)
|
||||||
|
self.baselineButton = QtWidgets.QToolButton(self.settingsDockWidgetContents)
|
||||||
|
self.baselineButton.setAutoRaise(False)
|
||||||
|
self.baselineButton.setObjectName("baselineButton")
|
||||||
|
self.gridLayout.addWidget(self.baselineButton, 9, 2, 1, 1)
|
||||||
|
self.subtractBaselineCheckBox = QtWidgets.QCheckBox(self.settingsDockWidgetContents)
|
||||||
|
self.subtractBaselineCheckBox.setObjectName("subtractBaselineCheckBox")
|
||||||
|
self.gridLayout.addWidget(self.subtractBaselineCheckBox, 10, 0, 1, 1)
|
||||||
self.settingsDockWidget.setWidget(self.settingsDockWidgetContents)
|
self.settingsDockWidget.setWidget(self.settingsDockWidgetContents)
|
||||||
QSpectrumAnalyzerMainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.settingsDockWidget)
|
QSpectrumAnalyzerMainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.settingsDockWidget)
|
||||||
self.levelsDockWidget = QtGui.QDockWidget(QSpectrumAnalyzerMainWindow)
|
self.levelsDockWidget = QtWidgets.QDockWidget(QSpectrumAnalyzerMainWindow)
|
||||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Expanding)
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding)
|
||||||
sizePolicy.setHorizontalStretch(0)
|
sizePolicy.setHorizontalStretch(0)
|
||||||
sizePolicy.setVerticalStretch(0)
|
sizePolicy.setVerticalStretch(0)
|
||||||
sizePolicy.setHeightForWidth(self.levelsDockWidget.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.levelsDockWidget.sizePolicy().hasHeightForWidth())
|
||||||
self.levelsDockWidget.setSizePolicy(sizePolicy)
|
self.levelsDockWidget.setSizePolicy(sizePolicy)
|
||||||
self.levelsDockWidget.setFeatures(QtGui.QDockWidget.DockWidgetFloatable|QtGui.QDockWidget.DockWidgetMovable)
|
self.levelsDockWidget.setFeatures(QtWidgets.QDockWidget.DockWidgetFloatable|QtWidgets.QDockWidget.DockWidgetMovable)
|
||||||
self.levelsDockWidget.setObjectName(_fromUtf8("levelsDockWidget"))
|
self.levelsDockWidget.setObjectName("levelsDockWidget")
|
||||||
self.levelsDockWidgetContents = QtGui.QWidget()
|
self.levelsDockWidgetContents = QtWidgets.QWidget()
|
||||||
self.levelsDockWidgetContents.setObjectName(_fromUtf8("levelsDockWidgetContents"))
|
self.levelsDockWidgetContents.setObjectName("levelsDockWidgetContents")
|
||||||
self.verticalLayout_6 = QtGui.QVBoxLayout(self.levelsDockWidgetContents)
|
self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.levelsDockWidgetContents)
|
||||||
self.verticalLayout_6.setMargin(0)
|
self.verticalLayout_6.setContentsMargins(0, 0, 0, 0)
|
||||||
self.verticalLayout_6.setObjectName(_fromUtf8("verticalLayout_6"))
|
self.verticalLayout_6.setObjectName("verticalLayout_6")
|
||||||
self.histogramPlotLayout = GraphicsLayoutWidget(self.levelsDockWidgetContents)
|
self.histogramPlotLayout = GraphicsLayoutWidget(self.levelsDockWidgetContents)
|
||||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Ignored, QtGui.QSizePolicy.Expanding)
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Expanding)
|
||||||
sizePolicy.setHorizontalStretch(0)
|
sizePolicy.setHorizontalStretch(0)
|
||||||
sizePolicy.setVerticalStretch(0)
|
sizePolicy.setVerticalStretch(0)
|
||||||
sizePolicy.setHeightForWidth(self.histogramPlotLayout.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.histogramPlotLayout.sizePolicy().hasHeightForWidth())
|
||||||
self.histogramPlotLayout.setSizePolicy(sizePolicy)
|
self.histogramPlotLayout.setSizePolicy(sizePolicy)
|
||||||
self.histogramPlotLayout.setObjectName(_fromUtf8("histogramPlotLayout"))
|
self.histogramPlotLayout.setObjectName("histogramPlotLayout")
|
||||||
self.verticalLayout_6.addWidget(self.histogramPlotLayout)
|
self.verticalLayout_6.addWidget(self.histogramPlotLayout)
|
||||||
self.levelsDockWidget.setWidget(self.levelsDockWidgetContents)
|
self.levelsDockWidget.setWidget(self.levelsDockWidgetContents)
|
||||||
QSpectrumAnalyzerMainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.levelsDockWidget)
|
QSpectrumAnalyzerMainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.levelsDockWidget)
|
||||||
self.action_Settings = QtGui.QAction(QSpectrumAnalyzerMainWindow)
|
self.action_Settings = QtWidgets.QAction(QSpectrumAnalyzerMainWindow)
|
||||||
self.action_Settings.setObjectName(_fromUtf8("action_Settings"))
|
self.action_Settings.setObjectName("action_Settings")
|
||||||
self.action_Quit = QtGui.QAction(QSpectrumAnalyzerMainWindow)
|
self.action_Quit = QtWidgets.QAction(QSpectrumAnalyzerMainWindow)
|
||||||
self.action_Quit.setObjectName(_fromUtf8("action_Quit"))
|
self.action_Quit.setObjectName("action_Quit")
|
||||||
self.action_About = QtGui.QAction(QSpectrumAnalyzerMainWindow)
|
self.action_About = QtWidgets.QAction(QSpectrumAnalyzerMainWindow)
|
||||||
self.action_About.setObjectName(_fromUtf8("action_About"))
|
self.action_About.setObjectName("action_About")
|
||||||
self.menu_File.addAction(self.action_Settings)
|
self.menu_File.addAction(self.action_Settings)
|
||||||
self.menu_File.addSeparator()
|
self.menu_File.addSeparator()
|
||||||
self.menu_File.addAction(self.action_Quit)
|
self.menu_File.addAction(self.action_Quit)
|
||||||
@ -303,44 +305,51 @@ class Ui_QSpectrumAnalyzerMainWindow(object):
|
|||||||
QSpectrumAnalyzerMainWindow.setTabOrder(self.smoothCheckBox, self.smoothButton)
|
QSpectrumAnalyzerMainWindow.setTabOrder(self.smoothCheckBox, self.smoothButton)
|
||||||
QSpectrumAnalyzerMainWindow.setTabOrder(self.smoothButton, self.persistenceCheckBox)
|
QSpectrumAnalyzerMainWindow.setTabOrder(self.smoothButton, self.persistenceCheckBox)
|
||||||
QSpectrumAnalyzerMainWindow.setTabOrder(self.persistenceCheckBox, self.persistenceButton)
|
QSpectrumAnalyzerMainWindow.setTabOrder(self.persistenceCheckBox, self.persistenceButton)
|
||||||
QSpectrumAnalyzerMainWindow.setTabOrder(self.persistenceButton, self.histogramPlotLayout)
|
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.histogramPlotLayout, self.mainPlotLayout)
|
QSpectrumAnalyzerMainWindow.setTabOrder(self.histogramPlotLayout, self.mainPlotLayout)
|
||||||
QSpectrumAnalyzerMainWindow.setTabOrder(self.mainPlotLayout, self.waterfallPlotLayout)
|
QSpectrumAnalyzerMainWindow.setTabOrder(self.mainPlotLayout, self.waterfallPlotLayout)
|
||||||
|
|
||||||
def retranslateUi(self, QSpectrumAnalyzerMainWindow):
|
def retranslateUi(self, QSpectrumAnalyzerMainWindow):
|
||||||
QSpectrumAnalyzerMainWindow.setWindowTitle(_translate("QSpectrumAnalyzerMainWindow", "QSpectrumAnalyzer", None))
|
_translate = QtCore.QCoreApplication.translate
|
||||||
self.menu_File.setTitle(_translate("QSpectrumAnalyzerMainWindow", "&File", None))
|
QSpectrumAnalyzerMainWindow.setWindowTitle(_translate("QSpectrumAnalyzerMainWindow", "QSpectrumAnalyzer"))
|
||||||
self.menu_Help.setTitle(_translate("QSpectrumAnalyzerMainWindow", "&Help", None))
|
self.menu_File.setTitle(_translate("QSpectrumAnalyzerMainWindow", "&File"))
|
||||||
self.controlsDockWidget.setWindowTitle(_translate("QSpectrumAnalyzerMainWindow", "Controls", None))
|
self.menu_Help.setTitle(_translate("QSpectrumAnalyzerMainWindow", "&Help"))
|
||||||
self.startButton.setText(_translate("QSpectrumAnalyzerMainWindow", "&Start", None))
|
self.controlsDockWidget.setWindowTitle(_translate("QSpectrumAnalyzerMainWindow", "Controls"))
|
||||||
self.stopButton.setText(_translate("QSpectrumAnalyzerMainWindow", "S&top", None))
|
self.startButton.setText(_translate("QSpectrumAnalyzerMainWindow", "&Start"))
|
||||||
self.singleShotButton.setText(_translate("QSpectrumAnalyzerMainWindow", "Si&ngle shot", None))
|
self.stopButton.setText(_translate("QSpectrumAnalyzerMainWindow", "S&top"))
|
||||||
self.frequencyDockWidget.setWindowTitle(_translate("QSpectrumAnalyzerMainWindow", "Frequency", None))
|
self.singleShotButton.setText(_translate("QSpectrumAnalyzerMainWindow", "Si&ngle shot"))
|
||||||
self.label_2.setText(_translate("QSpectrumAnalyzerMainWindow", "Start:", None))
|
self.frequencyDockWidget.setWindowTitle(_translate("QSpectrumAnalyzerMainWindow", "Frequency"))
|
||||||
self.startFreqSpinBox.setSuffix(_translate("QSpectrumAnalyzerMainWindow", " MHz", None))
|
self.label_2.setText(_translate("QSpectrumAnalyzerMainWindow", "Start:"))
|
||||||
self.label_3.setText(_translate("QSpectrumAnalyzerMainWindow", "Stop:", None))
|
self.startFreqSpinBox.setSuffix(_translate("QSpectrumAnalyzerMainWindow", " MHz"))
|
||||||
self.stopFreqSpinBox.setSuffix(_translate("QSpectrumAnalyzerMainWindow", " MHz", None))
|
self.label_3.setText(_translate("QSpectrumAnalyzerMainWindow", "Stop:"))
|
||||||
self.label.setText(_translate("QSpectrumAnalyzerMainWindow", "Bin size:", None))
|
self.stopFreqSpinBox.setSuffix(_translate("QSpectrumAnalyzerMainWindow", " MHz"))
|
||||||
self.binSizeSpinBox.setSuffix(_translate("QSpectrumAnalyzerMainWindow", " kHz", None))
|
self.label.setText(_translate("QSpectrumAnalyzerMainWindow", "&Bin size:"))
|
||||||
self.settingsDockWidget.setWindowTitle(_translate("QSpectrumAnalyzerMainWindow", "Settings", None))
|
self.binSizeSpinBox.setSuffix(_translate("QSpectrumAnalyzerMainWindow", " kHz"))
|
||||||
self.label_4.setText(_translate("QSpectrumAnalyzerMainWindow", "Interval [s]:", None))
|
self.settingsDockWidget.setWindowTitle(_translate("QSpectrumAnalyzerMainWindow", "Settings"))
|
||||||
self.label_6.setText(_translate("QSpectrumAnalyzerMainWindow", "Gain [dB]:", None))
|
self.label_4.setText(_translate("QSpectrumAnalyzerMainWindow", "&Interval [s]:"))
|
||||||
self.gainSpinBox.setSpecialValueText(_translate("QSpectrumAnalyzerMainWindow", "auto", None))
|
self.label_6.setText(_translate("QSpectrumAnalyzerMainWindow", "&Gain [dB]:"))
|
||||||
self.label_5.setText(_translate("QSpectrumAnalyzerMainWindow", "Corr. [ppm]:", None))
|
self.label_5.setText(_translate("QSpectrumAnalyzerMainWindow", "Corr. [ppm]:"))
|
||||||
self.label_7.setText(_translate("QSpectrumAnalyzerMainWindow", "Crop [%]:", None))
|
self.label_7.setText(_translate("QSpectrumAnalyzerMainWindow", "Crop [%]:"))
|
||||||
self.mainCurveCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Main curve", None))
|
self.mainCurveCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Main curve"))
|
||||||
self.colorsButton.setText(_translate("QSpectrumAnalyzerMainWindow", "Colors...", None))
|
self.colorsButton.setText(_translate("QSpectrumAnalyzerMainWindow", "Colors..."))
|
||||||
self.peakHoldMaxCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Max. hold", None))
|
self.peakHoldMaxCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Max. hold"))
|
||||||
self.peakHoldMinCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Min. hold", None))
|
self.peakHoldMinCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Min. hold"))
|
||||||
self.averageCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Average", None))
|
self.averageCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Average"))
|
||||||
self.smoothCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Smoothing", None))
|
self.smoothCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Smoothing"))
|
||||||
self.smoothButton.setText(_translate("QSpectrumAnalyzerMainWindow", "...", None))
|
self.smoothButton.setText(_translate("QSpectrumAnalyzerMainWindow", "..."))
|
||||||
self.persistenceCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Persistence", None))
|
self.persistenceCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Persistence"))
|
||||||
self.persistenceButton.setText(_translate("QSpectrumAnalyzerMainWindow", "...", None))
|
self.persistenceButton.setText(_translate("QSpectrumAnalyzerMainWindow", "..."))
|
||||||
self.levelsDockWidget.setWindowTitle(_translate("QSpectrumAnalyzerMainWindow", "Levels", None))
|
self.gainSpinBox.setSpecialValueText(_translate("QSpectrumAnalyzerMainWindow", "auto"))
|
||||||
self.action_Settings.setText(_translate("QSpectrumAnalyzerMainWindow", "&Settings...", None))
|
self.baselineCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Baseline"))
|
||||||
self.action_Quit.setText(_translate("QSpectrumAnalyzerMainWindow", "&Quit", None))
|
self.baselineButton.setText(_translate("QSpectrumAnalyzerMainWindow", "..."))
|
||||||
self.action_Quit.setShortcut(_translate("QSpectrumAnalyzerMainWindow", "Ctrl+Q", None))
|
self.subtractBaselineCheckBox.setText(_translate("QSpectrumAnalyzerMainWindow", "Subtract baseline"))
|
||||||
self.action_About.setText(_translate("QSpectrumAnalyzerMainWindow", "&About", None))
|
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"))
|
||||||
|
|
||||||
from pyqtgraph import GraphicsLayoutWidget
|
from pyqtgraph import GraphicsLayoutWidget
|
||||||
|
53
qspectrumanalyzer/ui_qspectrumanalyzer_baseline.py
Normal file
53
qspectrumanalyzer/ui_qspectrumanalyzer_baseline.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
# -*- 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,124 +2,125 @@
|
|||||||
|
|
||||||
# Form implementation generated from reading ui file 'qspectrumanalyzer/qspectrumanalyzer_colors.ui'
|
# Form implementation generated from reading ui file 'qspectrumanalyzer/qspectrumanalyzer_colors.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt4 UI code generator 4.12
|
# Created by: PyQt5 UI code generator 5.8
|
||||||
#
|
#
|
||||||
# WARNING! All changes made in this file will be lost!
|
# WARNING! All changes made in this file will be lost!
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from Qt import QtCore, QtGui, QtWidgets
|
||||||
|
|
||||||
try:
|
|
||||||
_fromUtf8 = QtCore.QString.fromUtf8
|
|
||||||
except AttributeError:
|
|
||||||
def _fromUtf8(s):
|
|
||||||
return s
|
|
||||||
|
|
||||||
try:
|
|
||||||
_encoding = QtGui.QApplication.UnicodeUTF8
|
|
||||||
def _translate(context, text, disambig):
|
|
||||||
return QtGui.QApplication.translate(context, text, disambig, _encoding)
|
|
||||||
except AttributeError:
|
|
||||||
def _translate(context, text, disambig):
|
|
||||||
return QtGui.QApplication.translate(context, text, disambig)
|
|
||||||
|
|
||||||
class Ui_QSpectrumAnalyzerColors(object):
|
class Ui_QSpectrumAnalyzerColors(object):
|
||||||
def setupUi(self, QSpectrumAnalyzerColors):
|
def setupUi(self, QSpectrumAnalyzerColors):
|
||||||
QSpectrumAnalyzerColors.setObjectName(_fromUtf8("QSpectrumAnalyzerColors"))
|
QSpectrumAnalyzerColors.setObjectName("QSpectrumAnalyzerColors")
|
||||||
QSpectrumAnalyzerColors.resize(232, 260)
|
QSpectrumAnalyzerColors.resize(253, 266)
|
||||||
self.verticalLayout = QtGui.QVBoxLayout(QSpectrumAnalyzerColors)
|
self.verticalLayout = QtWidgets.QVBoxLayout(QSpectrumAnalyzerColors)
|
||||||
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
|
self.verticalLayout.setObjectName("verticalLayout")
|
||||||
self.formLayout = QtGui.QFormLayout()
|
self.formLayout = QtWidgets.QFormLayout()
|
||||||
self.formLayout.setObjectName(_fromUtf8("formLayout"))
|
self.formLayout.setObjectName("formLayout")
|
||||||
self.label_2 = QtGui.QLabel(QSpectrumAnalyzerColors)
|
self.label_2 = QtWidgets.QLabel(QSpectrumAnalyzerColors)
|
||||||
self.label_2.setObjectName(_fromUtf8("label_2"))
|
self.label_2.setObjectName("label_2")
|
||||||
self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.label_2)
|
self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.label_2)
|
||||||
self.mainColorButton = ColorButton(QSpectrumAnalyzerColors)
|
self.mainColorButton = ColorButton(QSpectrumAnalyzerColors)
|
||||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
|
||||||
sizePolicy.setHorizontalStretch(0)
|
sizePolicy.setHorizontalStretch(0)
|
||||||
sizePolicy.setVerticalStretch(0)
|
sizePolicy.setVerticalStretch(0)
|
||||||
sizePolicy.setHeightForWidth(self.mainColorButton.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.mainColorButton.sizePolicy().hasHeightForWidth())
|
||||||
self.mainColorButton.setSizePolicy(sizePolicy)
|
self.mainColorButton.setSizePolicy(sizePolicy)
|
||||||
self.mainColorButton.setObjectName(_fromUtf8("mainColorButton"))
|
self.mainColorButton.setObjectName("mainColorButton")
|
||||||
self.formLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.mainColorButton)
|
self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.mainColorButton)
|
||||||
self.label_4 = QtGui.QLabel(QSpectrumAnalyzerColors)
|
self.label_4 = QtWidgets.QLabel(QSpectrumAnalyzerColors)
|
||||||
self.label_4.setObjectName(_fromUtf8("label_4"))
|
self.label_4.setObjectName("label_4")
|
||||||
self.formLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.label_4)
|
self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label_4)
|
||||||
self.peakHoldMaxColorButton = ColorButton(QSpectrumAnalyzerColors)
|
self.peakHoldMaxColorButton = ColorButton(QSpectrumAnalyzerColors)
|
||||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
|
||||||
sizePolicy.setHorizontalStretch(0)
|
sizePolicy.setHorizontalStretch(0)
|
||||||
sizePolicy.setVerticalStretch(0)
|
sizePolicy.setVerticalStretch(0)
|
||||||
sizePolicy.setHeightForWidth(self.peakHoldMaxColorButton.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.peakHoldMaxColorButton.sizePolicy().hasHeightForWidth())
|
||||||
self.peakHoldMaxColorButton.setSizePolicy(sizePolicy)
|
self.peakHoldMaxColorButton.setSizePolicy(sizePolicy)
|
||||||
self.peakHoldMaxColorButton.setObjectName(_fromUtf8("peakHoldMaxColorButton"))
|
self.peakHoldMaxColorButton.setObjectName("peakHoldMaxColorButton")
|
||||||
self.formLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.peakHoldMaxColorButton)
|
self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.peakHoldMaxColorButton)
|
||||||
self.label_6 = QtGui.QLabel(QSpectrumAnalyzerColors)
|
self.label_6 = QtWidgets.QLabel(QSpectrumAnalyzerColors)
|
||||||
self.label_6.setObjectName(_fromUtf8("label_6"))
|
self.label_6.setObjectName("label_6")
|
||||||
self.formLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.label_6)
|
self.formLayout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.label_6)
|
||||||
self.peakHoldMinColorButton = ColorButton(QSpectrumAnalyzerColors)
|
self.peakHoldMinColorButton = ColorButton(QSpectrumAnalyzerColors)
|
||||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
|
||||||
sizePolicy.setHorizontalStretch(0)
|
sizePolicy.setHorizontalStretch(0)
|
||||||
sizePolicy.setVerticalStretch(0)
|
sizePolicy.setVerticalStretch(0)
|
||||||
sizePolicy.setHeightForWidth(self.peakHoldMinColorButton.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.peakHoldMinColorButton.sizePolicy().hasHeightForWidth())
|
||||||
self.peakHoldMinColorButton.setSizePolicy(sizePolicy)
|
self.peakHoldMinColorButton.setSizePolicy(sizePolicy)
|
||||||
self.peakHoldMinColorButton.setObjectName(_fromUtf8("peakHoldMinColorButton"))
|
self.peakHoldMinColorButton.setObjectName("peakHoldMinColorButton")
|
||||||
self.formLayout.setWidget(2, QtGui.QFormLayout.FieldRole, self.peakHoldMinColorButton)
|
self.formLayout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.peakHoldMinColorButton)
|
||||||
self.label_5 = QtGui.QLabel(QSpectrumAnalyzerColors)
|
self.label_5 = QtWidgets.QLabel(QSpectrumAnalyzerColors)
|
||||||
self.label_5.setObjectName(_fromUtf8("label_5"))
|
self.label_5.setObjectName("label_5")
|
||||||
self.formLayout.setWidget(3, QtGui.QFormLayout.LabelRole, self.label_5)
|
self.formLayout.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.label_5)
|
||||||
self.averageColorButton = ColorButton(QSpectrumAnalyzerColors)
|
self.averageColorButton = ColorButton(QSpectrumAnalyzerColors)
|
||||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
|
||||||
sizePolicy.setHorizontalStretch(0)
|
sizePolicy.setHorizontalStretch(0)
|
||||||
sizePolicy.setVerticalStretch(0)
|
sizePolicy.setVerticalStretch(0)
|
||||||
sizePolicy.setHeightForWidth(self.averageColorButton.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.averageColorButton.sizePolicy().hasHeightForWidth())
|
||||||
self.averageColorButton.setSizePolicy(sizePolicy)
|
self.averageColorButton.setSizePolicy(sizePolicy)
|
||||||
self.averageColorButton.setObjectName(_fromUtf8("averageColorButton"))
|
self.averageColorButton.setObjectName("averageColorButton")
|
||||||
self.formLayout.setWidget(3, QtGui.QFormLayout.FieldRole, self.averageColorButton)
|
self.formLayout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.averageColorButton)
|
||||||
self.label_3 = QtGui.QLabel(QSpectrumAnalyzerColors)
|
self.label_3 = QtWidgets.QLabel(QSpectrumAnalyzerColors)
|
||||||
self.label_3.setObjectName(_fromUtf8("label_3"))
|
self.label_3.setObjectName("label_3")
|
||||||
self.formLayout.setWidget(4, QtGui.QFormLayout.LabelRole, self.label_3)
|
self.formLayout.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.label_3)
|
||||||
self.persistenceColorButton = ColorButton(QSpectrumAnalyzerColors)
|
self.persistenceColorButton = ColorButton(QSpectrumAnalyzerColors)
|
||||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
|
||||||
sizePolicy.setHorizontalStretch(0)
|
sizePolicy.setHorizontalStretch(0)
|
||||||
sizePolicy.setVerticalStretch(0)
|
sizePolicy.setVerticalStretch(0)
|
||||||
sizePolicy.setHeightForWidth(self.persistenceColorButton.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.persistenceColorButton.sizePolicy().hasHeightForWidth())
|
||||||
self.persistenceColorButton.setSizePolicy(sizePolicy)
|
self.persistenceColorButton.setSizePolicy(sizePolicy)
|
||||||
self.persistenceColorButton.setObjectName(_fromUtf8("persistenceColorButton"))
|
self.persistenceColorButton.setObjectName("persistenceColorButton")
|
||||||
self.formLayout.setWidget(4, QtGui.QFormLayout.FieldRole, self.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.verticalLayout.addLayout(self.formLayout)
|
self.verticalLayout.addLayout(self.formLayout)
|
||||||
spacerItem = QtGui.QSpacerItem(20, 2, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
spacerItem = QtWidgets.QSpacerItem(20, 2, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||||
self.verticalLayout.addItem(spacerItem)
|
self.verticalLayout.addItem(spacerItem)
|
||||||
self.buttonBox = QtGui.QDialogButtonBox(QSpectrumAnalyzerColors)
|
self.buttonBox = QtWidgets.QDialogButtonBox(QSpectrumAnalyzerColors)
|
||||||
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
|
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
|
||||||
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
|
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
|
||||||
self.buttonBox.setObjectName(_fromUtf8("buttonBox"))
|
self.buttonBox.setObjectName("buttonBox")
|
||||||
self.verticalLayout.addWidget(self.buttonBox)
|
self.verticalLayout.addWidget(self.buttonBox)
|
||||||
self.label_2.setBuddy(self.mainColorButton)
|
self.label_2.setBuddy(self.mainColorButton)
|
||||||
self.label_4.setBuddy(self.peakHoldMaxColorButton)
|
self.label_4.setBuddy(self.peakHoldMaxColorButton)
|
||||||
self.label_6.setBuddy(self.peakHoldMinColorButton)
|
self.label_6.setBuddy(self.peakHoldMinColorButton)
|
||||||
self.label_5.setBuddy(self.averageColorButton)
|
self.label_5.setBuddy(self.averageColorButton)
|
||||||
self.label_3.setBuddy(self.persistenceColorButton)
|
self.label_3.setBuddy(self.persistenceColorButton)
|
||||||
|
self.label.setBuddy(self.baselineColorButton)
|
||||||
|
|
||||||
self.retranslateUi(QSpectrumAnalyzerColors)
|
self.retranslateUi(QSpectrumAnalyzerColors)
|
||||||
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), QSpectrumAnalyzerColors.accept)
|
self.buttonBox.accepted.connect(QSpectrumAnalyzerColors.accept)
|
||||||
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), QSpectrumAnalyzerColors.reject)
|
self.buttonBox.rejected.connect(QSpectrumAnalyzerColors.reject)
|
||||||
QtCore.QMetaObject.connectSlotsByName(QSpectrumAnalyzerColors)
|
QtCore.QMetaObject.connectSlotsByName(QSpectrumAnalyzerColors)
|
||||||
QSpectrumAnalyzerColors.setTabOrder(self.mainColorButton, self.peakHoldMaxColorButton)
|
QSpectrumAnalyzerColors.setTabOrder(self.mainColorButton, self.peakHoldMaxColorButton)
|
||||||
QSpectrumAnalyzerColors.setTabOrder(self.peakHoldMaxColorButton, self.peakHoldMinColorButton)
|
QSpectrumAnalyzerColors.setTabOrder(self.peakHoldMaxColorButton, self.peakHoldMinColorButton)
|
||||||
QSpectrumAnalyzerColors.setTabOrder(self.peakHoldMinColorButton, self.averageColorButton)
|
QSpectrumAnalyzerColors.setTabOrder(self.peakHoldMinColorButton, self.averageColorButton)
|
||||||
QSpectrumAnalyzerColors.setTabOrder(self.averageColorButton, self.persistenceColorButton)
|
QSpectrumAnalyzerColors.setTabOrder(self.averageColorButton, self.persistenceColorButton)
|
||||||
QSpectrumAnalyzerColors.setTabOrder(self.persistenceColorButton, self.buttonBox)
|
QSpectrumAnalyzerColors.setTabOrder(self.persistenceColorButton, self.baselineColorButton)
|
||||||
|
|
||||||
def retranslateUi(self, QSpectrumAnalyzerColors):
|
def retranslateUi(self, QSpectrumAnalyzerColors):
|
||||||
QSpectrumAnalyzerColors.setWindowTitle(_translate("QSpectrumAnalyzerColors", "Colors - QSpectrumAnalyzer", None))
|
_translate = QtCore.QCoreApplication.translate
|
||||||
self.label_2.setText(_translate("QSpectrumAnalyzerColors", "Main curve color:", None))
|
QSpectrumAnalyzerColors.setWindowTitle(_translate("QSpectrumAnalyzerColors", "Colors - QSpectrumAnalyzer"))
|
||||||
self.mainColorButton.setText(_translate("QSpectrumAnalyzerColors", "...", None))
|
self.label_2.setText(_translate("QSpectrumAnalyzerColors", "&Main curve color:"))
|
||||||
self.label_4.setText(_translate("QSpectrumAnalyzerColors", "Max. peak hold color:", None))
|
self.mainColorButton.setText(_translate("QSpectrumAnalyzerColors", "..."))
|
||||||
self.peakHoldMaxColorButton.setText(_translate("QSpectrumAnalyzerColors", "...", None))
|
self.label_4.setText(_translate("QSpectrumAnalyzerColors", "Max. peak &hold color:"))
|
||||||
self.label_6.setText(_translate("QSpectrumAnalyzerColors", "Min. peak hold color:", None))
|
self.peakHoldMaxColorButton.setText(_translate("QSpectrumAnalyzerColors", "..."))
|
||||||
self.peakHoldMinColorButton.setText(_translate("QSpectrumAnalyzerColors", "...", None))
|
self.label_6.setText(_translate("QSpectrumAnalyzerColors", "M&in. peak hold color:"))
|
||||||
self.label_5.setText(_translate("QSpectrumAnalyzerColors", "Average color:", None))
|
self.peakHoldMinColorButton.setText(_translate("QSpectrumAnalyzerColors", "..."))
|
||||||
self.averageColorButton.setText(_translate("QSpectrumAnalyzerColors", "...", None))
|
self.label_5.setText(_translate("QSpectrumAnalyzerColors", "Average &color:"))
|
||||||
self.label_3.setText(_translate("QSpectrumAnalyzerColors", "Persistence color:", None))
|
self.averageColorButton.setText(_translate("QSpectrumAnalyzerColors", "..."))
|
||||||
self.persistenceColorButton.setText(_translate("QSpectrumAnalyzerColors", "...", None))
|
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", "..."))
|
||||||
|
|
||||||
from pyqtgraph import ColorButton
|
from pyqtgraph import ColorButton
|
||||||
|
@ -2,72 +2,59 @@
|
|||||||
|
|
||||||
# Form implementation generated from reading ui file 'qspectrumanalyzer/qspectrumanalyzer_persistence.ui'
|
# Form implementation generated from reading ui file 'qspectrumanalyzer/qspectrumanalyzer_persistence.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt4 UI code generator 4.12
|
# Created by: PyQt5 UI code generator 5.8
|
||||||
#
|
#
|
||||||
# WARNING! All changes made in this file will be lost!
|
# WARNING! All changes made in this file will be lost!
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from Qt import QtCore, QtGui, QtWidgets
|
||||||
|
|
||||||
try:
|
|
||||||
_fromUtf8 = QtCore.QString.fromUtf8
|
|
||||||
except AttributeError:
|
|
||||||
def _fromUtf8(s):
|
|
||||||
return s
|
|
||||||
|
|
||||||
try:
|
|
||||||
_encoding = QtGui.QApplication.UnicodeUTF8
|
|
||||||
def _translate(context, text, disambig):
|
|
||||||
return QtGui.QApplication.translate(context, text, disambig, _encoding)
|
|
||||||
except AttributeError:
|
|
||||||
def _translate(context, text, disambig):
|
|
||||||
return QtGui.QApplication.translate(context, text, disambig)
|
|
||||||
|
|
||||||
class Ui_QSpectrumAnalyzerPersistence(object):
|
class Ui_QSpectrumAnalyzerPersistence(object):
|
||||||
def setupUi(self, QSpectrumAnalyzerPersistence):
|
def setupUi(self, QSpectrumAnalyzerPersistence):
|
||||||
QSpectrumAnalyzerPersistence.setObjectName(_fromUtf8("QSpectrumAnalyzerPersistence"))
|
QSpectrumAnalyzerPersistence.setObjectName("QSpectrumAnalyzerPersistence")
|
||||||
QSpectrumAnalyzerPersistence.resize(250, 130)
|
QSpectrumAnalyzerPersistence.resize(250, 130)
|
||||||
self.verticalLayout = QtGui.QVBoxLayout(QSpectrumAnalyzerPersistence)
|
self.verticalLayout = QtWidgets.QVBoxLayout(QSpectrumAnalyzerPersistence)
|
||||||
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
|
self.verticalLayout.setObjectName("verticalLayout")
|
||||||
self.formLayout = QtGui.QFormLayout()
|
self.formLayout = QtWidgets.QFormLayout()
|
||||||
self.formLayout.setObjectName(_fromUtf8("formLayout"))
|
self.formLayout.setObjectName("formLayout")
|
||||||
self.label_2 = QtGui.QLabel(QSpectrumAnalyzerPersistence)
|
self.label_2 = QtWidgets.QLabel(QSpectrumAnalyzerPersistence)
|
||||||
self.label_2.setObjectName(_fromUtf8("label_2"))
|
self.label_2.setObjectName("label_2")
|
||||||
self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.label_2)
|
self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.label_2)
|
||||||
self.decayFunctionComboBox = QtGui.QComboBox(QSpectrumAnalyzerPersistence)
|
self.decayFunctionComboBox = QtWidgets.QComboBox(QSpectrumAnalyzerPersistence)
|
||||||
self.decayFunctionComboBox.setObjectName(_fromUtf8("decayFunctionComboBox"))
|
self.decayFunctionComboBox.setObjectName("decayFunctionComboBox")
|
||||||
self.decayFunctionComboBox.addItem(_fromUtf8(""))
|
self.decayFunctionComboBox.addItem("")
|
||||||
self.decayFunctionComboBox.addItem(_fromUtf8(""))
|
self.decayFunctionComboBox.addItem("")
|
||||||
self.formLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.decayFunctionComboBox)
|
self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.decayFunctionComboBox)
|
||||||
self.label = QtGui.QLabel(QSpectrumAnalyzerPersistence)
|
self.label = QtWidgets.QLabel(QSpectrumAnalyzerPersistence)
|
||||||
self.label.setObjectName(_fromUtf8("label"))
|
self.label.setObjectName("label")
|
||||||
self.formLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.label)
|
self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label)
|
||||||
self.persistenceLengthSpinBox = QtGui.QSpinBox(QSpectrumAnalyzerPersistence)
|
self.persistenceLengthSpinBox = QtWidgets.QSpinBox(QSpectrumAnalyzerPersistence)
|
||||||
self.persistenceLengthSpinBox.setProperty("value", 5)
|
self.persistenceLengthSpinBox.setProperty("value", 5)
|
||||||
self.persistenceLengthSpinBox.setObjectName(_fromUtf8("persistenceLengthSpinBox"))
|
self.persistenceLengthSpinBox.setObjectName("persistenceLengthSpinBox")
|
||||||
self.formLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.persistenceLengthSpinBox)
|
self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.persistenceLengthSpinBox)
|
||||||
self.verticalLayout.addLayout(self.formLayout)
|
self.verticalLayout.addLayout(self.formLayout)
|
||||||
spacerItem = QtGui.QSpacerItem(20, 5, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
spacerItem = QtWidgets.QSpacerItem(20, 5, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||||
self.verticalLayout.addItem(spacerItem)
|
self.verticalLayout.addItem(spacerItem)
|
||||||
self.buttonBox = QtGui.QDialogButtonBox(QSpectrumAnalyzerPersistence)
|
self.buttonBox = QtWidgets.QDialogButtonBox(QSpectrumAnalyzerPersistence)
|
||||||
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
|
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
|
||||||
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
|
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
|
||||||
self.buttonBox.setObjectName(_fromUtf8("buttonBox"))
|
self.buttonBox.setObjectName("buttonBox")
|
||||||
self.verticalLayout.addWidget(self.buttonBox)
|
self.verticalLayout.addWidget(self.buttonBox)
|
||||||
self.label_2.setBuddy(self.decayFunctionComboBox)
|
self.label_2.setBuddy(self.decayFunctionComboBox)
|
||||||
self.label.setBuddy(self.persistenceLengthSpinBox)
|
self.label.setBuddy(self.persistenceLengthSpinBox)
|
||||||
|
|
||||||
self.retranslateUi(QSpectrumAnalyzerPersistence)
|
self.retranslateUi(QSpectrumAnalyzerPersistence)
|
||||||
self.decayFunctionComboBox.setCurrentIndex(1)
|
self.decayFunctionComboBox.setCurrentIndex(1)
|
||||||
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), QSpectrumAnalyzerPersistence.accept)
|
self.buttonBox.accepted.connect(QSpectrumAnalyzerPersistence.accept)
|
||||||
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), QSpectrumAnalyzerPersistence.reject)
|
self.buttonBox.rejected.connect(QSpectrumAnalyzerPersistence.reject)
|
||||||
QtCore.QMetaObject.connectSlotsByName(QSpectrumAnalyzerPersistence)
|
QtCore.QMetaObject.connectSlotsByName(QSpectrumAnalyzerPersistence)
|
||||||
QSpectrumAnalyzerPersistence.setTabOrder(self.decayFunctionComboBox, self.persistenceLengthSpinBox)
|
QSpectrumAnalyzerPersistence.setTabOrder(self.decayFunctionComboBox, self.persistenceLengthSpinBox)
|
||||||
QSpectrumAnalyzerPersistence.setTabOrder(self.persistenceLengthSpinBox, self.buttonBox)
|
QSpectrumAnalyzerPersistence.setTabOrder(self.persistenceLengthSpinBox, self.buttonBox)
|
||||||
|
|
||||||
def retranslateUi(self, QSpectrumAnalyzerPersistence):
|
def retranslateUi(self, QSpectrumAnalyzerPersistence):
|
||||||
QSpectrumAnalyzerPersistence.setWindowTitle(_translate("QSpectrumAnalyzerPersistence", "Persistence - QSpectrumAnalyzer", None))
|
_translate = QtCore.QCoreApplication.translate
|
||||||
self.label_2.setText(_translate("QSpectrumAnalyzerPersistence", "Decay function:", None))
|
QSpectrumAnalyzerPersistence.setWindowTitle(_translate("QSpectrumAnalyzerPersistence", "Persistence - QSpectrumAnalyzer"))
|
||||||
self.decayFunctionComboBox.setItemText(0, _translate("QSpectrumAnalyzerPersistence", "linear", None))
|
self.label_2.setText(_translate("QSpectrumAnalyzerPersistence", "Decay function:"))
|
||||||
self.decayFunctionComboBox.setItemText(1, _translate("QSpectrumAnalyzerPersistence", "exponential", None))
|
self.decayFunctionComboBox.setItemText(0, _translate("QSpectrumAnalyzerPersistence", "linear"))
|
||||||
self.label.setText(_translate("QSpectrumAnalyzerPersistence", "Persistence length:", None))
|
self.decayFunctionComboBox.setItemText(1, _translate("QSpectrumAnalyzerPersistence", "exponential"))
|
||||||
|
self.label.setText(_translate("QSpectrumAnalyzerPersistence", "Persistence length:"))
|
||||||
|
|
||||||
|
@ -2,119 +2,170 @@
|
|||||||
|
|
||||||
# Form implementation generated from reading ui file 'qspectrumanalyzer/qspectrumanalyzer_settings.ui'
|
# Form implementation generated from reading ui file 'qspectrumanalyzer/qspectrumanalyzer_settings.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt4 UI code generator 4.12
|
# Created by: PyQt5 UI code generator 5.8
|
||||||
#
|
#
|
||||||
# WARNING! All changes made in this file will be lost!
|
# WARNING! All changes made in this file will be lost!
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from Qt import QtCore, QtGui, QtWidgets
|
||||||
|
|
||||||
try:
|
|
||||||
_fromUtf8 = QtCore.QString.fromUtf8
|
|
||||||
except AttributeError:
|
|
||||||
def _fromUtf8(s):
|
|
||||||
return s
|
|
||||||
|
|
||||||
try:
|
|
||||||
_encoding = QtGui.QApplication.UnicodeUTF8
|
|
||||||
def _translate(context, text, disambig):
|
|
||||||
return QtGui.QApplication.translate(context, text, disambig, _encoding)
|
|
||||||
except AttributeError:
|
|
||||||
def _translate(context, text, disambig):
|
|
||||||
return QtGui.QApplication.translate(context, text, disambig)
|
|
||||||
|
|
||||||
class Ui_QSpectrumAnalyzerSettings(object):
|
class Ui_QSpectrumAnalyzerSettings(object):
|
||||||
def setupUi(self, QSpectrumAnalyzerSettings):
|
def setupUi(self, QSpectrumAnalyzerSettings):
|
||||||
QSpectrumAnalyzerSettings.setObjectName(_fromUtf8("QSpectrumAnalyzerSettings"))
|
QSpectrumAnalyzerSettings.setObjectName("QSpectrumAnalyzerSettings")
|
||||||
QSpectrumAnalyzerSettings.resize(420, 255)
|
QSpectrumAnalyzerSettings.resize(600, 388)
|
||||||
self.verticalLayout = QtGui.QVBoxLayout(QSpectrumAnalyzerSettings)
|
self.verticalLayout = QtWidgets.QVBoxLayout(QSpectrumAnalyzerSettings)
|
||||||
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
|
self.verticalLayout.setObjectName("verticalLayout")
|
||||||
self.formLayout = QtGui.QFormLayout()
|
self.formLayout = QtWidgets.QFormLayout()
|
||||||
self.formLayout.setObjectName(_fromUtf8("formLayout"))
|
self.formLayout.setObjectName("formLayout")
|
||||||
self.label_3 = QtGui.QLabel(QSpectrumAnalyzerSettings)
|
self.label_3 = QtWidgets.QLabel(QSpectrumAnalyzerSettings)
|
||||||
self.label_3.setObjectName(_fromUtf8("label_3"))
|
self.label_3.setObjectName("label_3")
|
||||||
self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.label_3)
|
self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.label_3)
|
||||||
self.backendComboBox = QtGui.QComboBox(QSpectrumAnalyzerSettings)
|
self.backendComboBox = QtWidgets.QComboBox(QSpectrumAnalyzerSettings)
|
||||||
self.backendComboBox.setObjectName(_fromUtf8("backendComboBox"))
|
self.backendComboBox.setObjectName("backendComboBox")
|
||||||
self.backendComboBox.addItem(_fromUtf8(""))
|
self.backendComboBox.addItem("")
|
||||||
self.backendComboBox.addItem(_fromUtf8(""))
|
self.backendComboBox.addItem("")
|
||||||
self.backendComboBox.addItem(_fromUtf8(""))
|
self.backendComboBox.addItem("")
|
||||||
self.backendComboBox.addItem(_fromUtf8(""))
|
self.backendComboBox.addItem("")
|
||||||
self.backendComboBox.addItem(_fromUtf8(""))
|
self.backendComboBox.addItem("")
|
||||||
self.formLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.backendComboBox)
|
self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.backendComboBox)
|
||||||
self.label = QtGui.QLabel(QSpectrumAnalyzerSettings)
|
self.label = QtWidgets.QLabel(QSpectrumAnalyzerSettings)
|
||||||
self.label.setObjectName(_fromUtf8("label"))
|
self.label.setObjectName("label")
|
||||||
self.formLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.label)
|
self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label)
|
||||||
self.horizontalLayout = QtGui.QHBoxLayout()
|
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
||||||
self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
|
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||||
self.executableEdit = QtGui.QLineEdit(QSpectrumAnalyzerSettings)
|
self.executableEdit = QtWidgets.QLineEdit(QSpectrumAnalyzerSettings)
|
||||||
self.executableEdit.setObjectName(_fromUtf8("executableEdit"))
|
self.executableEdit.setObjectName("executableEdit")
|
||||||
self.horizontalLayout.addWidget(self.executableEdit)
|
self.horizontalLayout.addWidget(self.executableEdit)
|
||||||
self.executableButton = QtGui.QToolButton(QSpectrumAnalyzerSettings)
|
self.executableButton = QtWidgets.QToolButton(QSpectrumAnalyzerSettings)
|
||||||
self.executableButton.setObjectName(_fromUtf8("executableButton"))
|
self.executableButton.setMinimumSize(QtCore.QSize(50, 0))
|
||||||
|
self.executableButton.setObjectName("executableButton")
|
||||||
self.horizontalLayout.addWidget(self.executableButton)
|
self.horizontalLayout.addWidget(self.executableButton)
|
||||||
self.formLayout.setLayout(1, QtGui.QFormLayout.FieldRole, self.horizontalLayout)
|
self.formLayout.setLayout(1, QtWidgets.QFormLayout.FieldRole, self.horizontalLayout)
|
||||||
self.label_5 = QtGui.QLabel(QSpectrumAnalyzerSettings)
|
self.label_5 = QtWidgets.QLabel(QSpectrumAnalyzerSettings)
|
||||||
self.label_5.setObjectName(_fromUtf8("label_5"))
|
self.label_5.setObjectName("label_5")
|
||||||
self.formLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.label_5)
|
self.formLayout.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.label_5)
|
||||||
self.deviceEdit = QtGui.QLineEdit(QSpectrumAnalyzerSettings)
|
self.label_4 = QtWidgets.QLabel(QSpectrumAnalyzerSettings)
|
||||||
self.deviceEdit.setObjectName(_fromUtf8("deviceEdit"))
|
self.label_4.setObjectName("label_4")
|
||||||
self.formLayout.setWidget(2, QtGui.QFormLayout.FieldRole, self.deviceEdit)
|
self.formLayout.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.label_4)
|
||||||
self.label_4 = QtGui.QLabel(QSpectrumAnalyzerSettings)
|
self.label_2 = QtWidgets.QLabel(QSpectrumAnalyzerSettings)
|
||||||
self.label_4.setObjectName(_fromUtf8("label_4"))
|
self.label_2.setObjectName("label_2")
|
||||||
self.formLayout.setWidget(3, QtGui.QFormLayout.LabelRole, self.label_4)
|
self.formLayout.setWidget(7, QtWidgets.QFormLayout.LabelRole, self.label_2)
|
||||||
self.sampleRateSpinBox = QtGui.QSpinBox(QSpectrumAnalyzerSettings)
|
self.waterfallHistorySizeSpinBox = QtWidgets.QSpinBox(QSpectrumAnalyzerSettings)
|
||||||
self.sampleRateSpinBox.setMinimum(0)
|
|
||||||
self.sampleRateSpinBox.setMaximum(25000000)
|
|
||||||
self.sampleRateSpinBox.setSingleStep(10000)
|
|
||||||
self.sampleRateSpinBox.setProperty("value", 2560000)
|
|
||||||
self.sampleRateSpinBox.setObjectName(_fromUtf8("sampleRateSpinBox"))
|
|
||||||
self.formLayout.setWidget(3, QtGui.QFormLayout.FieldRole, self.sampleRateSpinBox)
|
|
||||||
self.label_2 = QtGui.QLabel(QSpectrumAnalyzerSettings)
|
|
||||||
self.label_2.setObjectName(_fromUtf8("label_2"))
|
|
||||||
self.formLayout.setWidget(4, QtGui.QFormLayout.LabelRole, self.label_2)
|
|
||||||
self.waterfallHistorySizeSpinBox = QtGui.QSpinBox(QSpectrumAnalyzerSettings)
|
|
||||||
self.waterfallHistorySizeSpinBox.setMinimum(1)
|
self.waterfallHistorySizeSpinBox.setMinimum(1)
|
||||||
self.waterfallHistorySizeSpinBox.setMaximum(10000000)
|
self.waterfallHistorySizeSpinBox.setMaximum(10000000)
|
||||||
self.waterfallHistorySizeSpinBox.setProperty("value", 100)
|
self.waterfallHistorySizeSpinBox.setProperty("value", 100)
|
||||||
self.waterfallHistorySizeSpinBox.setObjectName(_fromUtf8("waterfallHistorySizeSpinBox"))
|
self.waterfallHistorySizeSpinBox.setObjectName("waterfallHistorySizeSpinBox")
|
||||||
self.formLayout.setWidget(4, QtGui.QFormLayout.FieldRole, self.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.verticalLayout.addLayout(self.formLayout)
|
self.verticalLayout.addLayout(self.formLayout)
|
||||||
spacerItem = QtGui.QSpacerItem(20, 21, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
spacerItem = QtWidgets.QSpacerItem(20, 21, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||||
self.verticalLayout.addItem(spacerItem)
|
self.verticalLayout.addItem(spacerItem)
|
||||||
self.buttonBox = QtGui.QDialogButtonBox(QSpectrumAnalyzerSettings)
|
self.buttonBox = QtWidgets.QDialogButtonBox(QSpectrumAnalyzerSettings)
|
||||||
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
|
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
|
||||||
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
|
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
|
||||||
self.buttonBox.setObjectName(_fromUtf8("buttonBox"))
|
self.buttonBox.setObjectName("buttonBox")
|
||||||
self.verticalLayout.addWidget(self.buttonBox)
|
self.verticalLayout.addWidget(self.buttonBox)
|
||||||
self.label_3.setBuddy(self.backendComboBox)
|
self.label_3.setBuddy(self.backendComboBox)
|
||||||
self.label.setBuddy(self.executableEdit)
|
self.label.setBuddy(self.executableEdit)
|
||||||
self.label_5.setBuddy(self.deviceEdit)
|
self.label_5.setBuddy(self.deviceEdit)
|
||||||
self.label_4.setBuddy(self.sampleRateSpinBox)
|
self.label_4.setBuddy(self.sampleRateSpinBox)
|
||||||
self.label_2.setBuddy(self.waterfallHistorySizeSpinBox)
|
self.label_2.setBuddy(self.waterfallHistorySizeSpinBox)
|
||||||
|
self.label_7.setBuddy(self.bandwidthSpinBox)
|
||||||
|
self.label_8.setBuddy(self.lnbSpinBox)
|
||||||
|
self.label_6.setBuddy(self.paramsEdit)
|
||||||
|
|
||||||
self.retranslateUi(QSpectrumAnalyzerSettings)
|
self.retranslateUi(QSpectrumAnalyzerSettings)
|
||||||
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), QSpectrumAnalyzerSettings.accept)
|
self.buttonBox.accepted.connect(QSpectrumAnalyzerSettings.accept)
|
||||||
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), QSpectrumAnalyzerSettings.reject)
|
self.buttonBox.rejected.connect(QSpectrumAnalyzerSettings.reject)
|
||||||
QtCore.QMetaObject.connectSlotsByName(QSpectrumAnalyzerSettings)
|
QtCore.QMetaObject.connectSlotsByName(QSpectrumAnalyzerSettings)
|
||||||
QSpectrumAnalyzerSettings.setTabOrder(self.backendComboBox, self.executableEdit)
|
QSpectrumAnalyzerSettings.setTabOrder(self.backendComboBox, self.executableEdit)
|
||||||
QSpectrumAnalyzerSettings.setTabOrder(self.executableEdit, self.executableButton)
|
QSpectrumAnalyzerSettings.setTabOrder(self.executableEdit, self.executableButton)
|
||||||
QSpectrumAnalyzerSettings.setTabOrder(self.executableButton, self.deviceEdit)
|
QSpectrumAnalyzerSettings.setTabOrder(self.executableButton, self.paramsEdit)
|
||||||
QSpectrumAnalyzerSettings.setTabOrder(self.deviceEdit, self.sampleRateSpinBox)
|
QSpectrumAnalyzerSettings.setTabOrder(self.paramsEdit, self.paramsHelpButton)
|
||||||
QSpectrumAnalyzerSettings.setTabOrder(self.sampleRateSpinBox, self.waterfallHistorySizeSpinBox)
|
QSpectrumAnalyzerSettings.setTabOrder(self.paramsHelpButton, self.deviceEdit)
|
||||||
QSpectrumAnalyzerSettings.setTabOrder(self.waterfallHistorySizeSpinBox, self.buttonBox)
|
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)
|
||||||
|
|
||||||
def retranslateUi(self, QSpectrumAnalyzerSettings):
|
def retranslateUi(self, QSpectrumAnalyzerSettings):
|
||||||
QSpectrumAnalyzerSettings.setWindowTitle(_translate("QSpectrumAnalyzerSettings", "Settings - QSpectrumAnalyzer", None))
|
_translate = QtCore.QCoreApplication.translate
|
||||||
self.label_3.setText(_translate("QSpectrumAnalyzerSettings", "&Backend:", None))
|
QSpectrumAnalyzerSettings.setWindowTitle(_translate("QSpectrumAnalyzerSettings", "Settings - QSpectrumAnalyzer"))
|
||||||
self.backendComboBox.setItemText(0, _translate("QSpectrumAnalyzerSettings", "soapy_power", None))
|
self.label_3.setText(_translate("QSpectrumAnalyzerSettings", "&Backend:"))
|
||||||
self.backendComboBox.setItemText(1, _translate("QSpectrumAnalyzerSettings", "rx_power", None))
|
self.backendComboBox.setItemText(0, _translate("QSpectrumAnalyzerSettings", "soapy_power"))
|
||||||
self.backendComboBox.setItemText(2, _translate("QSpectrumAnalyzerSettings", "rtl_power_fftw", None))
|
self.backendComboBox.setItemText(1, _translate("QSpectrumAnalyzerSettings", "rx_power"))
|
||||||
self.backendComboBox.setItemText(3, _translate("QSpectrumAnalyzerSettings", "rtl_power", None))
|
self.backendComboBox.setItemText(2, _translate("QSpectrumAnalyzerSettings", "rtl_power_fftw"))
|
||||||
self.backendComboBox.setItemText(4, _translate("QSpectrumAnalyzerSettings", "hackrf_sweep", None))
|
self.backendComboBox.setItemText(3, _translate("QSpectrumAnalyzerSettings", "rtl_power"))
|
||||||
self.label.setText(_translate("QSpectrumAnalyzerSettings", "E&xecutable:", None))
|
self.backendComboBox.setItemText(4, _translate("QSpectrumAnalyzerSettings", "hackrf_sweep"))
|
||||||
self.executableEdit.setText(_translate("QSpectrumAnalyzerSettings", "soapy_power", None))
|
self.label.setText(_translate("QSpectrumAnalyzerSettings", "E&xecutable:"))
|
||||||
self.executableButton.setText(_translate("QSpectrumAnalyzerSettings", "...", None))
|
self.executableEdit.setText(_translate("QSpectrumAnalyzerSettings", "soapy_power"))
|
||||||
self.label_5.setText(_translate("QSpectrumAnalyzerSettings", "Device:", None))
|
self.executableButton.setText(_translate("QSpectrumAnalyzerSettings", "..."))
|
||||||
self.label_4.setText(_translate("QSpectrumAnalyzerSettings", "Sa&mple rate:", None))
|
self.label_5.setText(_translate("QSpectrumAnalyzerSettings", "&Device:"))
|
||||||
self.label_2.setText(_translate("QSpectrumAnalyzerSettings", "&Waterfall history size:", None))
|
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"))
|
||||||
|
|
||||||
|
37
qspectrumanalyzer/ui_qspectrumanalyzer_settings_help.py
Normal file
37
qspectrumanalyzer/ui_qspectrumanalyzer_settings_help.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# -*- 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"))
|
||||||
|
|
@ -1,81 +0,0 @@
|
|||||||
# -*- 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))
|
|
||||||
|
|
68
qspectrumanalyzer/ui_qspectrumanalyzer_smoothing.py
Normal file
68
qspectrumanalyzer/ui_qspectrumanalyzer_smoothing.py
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
# -*- 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
|
import numpy as np
|
||||||
|
|
||||||
from PyQt4 import QtGui
|
from Qt import QtGui
|
||||||
|
|
||||||
|
|
||||||
def smooth(x, window_len=11, window='hanning'):
|
def smooth(x, window_len=11, window='hanning'):
|
||||||
@ -35,3 +35,19 @@ def str_to_color(color_string):
|
|||||||
def color_to_str(color):
|
def color_to_str(color):
|
||||||
"""Create comma separated RGBA string from QColor"""
|
"""Create comma separated RGBA string from QColor"""
|
||||||
return ", ".join([str(color.red()), str(color.green()), str(color.blue()), str(color.alpha())])
|
return ", ".join([str(color.red()), str(color.green()), str(color.blue()), str(color.alpha())])
|
||||||
|
|
||||||
|
|
||||||
|
def human_time(seconds):
|
||||||
|
"""Format time in seconds to human readable form (e.g. 1 h 2 min 3 s)"""
|
||||||
|
seconds = int(seconds)
|
||||||
|
m, s = divmod(seconds, 60)
|
||||||
|
h, m = divmod(m, 60)
|
||||||
|
|
||||||
|
if h > 0:
|
||||||
|
timestr = '{:.0f} h {:.0f} min {:.0f} s'.format(h, m, s)
|
||||||
|
elif m > 0:
|
||||||
|
timestr = '{:.0f} min {:.0f} s'.format(m, s)
|
||||||
|
else:
|
||||||
|
timestr = '{:.0f} s'.format(s)
|
||||||
|
|
||||||
|
return timestr
|
||||||
|
@ -1 +1 @@
|
|||||||
__version__ = "1.4.0"
|
__version__ = "2.2.0"
|
||||||
|
51
qspectrumanalyzer/windows.py
Normal file
51
qspectrumanalyzer/windows.py
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
# -*- 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
26
setup-qt.py
@ -1,26 +0,0 @@
|
|||||||
#!/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,36 +1,90 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import setuptools
|
||||||
from setuptools import setup
|
from setuptools import setup
|
||||||
|
|
||||||
from qspectrumanalyzer.version import __version__
|
from qspectrumanalyzer.version import __version__
|
||||||
|
|
||||||
|
setup_cmdclass = {}
|
||||||
|
setup_entry_points = {
|
||||||
|
"gui_scripts": [
|
||||||
|
"qspectrumanalyzer=qspectrumanalyzer.__main__:main",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
# Allow compilation of Qt .qrc, .ui and .ts files (build_qt command)
|
||||||
|
try:
|
||||||
|
from setup_qt import build_qt
|
||||||
|
setup_cmdclass['build_qt'] = build_qt
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Allow building frozen executables with PyInstaller / subzero (build_exe command)
|
||||||
|
try:
|
||||||
|
from subzero import setup, Executable
|
||||||
|
setup_entry_points = {
|
||||||
|
"console_scripts": [
|
||||||
|
Executable('qspectrumanalyzer=qspectrumanalyzer.__main__:main',
|
||||||
|
console=True, icon_file='qspectrumanalyzer.ico'),
|
||||||
|
Executable('soapy_power=soapypower.__main__:main',
|
||||||
|
console=True),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="QSpectrumAnalyzer",
|
name="QSpectrumAnalyzer",
|
||||||
version=__version__,
|
version=__version__,
|
||||||
description="Spectrum analyzer for RTL-SDR (GUI for rtl_power based on PyQtGraph)",
|
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(),
|
||||||
author="Michal Krenek (Mikos)",
|
author="Michal Krenek (Mikos)",
|
||||||
author_email="m.krenek@gmail.com",
|
author_email="m.krenek@gmail.com",
|
||||||
url="https://github.com/xmikos/qspectrumanalyzer",
|
url="https://github.com/xmikos/qspectrumanalyzer",
|
||||||
license="GNU GPLv3",
|
license="GNU GPLv3",
|
||||||
packages=["qspectrumanalyzer"],
|
packages=["qspectrumanalyzer", "qspectrumanalyzer.backends"],
|
||||||
package_data={
|
package_data={
|
||||||
"qspectrumanalyzer": [
|
"qspectrumanalyzer": [
|
||||||
|
"qspectrumanalyzer.svg",
|
||||||
"*.ui",
|
"*.ui",
|
||||||
"languages/*.qm",
|
"languages/*.qm",
|
||||||
"languages/*.ts"
|
"languages/*.ts",
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
data_files=[
|
data_files=[
|
||||||
("share/applications", ["qspectrumanalyzer.desktop"]),
|
("share/applications", ["qspectrumanalyzer.desktop"]),
|
||||||
("share/pixmaps", ["qspectrumanalyzer.png"])
|
("share/pixmaps", ["qspectrumanalyzer.png"]),
|
||||||
],
|
],
|
||||||
entry_points={
|
|
||||||
"gui_scripts": [
|
|
||||||
"qspectrumanalyzer=qspectrumanalyzer.__main__:main"
|
|
||||||
],
|
|
||||||
},
|
|
||||||
install_requires=[
|
install_requires=[
|
||||||
"pyqtgraph"
|
"soapy_power>=1.6.0",
|
||||||
|
"pyqtgraph>=0.10.0",
|
||||||
|
"Qt.py",
|
||||||
],
|
],
|
||||||
|
options={
|
||||||
|
'build_qt': {
|
||||||
|
'packages': ['qspectrumanalyzer'],
|
||||||
|
'languages': ['cs'],
|
||||||
|
'replacement_bindings': 'Qt',
|
||||||
|
},
|
||||||
|
'build_exe': {
|
||||||
|
'datas': [
|
||||||
|
('qspectrumanalyzer/qspectrumanalyzer.svg', 'qspectrumanalyzer'),
|
||||||
|
('qspectrumanalyzer/*.ui', 'qspectrumanalyzer'),
|
||||||
|
('qspectrumanalyzer/languages/*.ts', 'qspectrumanalyzer/languages'),
|
||||||
|
('qspectrumanalyzer/languages/*.qm', 'qspectrumanalyzer/languages'),
|
||||||
|
('README.rst', '.'),
|
||||||
|
('LICENSE', '.'),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'bdist_msi': {
|
||||||
|
'upgrade_code': '30740ef4-84e7-4e67-8e4a-12b53492c387',
|
||||||
|
'shortcuts': [
|
||||||
|
'QSpectrumAnalyzer=qspectrumanalyzer',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
classifiers=[
|
classifiers=[
|
||||||
"Development Status :: 4 - Beta",
|
"Development Status :: 4 - Beta",
|
||||||
"Environment :: MacOS X",
|
"Environment :: MacOS X",
|
||||||
@ -44,6 +98,8 @@ setup(
|
|||||||
"Operating System :: OS Independent",
|
"Operating System :: OS Independent",
|
||||||
"Programming Language :: Python :: 3",
|
"Programming Language :: Python :: 3",
|
||||||
"Topic :: Communications :: Ham Radio",
|
"Topic :: Communications :: Ham Radio",
|
||||||
"Topic :: Scientific/Engineering :: Visualization"
|
"Topic :: Scientific/Engineering :: Visualization",
|
||||||
]
|
],
|
||||||
|
entry_points=setup_entry_points,
|
||||||
|
cmdclass=setup_cmdclass,
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user