pythonpyqtgraphqtopengl

Error while drawing item <pyqtgraph.opengl.items.GLScatterPlotItem.GLScatterPlotItem object at 0x0000026EB461B4C0>


I am running into an error with pyqtgraph. I am trying to plot a 3D scatterplot with OpenGL. However, when I run my code, I get a blank plot and this output:

|==============================>>
|  Traceback (most recent call last):
|    File "C:\Users\T\anaconda3\lib\runpy.py", line 197, in _run_module_as_main
|      return _run_code(code, main_globals, None,
|    File "C:\Users\T\anaconda3\lib\runpy.py", line 87, in _run_code
|      exec(code, run_globals)
|    File "C:\Users\T\Anaconda3\Lib\site-packages\spyder_kernels\console\__main__.py", line 23, in <module>
|      start.main()
|    File "C:\Users\T\Anaconda3\Lib\site-packages\spyder_kernels\console\start.py", line 328, in main
|      kernel.start()
|    File "C:\Users\T\Anaconda3\Lib\site-packages\ipykernel\kernelapp.py", line 677, in start
|      self.io_loop.start()
|    File "C:\Users\T\Anaconda3\Lib\site-packages\tornado\platform\asyncio.py", line 199, in start
|      self.asyncio_loop.run_forever()
|    File "C:\Users\T\anaconda3\lib\asyncio\base_events.py", line 601, in run_forever
|      self._run_once()
|    File "C:\Users\T\anaconda3\lib\asyncio\base_events.py", line 1905, in _run_once
|      handle._run()
|    File "C:\Users\T\anaconda3\lib\asyncio\events.py", line 80, in _run
|      self._context.run(self._callback, *self._args)
|    File "C:\Users\T\Anaconda3\Lib\site-packages\ipykernel\kernelbase.py", line 471, in dispatch_queue
|      await self.process_one()
|    File "C:\Users\T\Anaconda3\Lib\site-packages\ipykernel\kernelbase.py", line 460, in process_one
|      await dispatch(*args)
|    File "C:\Users\T\Anaconda3\Lib\site-packages\ipykernel\kernelbase.py", line 367, in dispatch_shell
|      await result
|    File "C:\Users\T\Anaconda3\Lib\site-packages\ipykernel\kernelbase.py", line 662, in execute_request
|      reply_content = await reply_content
|    File "C:\Users\T\Anaconda3\Lib\site-packages\ipykernel\ipkernel.py", line 360, in do_execute
|      res = shell.run_cell(code, store_history=store_history, silent=silent)
|    File "C:\Users\T\Anaconda3\Lib\site-packages\ipykernel\zmqshell.py", line 532, in run_cell
|      return super().run_cell(*args, **kwargs)
|    File "C:\Users\T\Anaconda3\Lib\site-packages\IPython\core\interactiveshell.py", line 2863, in run_cell
|      result = self._run_cell(
|    File "C:\Users\T\Anaconda3\Lib\site-packages\IPython\core\interactiveshell.py", line 2909, in _run_cell
|      return runner(coro)
|    File "C:\Users\T\Anaconda3\Lib\site-packages\IPython\core\async_helpers.py", line 129, in _pseudo_sync_runner
|      coro.send(None)
|    File "C:\Users\T\Anaconda3\Lib\site-packages\IPython\core\interactiveshell.py", line 3106, in run_cell_async
|      has_raised = await self.run_ast_nodes(code_ast.body, cell_name,
|    File "C:\Users\T\Anaconda3\Lib\site-packages\IPython\core\interactiveshell.py", line 3309, in run_ast_nodes
|      if await self.run_code(code, result, async_=asy):
|    File "C:\Users\T\Anaconda3\Lib\site-packages\IPython\core\interactiveshell.py", line 3369, in run_code
|      exec(code_obj, self.user_global_ns, self.user_ns)
|    File "C:\Users\T\AppData\Local\Temp\ipykernel_23572\2140586109.py", line 1, in <cell line: 1>
|      runfile('C:/Users/T/Downloads/pointPloter.py', wdir='C:/Users/T/Downloads')
|    File "C:\Users\T\Anaconda3\Lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 577, in runfile
|      exec_code(file_code, filename, ns_globals, ns_locals,
|    File "C:\Users\T\Anaconda3\Lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 465, in exec_code
|      exec(compiled, ns_globals, ns_locals)
|    File "C:\Users\T\Downloads\pointPloter.py", line 109, in <module>
|      v.animation()
|    File "C:\Users\T\Downloads\pointPloter.py", line 103, in animation
|      self.start()
|    File "C:\Users\T\Downloads\pointPloter.py", line 83, in start
|      QtGui.QApplication.instance().exec_()
|    File "C:\Users\T\Anaconda3\Lib\site-packages\pyqtgraph\opengl\GLViewWidget.py", line 193, in paintGL
|      self.drawItemTree(useItemNames=useItemNames)
|    File "C:\Users\T\Anaconda3\Lib\site-packages\pyqtgraph\opengl\GLViewWidget.py", line 233, in drawItemTree
|      self.drawItemTree(i, useItemNames=useItemNames)
|    File "C:\Users\T\Anaconda3\Lib\site-packages\pyqtgraph\opengl\GLViewWidget.py", line 214, in drawItemTree
|      debug.printExc()
|    --- exception caught here ---
|    File "C:\Users\T\Anaconda3\Lib\site-packages\pyqtgraph\opengl\GLViewWidget.py", line 211, in drawItemTree
|      i.paint()
|    File "C:\Users\T\Anaconda3\Lib\site-packages\pyqtgraph\opengl\items\GLScatterPlotItem.py", line 152, in paint
|      glDrawArrays(GL_POINTS, 0, int(pos.size / pos.shape[-1]))
|  AttributeError: 'list' object has no attribute 'size'
|==============================<<

Error while drawing item <pyqtgraph.opengl.items.GLScatterPlotItem.GLScatterPlotItem object at 0x0000026EB461B4C0>.

I see it gives me an attribute error. I tested the code each time I use the size attribute. However, I could not get the code to work. My code is:

# -*- coding: utf-8 -*-

from pyqtgraph.Qt import QtCore, QtGui
import pyqtgraph.opengl as gl
import pyqtgraph as pg
import numpy as np
import sys
import time
import random


class Visualizer(object):
    def __init__(self):
        self.traces = dict()
        self.app = QtGui.QApplication(sys.argv)
        self.w = gl.GLViewWidget()
        self.w.opts['distance'] = 40
        self.w.setWindowTitle('pyqtgraph example: GLLinePlotItem')
        self.w.setGeometry(0, 110, 1920, 1080)
        self.w.show()
        
        self.listPoints = []
        self.listPoints.append(self.PointsObj(0))
        self.listPoints.append(self.PointsObj(0))
        self.listPoints.append(self.PointsObj(0))
        #for obj in self.listPoints:
            #print(obj.y)
            
        for idObj, obj in enumerate(self.listPoints):
            pts = [obj.x, obj.y, obj.z] 
            print(pts)
            self.traces[idObj] = gl.GLScatterPlotItem(
                pos=pts,
                color=pg.glColor((0, 6.5)),
                size=3,
                pxMode=True
            )
            self.w.addItem(self.traces[idObj])
        
            
    class PointsObj:
        def __init__(self, type):
            self.type= type
            self.x= random.randint(-10, 10)
            self.y= random.randint(-10, 10)
            self.z= random.randint(-10, 10)
            self.dx= 0
            self.dy= 0
            self.dz= 0
            

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

    def set_plotdata(self, name, points, color, size):
        self.traces[name].setData(pos=points, color=color, size=size)

    def update(self):
        stime = time.time()
        for idObj, obj in enumerate(self.listPoints):
            
            pts = [obj.x + obj.dx, obj.y + obj.dy, obj.z + obj.dz]
            self.set_plotdata(
                name=idObj, points=pts,
                color=pg.glColor((0, 6.5)),
                size=3
            )
        
    def animation(self):
        timer = QtCore.QTimer()
        timer.timeout.connect(self.update)
        timer.start(10)
        self.start()


# Start event loop.
if __name__ == '__main__':
    v = Visualizer()
    v.animation()

Solution

  • You should pass a np.array to GLScatterPlotItem like the following snippet:

    self.traces[idObj] = gl.GLScatterPlotItem(
        pos=np.array(pts),                           # <- Here
        color=pg.glColor((0, 6.5)),
        size=3,
        pxMode=True
    )