【问题标题】:My PyQt plot's Y axes are upside down (even the text)?我的 PyQt 图的 Y 轴是颠倒的(甚至是文本)?
【发布时间】:2017-03-15 10:59:32
【问题描述】:

今天是我尝试使用 PyQtGraph 的第一天。到目前为止我真的很喜欢它,只是我似乎无法完全理解事情是如何运作的......

我正在尝试将两个 FFT 绘图小部件放入同一个窗口中。经过反复试验,我发现了我认为正确的方法。但是现在我有两个显示正确信息的图,但是 Y 轴上的所有内容都被反转了。

此外,缩放和平移似乎也不正确(整个情节移动,而不仅仅是其中的数据)。

此图像显示了两个实时音频 fft 图都在一个 GraphicsWindow 中。在左侧,我将 addPlot 与 addItem 一起使用,在右侧,我将 addViewBox 与 addItem 一起使用。

为了彻底,我尝试使用 item.invertY(True) 和 item.scale(1,-1)。 在这两种情况下,它都会反转 Y 轴数据,但不会反转文本或轴,也不会解决平移/缩放问题..

这个 Python 脚本是我能写的所有东西。

它基于这个文件:pyqtgraph live running spectrogram from microphone

import numpy as np
import pyqtgraph as pg
import pyaudio
from PyQt4 import QtCore, QtGui

FS = 44100 #Hz
CHUNKSZ = 1024 #samples

class MicrophoneRecorder():
    def __init__(self, signal):
        self.signal = signal
        self.p = pyaudio.PyAudio()
        self.stream = self.p.open(format=pyaudio.paInt16,
                            channels=1,
                            rate=FS,
                            input=True,
                            frames_per_buffer=CHUNKSZ)

    def read(self):
        data = self.stream.read(CHUNKSZ)
        y = np.fromstring(data, 'int16')
        self.signal.emit(y)

    def close(self):
        self.stream.stop_stream()
        self.stream.close()
        self.p.terminate()



class SpectrogramWidget2(pg.PlotWidget):

    read_collected = QtCore.pyqtSignal(np.ndarray)
    def __init__(self):
        super(SpectrogramWidget2, self).__init__()

        self.img = pg.ImageItem()
        self.addItem(self.img)

        self.img_array = np.zeros((1000, CHUNKSZ/2+1))

        # bipolar colormap
        pos = np.array([0., 0.5, 1.])
        color = np.array([[0,0,0,255], [0,255,0,255], [255,0,0,255]], dtype=np.ubyte)
        cmap = pg.ColorMap(pos, color)
        pg.colormap
        lut = cmap.getLookupTable(0.0, 1.0, 256)

        # set colormap
        self.img.setLookupTable(lut)
        self.img.setLevels([0,100])

        # setup the correct scaling for y-axis
        freq = np.arange((CHUNKSZ/2)+1)/(float(CHUNKSZ)/FS)
        yscale = 1.0/(self.img_array.shape[1]/freq[-1])

        self.img.scale((1./FS)*CHUNKSZ, yscale)

        self.setLabel('left', 'Frequency', units='Hz')

        # prepare window for later use
        self.win = np.hanning(CHUNKSZ)
        #self.show()

    def update(self, chunk):
        # normalized, windowed frequencies in data chunk
        spec = np.fft.rfft(chunk*self.win) / CHUNKSZ
        # get magnitude 
        psd = abs(spec)
        # convert to dB scaleaxis
        psd = 20 * np.log10(psd)

        # roll down one and replace leading edge with new data
        self.img_array = np.roll(self.img_array, -1, 0)
        self.img_array[-1:] = psd

        self.img.setImage(self.img_array, autoLevels=False)

