Python Radio Frequency Analysis with LightningChart Python

Tutorial

Assisted by AI

Explore Python Radio Frequency Analysis using LightningChart Python to visualize and analyze RF data efficiently and effectively.
Soroush Sohrabian

Soroush Sohrabian

Software Developer

LinkedIn icon
Radio-Frequency-Analysis-Cover

Introduction to Radio Signal Analysis

Signal analysis is the process of examining, interpreting, and extracting meaningful information from signals, such as radio frequency (RF) signals. It plays a critical role in understanding communication systems, identifying signal characteristics, and improving system performance.

Importance of Visualization in Communication Systems

Visualization bridges the gap between raw signal data and actionable insights. By using advanced visualization tools, engineers can identify patterns, detect anomalies, and optimize communication channels more effectively.

Significance of Signal Analysis for Communication Systems

Signal analysis enables:

  • Efficient Spectrum Utilization: Analyze frequency bands to optimize usage.
  • Error Detection: Identify noise and signal distortions.
  • System Improvement: Enhance modulation schemes and error correction techniques.

Understanding the Dataset for Signal Analysis

This synthetic dataset is tailored for communication systems analysis, including:

  • Modulations: BPSK, QPSK, 8PSK, and 16QAM.
  • Signal-to-Noise Ratios (SNR): 0 dB, 5 dB, 10 dB, and 20 dB.
  • Sampling Rates: 1 MHz, 2 MHz, and 5 MHz.
  • Carrier Frequencies: 100 MHz, 200 MHz, and 400 MHz.

Dataset Parameters and Their Relevance

  • Modulations: Define the signal encoding scheme.
  • SNRs: Represent signal quality under varying noise conditions.
  • Sampling Rates: Indicate signal resolution and bandwidth.
  • Carrier Frequencies: Reflect the spectral position of the signal.

LightningChart Python

LightningChart Python is a high-performance data visualization library designed to handle large datasets with minimal latency. It provides fast rendering capabilities, interactive features, and a diverse range of chart types, making it ideal for visualizing air traffic data.

LCPython1

Features and Chart Types Used in the Project

  1. Power Spectral Density (PSD) Line Charts
  2. 3D Bubble Charts
  3. Amplitude Distribution Histograms
  4. I/Q Waveform and Constellation Diagrams
  5. Real-Time Streaming Charts

Performance Characteristics

  • High Performance: Handles large datasets with low latency.
  • Interactivity: Features zooming, panning, and tooltips.
  • Customizability: Allows users to tailor visualizations for specific use cases.

Setting Up Python Environment

Install Python and the required libraries with the following command:

pip install numpy lightningchart scipy h5py

Overview of Libraries Used

  • Pandas: For efficient data manipulation and analysis.
  • NumPy: Provides tools for numerical operations and data scaling.
  • LightningChart: Enables high-performance, interactive data visualization.
  • h5py: Handling HDF5 data files.

Setting Up Your Development Environment

  1. Set up a virtual environment:
python -m venv rf_analysis_env
source rf_analysis_env/bin/activate  # On Windows: rf_analysis_env\Scripts\activate
  1. Use Visual Studio Code (VSCode) for a streamlined development experience.

Loading and Processing Data

The dataset contains I/Q signals stored in HDF5 format, with metadata including modulation type, SNR, sampling rate, and carrier frequency.

How to Load the Data Files

Load the dataset using h5py:

import h5py

file_path = 'Dataset/rf_dataset.h5'
with h5py.File(file_path, 'r') as f:
    sample_group = f['sample_0']
    iq_signal = sample_group['iq_signal'][:]  # Extract I/Q signal

Handling and Preprocessing the Data

  • Combine I and Q components into a complex signal:
complex_signal = iq_signal[:, 0] + 1j * iq_signal[:, 1]
  • Apply normalization for better visualization:
normalized_signal = (complex_signal - np.min(complex_signal)) / (np.max(complex_signal) - np.min(complex_signal))

Visualizing Data with LightningChart Python

LightningChart enables us to create a variety of visualizations to analyze telemetry data effectively. Let’s look at each chart created in this project and interpret the results.

Power Spectral Density (PSD)

Description:
This chart visualizes the frequency domain representation of a signal’s power. Welch’s method is used for computing the Power Spectral Density (PSD).

Results:

  • The central band highlights the frequency range with the most signal energy.
  • Signals exhibit varying spectral power depending on the modulation type and SNR.

Use Cases:

  • Spectrum Analysis: Identify occupied and unoccupied spectral regions.
  • Signal Quality Assessment: Compare power distribution at different SNRs.
  • Interference Detection: Spot anomalies in the frequency spectrum.

Script Snippet:

from scipy.signal import welch
import lightningchart as lc

freqs, psd = welch(complex_signal, fs=sampling_rate, nperseg=1024)

