Metadata-Version: 2.4
Name: iqview
Version: 0.7.2
Summary: High-performance Static RF Spectrogram Viewer
Author-email: Omer Naftali <omernaftali1@gmail.com>
License: MIT
Project-URL: Homepage, https://github.com/omernaf/IQView
Project-URL: Documentation, https://github.com/omernaf/IQView#readme
Project-URL: Repository, https://github.com/omernaf/IQView
Project-URL: Issues, https://github.com/omernaf/IQView/issues
Project-URL: Changelog, https://github.com/omernaf/IQView/blob/master/changelog.md
Keywords: rf,iq,spectrogram,dsp,pyqt,signal-processing
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: Intended Audience :: Telecommunications Industry
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Scientific/Engineering :: Visualization
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy
Requires-Dist: PyQt6
Requires-Dist: pyqtgraph>=0.14.0
Requires-Dist: PyOpenGL
Requires-Dist: scipy
Requires-Dist: soundfile
Dynamic: license-file

# IQView

**High-Performance Static RF Spectrogram Viewer**

IQView is a streamlined, high-performance GUI application designed for deep analysis of In-phase and Quadrature (IQ) signals. Built with Python, PyQt6, and PyOpenGL, it provides a fluid experience for exploring large RF captures in the time and frequency domains.

---

## 🚀 Key Features

- **Lazy Rendering Engine**: Explore ultra-long captures (e.g. 1 hour+) without RAM exhaustion by computing FFTs on-demand only for the visible viewport.
- **Dynamic Filtering**: Zero-cost frequency-domain BPF/BSF with realistic roll-offs for real-time spectrogram isolation. Zero-phase time-domain BPF/BSF in detail pop-ups for perfect phase alignment and exact band cancellation.
- **WAV Audio File Support**: Native loading of `.wav` files with automatic channel downmixing and float32 normalization (`[-1.0, 1.0]`) without any external audio dependencies.
- **Advanced Markers & Region Overlays**: Locked delta and center markers for precise timing and frequency measurements. Drag-and-drop interactive Region Overlays (`X-Region`, `Y-Region`, `Rect`, `Polygon`, `Ellipse`) with manual add capabilities and independent vertex manipulation for polygons.
- **Statistical Analysis**: Instant computation of Min, Max, Mean, Median, and Integrated Power for selected segments, with linear/logarithmic power-domain averaging.
- **Desktop Integration & Dynamic Loading**: One-click installation of desktop shortcuts and file associations for `.iq`, `.bin`, and `.mat` files. Drag-and-drop / dynamic loading of `.mat` files from Recent Files with support for `.mat.overlays` sidecar files.
- **Background Version Checker**: Non-blocking background checks for updates on startup via PyPI to alert users of newer versions without UI lag.
- **Offline Debian Packaging**: Support for bundling dependencies locally (wheels) to enable offline installation in isolated environments.

---

## 💻 Installation

### For Users
Install the latest package directly from PyPI:
```bash
pip install iqview
```
*Note: Under Linux/Debian systems, ensure system packages `python3-pip` and `libxcb-cursor0` (required for Qt rendering) are installed.*

### Offline Debian Installation (for Isolated Environments)
For secure or offline environments, you can bundle dependencies into the Debian package. Build the offline wheels and package using the scripts:
```bash
# 1. Build project with offline wheels bundled
python scripts/build_project.py --offline-wheels

# 2. Build the .deb package incorporating offline wheels
python scripts/make_deb.py --offline-wheels
```
Then install the resulting `.deb` using:
```bash
sudo apt install ./dist/iqview_*.deb
```
The installer automatically uses the bundled offline wheels to satisfy pip dependencies without calling out to the internet.

### For Developers
Clone the repository and install in editable mode:
```bash
git clone https://github.com/omernaf/IQView.git
cd IQView
pip install -e .
```

### Desktop Integration
To add IQView to your Start Menu and associate it with common IQ file extensions:
```bash
iqview --install-desktop
```
To associate `.mat` files specifically (which requires specific fields `Y`, `XDelta`, `InputCenter`):
```bash
iqview --install-mat
```