class SpectrogramWidget(pg.PlotWidget):

    read_collected = QtCore.pyqtSignal(np.ndarray)
    def __init__(self):
        super(SpectrogramWidget, self).__init__()

        self.img = pg.ImageItem()
        self.addItem(self.img)

        self.img_array = np.zeros((1000, CHUNKSZ/2+1))

        # bipolar colormap
        pos = np.array([0., 0.5, 1.])
        color = np.array([[0,0,0,255], [0,255,0,255], [255,0,0,255]], dtype=np.ubyte)
        cmap = pg.ColorMap(pos, color)
        pg.colormap
        lut = cmap.getLookupTable(0.0, 1.0, 256)

        # set colormap
        self.img.setLookupTable(lut)
        self.img.setLevels([0,100])

        # setup the correct scaling for y-axis
        freq = np.arange((CHUNKSZ/2)+1)/(float(CHUNKSZ)/FS)
        yscale = 1.0/(self.img_array.shape[1]/freq[-1])

        self.img.scale((1./FS)*CHUNKSZ, yscale)

        self.setLabel('left', 'Frequency', units='Hz')

        # prepare window for later use
        self.win = np.hanning(CHUNKSZ)
        #self.show()

    def update(self, chunk):
        # normalized, windowed frequencies in data chunk
        spec = np.fft.rfft(chunk*self.win) / CHUNKSZ
        # get magnitude 
        psd = abs(spec)
        # convert to dB scaleaxis
        psd = 20 * np.log10(psd)

        # roll down one and replace leading edge with new data
        self.img_array = np.roll(self.img_array, -1, 0)
        self.img_array[-1:] = psd

        self.img.setImage(self.img_array, autoLevels=False)

if __name__ == '__main__':
    app = QtGui.QApplication([])


    win = pg.GraphicsWindow(title="Basic plotting examples")
    #win.resize(1000,600)


    w = SpectrogramWidget()
    w.read_collected.connect(w.update)

    spectrum1 = win.addPlot(title="Spectrum 1")#win.addViewBox()

    item = w.getPlotItem()

    spectrum1.addItem(item)


    w2 = SpectrogramWidget2()
    w2.read_collected.connect(w2.update)

    spectrum2 = win.addViewBox()
    spectrum2.addItem(w2.getPlotItem())

    mic = MicrophoneRecorder(w.read_collected)
    mic2 = MicrophoneRecorder(w2.read_collected)

    # time (seconds) between reads
    interval = FS/CHUNKSZ

    t = QtCore.QTimer()
    t.timeout.connect(mic.read)
    t.start((1000/interval) ) #QTimer takes ms

    t2 = QtCore.QTimer()
    t2.timeout.connect(mic2.read)
    t2.start((1000/interval) ) #QTimer takes ms

    app.exec_()
    mic.close()

感谢您的帮助!

【问题讨论】:

    标签: python plot real-time pyqtgraph


    【解决方案1】:

    我不知道为什么这样做会导致事物被镜像,但问题与在另一个情节中使用情节中的情节项目有关(我认为这就是你在做什么?)

    无论如何,PlotWidgets 不应该这样使用。它们只是普通的 Qt 小部件,因此可以像使用任何其他 Qt 小部件一样将它们添加到 Qt 布局中。

    if __name__ == '__main__':
        app = QtGui.QApplication([])
    
        win = QtGui.QMainWindow()
        widget = QtGui.QWidget()
        win.setCentralWidget(widget)
        layout = QtGui.QHBoxLayout(widget)
        win.show()
    
        w = SpectrogramWidget()
        w.read_collected.connect(w.update)
        layout.addWidget(w)
    
        w2 = SpectrogramWidget2()
        w2.read_collected.connect(w2.update)
        layout.addWidget(w2)
    
        # .... etc
    

    附:您有两个名称不同的相同类是否有原因?您可以只实例化同一类的多个副本。例如

    w = SpectrogramWidget()
    w2 = SpectrogramWidget()
    

    【讨论】:

    • 感谢您的示例!我今晚会试试看。附言我创建一个重复类的原因是因为我需要一种快速/简单的方法来创建两个小部件,以便我可以弄清楚如何将它们打包到一个窗口中;)我现在已经用完全不同的东西替换了第二个类。
    猜你喜欢
    • 1970-01-01
    • 2018-06-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-21
    • 2016-05-29
    • 1970-01-01
    • 1970-01-01
    • 2018-06-21
    相关资源
    最近更新 更多