chart = lc.ChartXY(
    theme=lc.Themes.Light,
    title=f'Power Spectral Density - {modulation} Modulation, SNR: {snr} dB'
)
line_series = chart.add_line_series()
line_series.add(freqs, psd)

x_axis = chart.get_default_x_axis().set_title('Frequency (Hz)')
chart.get_default_y_axis().set_title('Power Spectral Density (dB/Hz)')

# Highlight specific frequency bands
band = x_axis.add_band()
band.set_value_start(-25000)
band.set_value_end(25000)
band.set_color(lc.Color(255, 0, 0, 128))

chart.open()
Radio-Frequency-Analysis-Power-Spectral-Density

3D Bubble Chart – I/Q Signal Representation

Description:
This 3D chart represents the time evolution of the I/Q signal, with bubble size indicating signal magnitude and color encoding signal phase.

Results:

  • Signal distribution and intensity vary over time.
  • Phase differences are clearly visualized through color gradients.

Use Cases:

  • Signal Trajectory Analysis: Examine the temporal evolution of modulated signals.
  • Phase Variations: Evaluate phase shifts caused by channel effects.
  • Signal Integrity: Detect anomalies in magnitude and phase.

Script Snippet:

magnitude = np.sqrt(iq_signal[:, 0]**2 + iq_signal[:, 1]**2)
phase = np.arctan2(iq_signal[:, 1], iq_signal[:, 0])

chart = lc.Chart3D(
    title=f'3D Bubble Chart - {modulation} Modulation, SNR: {snr} dB',
    theme=lc.Themes.Light
)

series = chart.add_point_series(
    render_2d=False,
    individual_point_color_enabled=True,
    individual_lookup_values_enabled=True
)

series.set_point_shape('sphere')
series.set_palette_point_colors(
    steps=[
        {'value': 0.0, 'color': lc.Color('blue')},
        {'value': 0.5, 'color': lc.Color('yellow')},
        {'value': 1.0, 'color': lc.Color('red')}
    ],
    look_up_property='value',
    percentage_values=True
)

# Add data to the chart
time_axis = np.arange(len(magnitude)) / sampling_rate
data = [{'x': t, 'y': iq_signal[idx, 0], 'z': iq_signal[idx, 1], 'size': mag * 10, 'value': ph}
        for idx, (t, mag, ph) in enumerate(zip(time_axis, magnitude, phase))]

series.add(data)
chart.open()
Radio-Frequency-Analysis-3D-Bubble-Chart

Amplitude Distribution Histograms

Description:
Bar charts display the amplitude distribution for the in-phase (I) and quadrature (Q) components.

Results:

  • Symmetric distributions reflect modulation schemes like BPSK and QPSK.
  • Amplitude variations across components are clearly distinguishable.

Use Cases:

  • Modulation Scheme Identification: Distinguish between modulation types based on amplitude profiles.
  • Error Analysis: Detect unexpected variations in amplitude distributions.

Script Snippet:

counts_in_phase, bin_edges_in_phase = np.histogram(iq_signal[:, 0], bins=100)
counts_quadrature, bin_edges_quadrature = np.histogram(iq_signal[:, 1], bins=100)

# Prepare data for the bar charts
bar_data_in_phase = [
    {"category": f"{bin_edges_in_phase[i]:.2f}-{bin_edges_in_phase[i+1]:.2f}", "value": int(count)}
    for i, count in enumerate(counts_in_phase)
]

bar_data_quadrature = [
    {"category": f"{bin_edges_quadrature[i]:.2f}-{bin_edges_quadrature[i+1]:.2f}", "value": int(count)}
    for i, count in enumerate(counts_quadrature)
]

dashboard = lc.Dashboard(columns=2, rows=1, theme=lc.Themes.Light)

chart_in_phase = dashboard.BarChart(row_index=0, column_index=0)
chart_in_phase.set_title('In-phase (I) Amplitude Distribution')
chart_in_phase.set_data(bar_data_in_phase)

chart_quadrature = dashboard.BarChart(row_index=0, column_index=1)
chart_quadrature.set_title('Quadrature (Q) Amplitude Distribution')
chart_quadrature.set_data(bar_data_quadrature)

dashboard.open()
Radio-Frequency-Analysis-Amplitude-Distribution-Histogram

I/Q Signal Waveform and Constellation

Description:
The dashboard includes:

  • Waveform Plot: Temporal representation of I and Q components.
  • Constellation Plot: Scatterplot of I vs. Q components to represent modulation schemes.

Results:

  • Temporal trends reveal noise and signal strength.
  • Constellation diagrams show clustering patterns specific to modulation types.

Use Cases:

  • Modulation Analysis: Verify signal conformity to expected modulation types.
  • Noise Impact Study: Assess distortion effects due to channel noise.

Script Snippet:

dashboard = lc.Dashboard(columns=1, rows=2, theme=lc.Themes.Light)

