首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >加速频谱分析

加速频谱分析
EN

Code Review用户
提问于 2015-07-09 18:47:45
回答 3查看 931关注 0票数 12

我试图加速这段代码在整个光谱范围内的循环。它使用的是一个覆盆子Pi,和一个,涵盖了大约1.7 GHz。我的目标是横扫这一领域,并及时从其中收集数据。

代码语言:javascript
复制
#!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=True)
        #p6.setRange(xRange = [0, (self.num_samples/2)*(1700e6/self.freq_step)], yRange = [-100,100])
        p6.setRange(xRange = [0, (self.num_samples/2)-48], yRange = [-100,100])






        print 'here'
        timer = pg.QtCore.QTimer()
        print'should begin update'
        timer.timeout.connect(self.update)
        timer.timeout.emit()
        print 'update should have finished'
        timer.start(2)

        if __name__ == '__main__':


            if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
                QtGui.QApplication.instance().exec_()



    def update(self):
        global curve, p6


        for self.freq in range(int(self.freq_range_lo), int(self.freq_range_hi), int(self.freq_step)):

            self.sdr.center_freq = self.freq
            self.samples = self.sdr.read_samples(self.num_samples)
            self.fft_data_temp = 20*np.log10(np.abs(np.fft.rfft(self.samples)))
            #self.fft_data_temp = self.fft_data_temp[0:2049]
##            self.fft_data_temp = self.fft_data_temp[1:(self.num_samples/2)]
##            self.fft_data_temp = 2*self.fft_data_temp[2::]
            self.fft_data = np.append(self.fft_data, self.fft_data_temp)
            self.fft_data_temp = 0

        #self.curve.setData(self.fft_data[1::], clear=True)
        self.fft_data = 0       

        print 'refresh'





def main():
    num_samples = 4096

    lo = 50e6     #experimental center freq for now
    hi = 1750e6
    step = 1e6
    freq = 425e6

    test = Spec_Scan(lo, hi, freq, step, num_samples)
##    test.pyqt()
    start = time.time()
    test.update()
    end = time.time()
    print str(end-start)


## Start Qt event loop unless running in interactive mode or using pyside.


main()

当扫描本身被计时时,结果产生197秒左右,这是完全太长。有什么办法可以加速光谱扫描吗?

EN

回答 3

Code Review用户

回答已采纳

发布于 2015-07-09 22:33:14

我将添加我的小贡献,即使我不是一个真正的Python开发人员(希望有一天)。我已经采用了您的更新方法,并在我的计算机上测试了它(桌面,i3-4360@ 3.70GHz×4 ),没有SDR比特。我的直觉是对的!

就像在大多数语言中允许你这样做一样,永远不要这样做:

代码语言:javascript
复制
self.fft_data = np.append(self.fft_data, self.fft_data_temp)

原因很简单:您的数组没有预定义的大小,因此对于要追加的每个调用,它必须重新分配内存以适应新的大小。这太慢了。

我们谈谈数字吧。如果没有这行代码,在我的计算机上执行快速傅立叶变换并将数据转换为dB需要300 my。加上这一行,它几乎达到9s。

那么,既然我们已经发现了这一点,那么您的应用程序应该如何处理呢?似乎你想要显示的频谱从50兆赫到1750兆赫,通过分解成信号与1兆赫的带宽。对于每一片,你会产生4096个样本。我不知道您有什么样的显示,但是显示4096 * 1700 FFT回收箱是很困难的(特别是在1000*600的窗口中)。您应该限制您想要立即显示的频谱的大小。说到波段,展示高频波段的末端,甚高频波段和超高频波段的一部分并不是真正有趣的事情。主要是因为你很难找到能同时覆盖所有这些波段的天线。

票数 9
EN

Code Review用户

发布于 2015-07-09 20:02:21

PEP394

第一个#!bin/usr/python应该是#!/bin/usr/python2。正如您应该声明它所使用的python版本一样。

  • python = Python2和Python3
  • python2 = Python2
  • python3 = Python3

这是因为Arch将python更改为python3,而不是python2。

PEP8

  • 模块级函数和类之间的两个空格。
  • 方法之间有一个空间。
  • 类是CamelCase。不是Capitalized_Words_With_Underscores
  • 操作人员双方应有1个空间。a = b20 * 2.这一例外情况是您需要显示优先级。20*2 + 1.,我个人认为使用括号看起来更好。(20 * 2) + 1
  • curvep6应该在类中。不是全球性的。
  • =不是用于传递kwargs的赋值运算符时,运算符周围就不应该有空格。yRange=[-100,100]
  • 当将事物放在列表中时,在逗号后面添加一个空格。[-100, 100]
  • if __name__=='__main__'应该阻止running.中的整个代码,它应该在模块级别执行。
  • 使用for循环时,不要将变量分配给类。for self.freq in
  • 但是,限制为79条characters.注释的行最多应该是72条。

就我个人而言,我认为你给自己打的电话太多了。以及对全球的依赖。访问局部变量更快。但不仅更快,而且更安全。

对于我来说,很难知道允许改变什么,因为所有东西都使用self.。因此,作为一所大学,我会改变一切,只是为了说明当地人是好的。

似乎您希望在update中使用列表理解。这是因为它是一个只写到变量self.fft_data的for循环。

代码语言:javascript
复制
def update(self):
    self.fft_data = np.array(
        20 * np.log10(np.abs(np.fft.rfft(
          self.sdr.read_samples(self.num_samples))))

        for _ in range(
            int(self.freq_range_lo),
            int(self.freq_range_hi),
            int(self.freq_step))
    )

如果上面的代码返回切片,则需要使用如下内容。它是用纯Python编写的。这是因为我找不到numpy数组的文档。

代码语言:javascript
复制
def update(self):
    self.fft_data = []
    append_ = self.fft_data.append
    for _ in range(
            int(self.freq_range_lo),
            int(self.freq_range_hi),
            int(self.freq_step)):
        append_(
          20 * np.log10(np.abs(np.fft.rfft(
            self.sdr.read_samples(self.num_samples)))))

这些主要是为了不同的观点,老实说,除了这些列表之外,我不知道您需要函数做什么。我再一次指责self.s。

除了PEP8中的所有样式更改之外,您还应该使用局部变量。我真的说不出什么是允许我改变的,什么是我在自我中所必需的。

票数 4
EN

Code Review用户

发布于 2015-07-09 19:01:59

我认为commented是“在发布或部署代码之前”,巨大的注释块,如:

代码语言:javascript
复制
#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

应该删除:版本控制将照顾他们。

您可以节省空间:

代码语言:javascript
复制
samples = np.array([])
samples_temp = np.array([])
fft_data = np.array([])
fft_data_temp = np.array([])

可以成为:

代码语言:javascript
复制
samples = samples_temp = fft_data = fft_data_temp = np.array([])
票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/96399

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档