HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Speeding up spectrum analysis

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
speedinganalysisspectrum

Problem

I'm trying to speed up this code that loops over an entire spectrum range. It's using a Raspberry Pi, and a rtl-sdr dongle that covers up to around 1.7 GHz. My goal is to be sweep over that spectrum and gather data from it in a timely manner.

```
#!bin/usr/python

#gathers from the rtl library needed for this program
from rtlsdr import RtlSdr
import math
from pylab import *
import time
from scipy.fftpack import fft, ifft
import pyqtgraph as pg
from pyqtgraph.Qt import QtGui, QtCore
import numpy as np
import os
import sys

os.system("sudo rmmod dvb_usb_rtl28xxu rtl2832")

#RtlSdr set up
##sdr = RtlSdr()
##
##
##num_samples = 4096
##
##freq_range_lo = 50e6 #experimental center freq for now
##freq_range_hi = 600e6 #1750e6
##freq_step = 1e6

##sample_rate = 2e6
##
###Set initial parameters for RTL-SDR Dongle
##sdr.sample_rate = sample_rate
##freq = 512e6
##sdr.center_freq = freq
##
##
##sdr.freq_correction = 102
##sdr.gain = 0

class Spec_Scan(object):

samples = np.array([])
samples_temp = np.array([])
fft_data = np.array([])
fft_data_temp = np.array([])

app = QtGui.QApplication([])
win = pg.GraphicsWindow(title="Basic plotting examples")
win.resize(1000,600)
win.setWindowTitle('pyqtgraph example: Plotting')

def __init__(self, lo, hi, freq, step, samps):
self.freq_range_lo = lo
self.freq_range_hi = hi
self.freq_step = step
self.freq = freq
self.num_samples = samps
self.sample_rate = 2e6

self.sdr = RtlSdr()
self.sdr_default()

def sdr_default(self):
self.sdr.center_freq = self.freq
self.sdr.freq_correction = 101
self.sdr.gain = 0
self.sdr.sample_rate = self.sample_rate

def pyqt(self):
global curve, p6
# Enable antialiasing for prettier plots
pg.setConfigOptions(antialias=True)

self.win.nextRow()
p6 = self.win.addPlot(title="Freq plot")

self.curve = p6.plot(pen='y', clear=Tr

Solution

I'll add my small contribution even though I'm not really a Python developer (hopefully some day). I've taken your update method and tested it on my computer (desktop, i3-4360@ 3.70GHz × 4 ), without the SDR bit. And my intuition was right!

Like in most languages allowing you to do it, don't ever do that:

self.fft_data = np.append(self.fft_data, self.fft_data_temp)


The reason is pretty simple: your array does not have a predefined size, so for each call to append, it has to re-allocate the memory to fit the new size. And that's terribly slow.

Let's talk numbers. Without this line of code, doing the FFT and converting the data to dB takes 300ms on my computer. Adding that line, it almost reaches 9s.

So now that we have found this, what to do about it for your application ? It seems that you would like to display the spectrum from 50MHz to 1750MHz, by decomposing it into signals with a 1MHz bandwidth. And for each slice, you generate 4096 samples. I don't know what kind of display you have, but displaying 4096 1700 FFT bins is gonna be difficult (especially in a 1000600 window). You should restrict the size of the spectrum you want to display at once. And speaking just about bands, displaying the end of the HF band, the VHF band and part of the UHF band is not really gonna be interesting. Mostly because you're gonna have trouble finding an antenna that can cover all these bands simultaneously.

Code Snippets

self.fft_data = np.append(self.fft_data, self.fft_data_temp)

Context

StackExchange Code Review Q#96399, answer score: 9

Revisions (0)

No revisions yet.