# I/Q Waveform
waveform_chart = dashboard.ChartXY(row_index=0, column_index=0)
waveform_chart.set_title(f'I/Q Signal Waveform - {modulation} Modulation, SNR: {snr} dB')

time_axis = np.arange(len(iq_signal)) / sampling_rate
waveform_chart.add_line_series().set_name('In-phase (I)').add(time_axis, iq_signal[:, 0])
waveform_chart.add_line_series().set_name('Quadrature (Q)').add(time_axis, iq_signal[:, 1])

# Constellation Plot
constellation_chart = dashboard.ChartXY(row_index=1, column_index=0)
constellation_chart.set_title(f'Constellation Plot - {modulation} Modulation')

constellation_chart.add_point_series().add(iq_signal[:, 0], iq_signal[:, 1])

dashboard.open()
Radio-Frequency-Analysis-Signal-Waveform

Real-Time Streaming: Bar Chart Equalizer

Description:
A real-time bar chart visualizes frequency spectrum updates over streaming data.

Results:

  • Smooth spectrum transitions highlight dynamic frequency shifts.
  • Noise and signal trends are immediately observable.

Use Cases:

  • Live Signal Monitoring: Track frequency content in real time.
  • Spectral Efficiency Analysis: Analyze bandwidth utilization over time.

Script Snippet:

from scipy.fftpack import fft

frame_size = 1000
frequencies = np.fft.rfftfreq(frame_size, d=1 / sampling_rate)

chart = lc.BarChart(title="Frequency Spectrum Equalizer Streaming", theme=lc.Themes.Dark)
chart.set_animation_values(True)

def stream_data():
    for start in range(0, len(signal), frame_size):
        frame_signal = signal[start:start + frame_size]
        spectrum = np.abs(fft(frame_signal)[:len(frequencies)])

        # Normalize spectrum values
        normalized_spectrum = spectrum / np.max(spectrum)

        # Prepare bar data
        bar_data = [{"category": f"{freq/1e3:.0f} kHz", "value": val} for freq, val in zip(frequencies, normalized_spectrum)]
        chart.set_data(bar_data)

        time.sleep(0.1)

stream_data()
chart.open()

Frequency Spectrum (Streaming Line Chart)

Description:
A line chart dynamically visualizes the streaming frequency spectrum over time, with amplitude-based color gradients.

Results:

  • Streaming data shows amplitude variations in real time.
  • Color gradients help highlight spectral peaks and troughs.

Use Cases:

  • Dynamic Spectrum Allocation: Optimize spectrum usage dynamically.
  • Anomaly Detection: Spot spectral peaks caused by interference.

Script Snippet:

frequencies = np.fft.rfftfreq(frame_size, d=1 / sampling_rate)

chart = lc.ChartXY(title="Frequency Spectrum (Streaming)", theme=lc.Themes.Dark)
line_series = chart.add_line_series()

for start in range(0, len(signal), frame_size):
    frame_signal = signal[start:start + frame_size]
    spectrum = np.abs(fft(frame_signal)[:len(frequencies)])

    line_series.clear()
    line_series.add(frequencies, spectrum)

    time.sleep(0.5)

chart.open()

3D Amplitude Histogram

Description:
A 3D histogram represents amplitude distributions over frequency bins, with color gradients indicating density.

Results:

  • Clear visualization of amplitude variations across the RF spectrum.
  • Higher density bins highlight dominant signal components.

Use Cases:

  • Amplitude Clustering: Analyze signal amplitude clustering patterns.
  • Frequency Band Evaluation: Assess signal behavior over different bands.

Script Snippet:

histogram_data = []
for idx, amp in enumerate(amplitudes):
    hist, bins = np.histogram(amp, bins=10)
    for bin_idx in range(len(hist)):
        bin_center = (bins[bin_idx] + bins[bin_idx + 1]) / 2
        histogram_data.append({
            'xCenter': idx,
            'yCenter': hist[bin_idx],
            'zCenter': bin_center,
            'xSize': 0.8,
            'ySize': hist[bin_idx],
            'zSize': bins[bin_idx + 1] - bins[bin_idx]
        })

chart = lc.Chart3D(title='3D Amplitude Histogram')
box_series = chart.add_box_series()
box_series.add(histogram_data)

chart.open()

Conclusion

This project demonstrates the versatility of LightningChart in visualizing signal data for wireless communication analysis. By exploring different visualization techniques, from power spectral density to real-time streaming, users gain actionable insights into signal behavior and channel characteristics.

Continue learning with LightningChart

Lighting

This article covers basics of Lighting in Data Visualization.

High-Performance WPF Charts : The Truth

What about manufacturers’ claims about Fastest rendering charts? There are a lot of false marketing terms used in the industry, so we are going to tell the truth, based on facts that anyone can reproduce and verify.