---

## 📖 Quick Start

Open an IQ file directly from the command line:
```bash
iqview -f signals.iq -r 20e6 -c 2.44e9 -t complex64
```
Or open an audio file (e.g. WAV):
```bash
iqview -f audio.wav -t audio
```
*   `-r`: Sample Rate ($f_s$)
*   `-c`: Center Frequency ($f_c$)
*   `-t`: Data Type (e.g. `complex64`, `int16`, `float32`, or `audio` / `aud` for WAV audio)

### Dynamic Filename Parameter Auto-detection
If you omit the sample rate (`-r`) or center frequency (`-c`) flags, IQView will automatically parse the file name for standard notation. For example, a file named `capture_10Msps_433MHz.bin` will be auto-loaded with a sample rate of $10\text{ MHz}$ and a center frequency of $433\text{ MHz}$.

---

## 🐍 Python API & Plugin Debugging

You can launch IQView directly from a Python script or IDE using the `iqview.view()` function. This is especially useful for **plugin development**, as it allows you to set breakpoints in your IDE and debug plugins interactively.

### Opening a File
```python
import iqview

# Opens the file and auto-detects sample rate and center frequency from the filename
iqview.view("path/to/capture_20Msps_2.4GHz.cf32")
```

### Passing Raw Arrays (Great for Synthetic Signals)
```python
import numpy as np
import iqview

fs = 2e6
t  = np.arange(int(fs * 0.5)) / fs
x  = np.exp(2j * np.pi * 250e3 * t)   # CW tone at +250 kHz

iqview.view(x, fs=fs, fc=2.4e9, name="Test Signal")
```

### Full Signature
```python
iqview.view(source=None, fs=1e6, fc=0.0, fft_size=1024, dtype='complex64', name=None, lazy=None)
```
*   `source`: File path (`str`), NumPy array (`np.ndarray`), or `None` (empty canvas).
*   `fs` / `fc`: Sample rate and center frequency (ignored if auto-detected from filename).
*   `fft_size`: Spectrogram frequency resolution (default 1024).
*   `dtype`: Data type (e.g., `'complex64'`, `'int16'`) if not auto-detected.
*   `name`: Custom window title.
*   `lazy`: Override lazy rendering mode (`True` / `False`).

---

## 🧪 Mathematical Foundations

### 1. Spectrogram Rendering
The spectrogram is computed using the Short-Time Fourier Transform (STFT). Each vertical slice represents the power spectral density of a windowed segment:

$$X[k] = \sum_{n=0}^{N-1} x[n] \cdot w[n] e^{-j \frac{2\pi}{N} kn}$$

Where $w[n]$ is the chosen window function (e.g., Hamming, Hann). The visual dB level is calculated as:
$$\text{Level}_{\text{dB}} = 20 \log_{10}(|X[k]| + \epsilon)$$
*$\epsilon$ is a small constant ($10^{-10}$) to prevent $\log(0)$.*

### 2. Time Domain Modes
IQView provides several ways to visualize raw samples $x[n] = I[n] + jQ[n]$:

| Mode | Formula |
| :--- | :--- |
| **Magnitude** | $\|x[n]\| = \sqrt{I[n]^2 + Q[n]^2}$ |
| **Magnitude [dB]** | $20 \log_{10}(\|x[n]\|)$ |
| **Magnitude² [dB]**| $10 \log_{10}(\|x[n]\|^2)$ |
| **Phase** | $\phi[n] = \arctan2(Q[n], I[n])$ |
| **Inst. Frequency**| $f_{\text{inst}}[n] = \frac{\phi[n] - \phi[n-1]}{2\pi} \cdot f_s$ |

### 3. Integrated Power
In the Frequency Domain view, selecting a region $[f_1, f_2]$ computes the integrated power within that bandwidth:
$$\text{Total Power} = \sum_{k \in \{f_1, f_2\}} |X[k]|^2$$
For dB displays, this is converted via $10 \log_{10}$ to represent total power relative to full scale.

### 4. Optimized Complex BPF
For the main spectrogram display, IQView applies an optimized frequency-domain mask to the FFT results:
1.  **Design**: A standard IIR low-pass filter (Elliptic, Butterworth, etc.) is designed for the target bandwidth.
2.  **Evaluate**: The filter's complex frequency response $H(f)$ is evaluated at each FFT bin frequency using `sosfreqz`.
3.  **Apply**: Each FFT row is multiplied by the response magnitude: $X_{\text{filt}}[k] = X[k] \cdot |H(f_k)|$.
This provides **zero-cost** filtering with realistic visual roll-offs. For time-domain analysis in pop-up tabs, the original sample-by-sample IIR filter is still used to maintain phase and signal integrity.

---

## ⌨️ Controls & Shortcuts

### General
| Key | Action |
| :--- | :--- |
| **T** | Enter **Time Marker** placement mode |
| **F** | Enter **Frequency/Magnitude Marker** placement mode |
| **Ctrl (Hold)** | Enter **Zoom Mode** (Left-click & drag to box zoom) |
| **Ctrl + Z** | Undo last zoom level |
| **Middle-Click** | Close active analysis tab |

### Markers
- **Draggable**: Hover over a marker; it turns red and can be dragged.
- **Locked Delta**: Lock the distance between $M_1$ and $M_2$ to move them together.
- **Locked Center**: Lock the midpoint between $M_1$ and $M_2$ to expand/shrink symmetrically.

---

## 🛠️ CLI Reference

| Flag | Description | Default |
| :--- | :--- | :--- |
| `-f`, `--file` | Path to binary IQ or audio (.wav) file | None |
| `--stdin` | Read binary IQ data from stdin pipe | False |
| `-r`, `--rate` | Sample rate in Hz | 1 MHz |
| `-c`, `--fc` | Center frequency in Hz | 0 Hz |
| `-t`, `--type` | Data type (`int16`, `float32`, `complex64`, `complex128`, `audio`, `aud`) | `complex64` |
| `-s`, `--fft` | FFT bin size (Power of 2) | 1024 |
| `--lazy` | Force on-demand viewport rendering | Settings |
| `--full` | Force full-file upfront rendering | Settings |
| `--profile` | Run with cProfile for performance debugging | False |

---

## ⚙️ Configuration
IQView saves its state in the system registry or config files via `QSettings`. You can adjust default colormaps, themes (Dark/Light), and FFT defaults in the **Settings Dialog** within the app.

---

## 📚 Detailed Documentation

For a deep dive into the specific features and mathematical foundations of each analysis view, please refer to the dedicated documentation files:

- [🌌 **Spectrogram View**](https://github.com/omernaf/IQView/blob/master/docs/spectrogram.md): STFT, windowing, colormaps, and OpenGL rendering.
- [⏳ **Time Domain View**](https://github.com/omernaf/IQView/blob/master/docs/time_domain.md): Plot modes, marker locking logic, and statistics.
- [📶 **Frequency Domain View**](https://github.com/omernaf/IQView/blob/master/docs/frequency_domain.md): FFT analysis, PSD estimation, preprocessing operators, and integrated power.
- [👁️ **Eye Diagram View**](https://github.com/omernaf/IQView/blob/master/docs/eye_diagram.md): Symbol timing visualization, fractional Nsps, and phase alignment.
- [✨ **Scatter Plot View**](https://github.com/omernaf/IQView/blob/master/docs/scatter_plot.md): IQ constellation visualization, integer downsampling, carrier phase, and 3-tier frequency offset tuning.
- [🔌 **Plugin Developer Guide**](https://github.com/omernaf/IQView/blob/master/docs/plugin_guide.md): Guide for creating and testing custom DSP plugins.

---

## 📄 License
This project is licensed under the MIT License - see the [LICENSE](https://github.com/omernaf/IQView/blob/master/LICENSE) file for details. Original author: Omer Naftali (omernaf).
