Added very basic LegendItem. Functional, but still missing some basic features.
Added GLImageItem and example.
This commit is contained in:
parent
1c8579d4b4
commit
65ed889a77
8
documentation/source/3dgraphics/glimageitem.rst
Normal file
8
documentation/source/3dgraphics/glimageitem.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
GLImageItem
|
||||||
|
===========
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.opengl.GLImageItem
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.opengl.GLImageItem.__init__
|
||||||
|
|
8
documentation/source/graphicsItems/legenditem.rst
Normal file
8
documentation/source/graphicsItems/legenditem.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
LegendItem
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. autoclass:: pyqtgraph.LegendItem
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. automethod:: pyqtgraph.LegendItem.__init__
|
||||||
|
|
47
examples/GLImageItem.py
Normal file
47
examples/GLImageItem.py
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
## Add path to library (just for examples; you do not need this)
|
||||||
|
import sys, os
|
||||||
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..'))
|
||||||
|
|
||||||
|
from pyqtgraph.Qt import QtCore, QtGui
|
||||||
|
import pyqtgraph.opengl as gl
|
||||||
|
import pyqtgraph as pg
|
||||||
|
import numpy as np
|
||||||
|
import scipy.ndimage as ndi
|
||||||
|
|
||||||
|
app = QtGui.QApplication([])
|
||||||
|
w = gl.GLViewWidget()
|
||||||
|
w.opts['distance'] = 200
|
||||||
|
w.show()
|
||||||
|
|
||||||
|
## create volume data set to slice three images from
|
||||||
|
shape = (100,100,70)
|
||||||
|
data = ndi.gaussian_filter(np.random.normal(size=shape), (4,4,4))
|
||||||
|
data += ndi.gaussian_filter(np.random.normal(size=shape), (15,15,15))*15
|
||||||
|
|
||||||
|
## slice out three planes, convert to ARGB for OpenGL texture
|
||||||
|
levels = (-0.08, 0.08)
|
||||||
|
tex1 = pg.makeRGBA(data[shape[0]/2], levels=levels)[0] # yz plane
|
||||||
|
tex2 = pg.makeRGBA(data[:,shape[1]/2], levels=levels)[0] # xz plane
|
||||||
|
tex3 = pg.makeRGBA(data[:,:,shape[2]/2], levels=levels)[0] # xy plane
|
||||||
|
|
||||||
|
## Create three image items from textures, add to view
|
||||||
|
v1 = gl.GLImageItem(tex1)
|
||||||
|
v1.translate(-shape[1]/2, -shape[2]/2, 0)
|
||||||
|
v1.rotate(90, 0,0,1)
|
||||||
|
v1.rotate(-90, 0,1,0)
|
||||||
|
w.addItem(v1)
|
||||||
|
v2 = gl.GLImageItem(tex2)
|
||||||
|
v2.translate(-shape[0]/2, -shape[2]/2, 0)
|
||||||
|
v2.rotate(-90, 1,0,0)
|
||||||
|
w.addItem(v2)
|
||||||
|
v3 = gl.GLImageItem(tex3)
|
||||||
|
v3.translate(-shape[0]/2, -shape[1]/2, 0)
|
||||||
|
w.addItem(v3)
|
||||||
|
|
||||||
|
ax = gl.GLAxisItem()
|
||||||
|
w.addItem(ax)
|
||||||
|
|
||||||
|
## Start Qt event loop unless running in interactive mode.
|
||||||
|
if sys.flags.interactive != 1:
|
||||||
|
app.exec_()
|
21
examples/Legend.py
Normal file
21
examples/Legend.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import initExample ## Add path to library (just for examples; you do not need this)
|
||||||
|
|
||||||
|
import pyqtgraph as pg
|
||||||
|
from pyqtgraph.Qt import QtCore, QtGui
|
||||||
|
|
||||||
|
plt = pg.plot()
|
||||||
|
|
||||||
|
l = pg.LegendItem((100,60), (60,10)) # args are (size, position)
|
||||||
|
l.setParentItem(plt.graphicsItem()) # Note we do NOT call plt.addItem in this case
|
||||||
|
|
||||||
|
c1 = plt.plot([1,3,2,4], pen='r')
|
||||||
|
c2 = plt.plot([2,1,4,3], pen='g')
|
||||||
|
l.addItem(c1, 'red plot')
|
||||||
|
l.addItem(c2, 'green plot')
|
||||||
|
|
||||||
|
|
||||||
|
## Start Qt event loop unless running in interactive mode or using pyside.
|
||||||
|
import sys
|
||||||
|
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
|
||||||
|
QtGui.QApplication.instance().exec_()
|
@ -31,6 +31,7 @@ examples = OrderedDict([
|
|||||||
('ImageItem - draw', 'Draw.py'),
|
('ImageItem - draw', 'Draw.py'),
|
||||||
('Region-of-Interest', 'ROIExamples.py'),
|
('Region-of-Interest', 'ROIExamples.py'),
|
||||||
('GraphicsLayout', 'GraphicsLayout.py'),
|
('GraphicsLayout', 'GraphicsLayout.py'),
|
||||||
|
('LegendItem', 'Legend.py'),
|
||||||
('Text Item', 'text.py'),
|
('Text Item', 'text.py'),
|
||||||
('Linked Views', 'linkedViews.py'),
|
('Linked Views', 'linkedViews.py'),
|
||||||
('Arrow', 'Arrow.py'),
|
('Arrow', 'Arrow.py'),
|
||||||
@ -39,6 +40,8 @@ examples = OrderedDict([
|
|||||||
('3D Graphics', OrderedDict([
|
('3D Graphics', OrderedDict([
|
||||||
('Volumetric', 'GLVolumeItem.py'),
|
('Volumetric', 'GLVolumeItem.py'),
|
||||||
('Isosurface', 'GLMeshItem.py'),
|
('Isosurface', 'GLMeshItem.py'),
|
||||||
|
('Image', 'GLImageItem.py'),
|
||||||
|
('Scatter Plot', 'GLScatterPlotItem.py'),
|
||||||
])),
|
])),
|
||||||
('Widgets', OrderedDict([
|
('Widgets', OrderedDict([
|
||||||
('PlotWidget', 'PlotWidget.py'),
|
('PlotWidget', 'PlotWidget.py'),
|
||||||
|
67
graphicsItems/LegendItem.py
Normal file
67
graphicsItems/LegendItem.py
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
from .GraphicsWidget import GraphicsWidget
|
||||||
|
from .LabelItem import LabelItem
|
||||||
|
from ..Qt import QtGui, QtCore
|
||||||
|
from .. import functions as fn
|
||||||
|
|
||||||
|
__all__ = ['LegendItem']
|
||||||
|
|
||||||
|
class LegendItem(GraphicsWidget):
|
||||||
|
"""
|
||||||
|
Displays a legend used for describing the contents of a plot.
|
||||||
|
|
||||||
|
Note that this item should not be added directly to a PlotItem. Instead,
|
||||||
|
Make it a direct descendant of the PlotItem::
|
||||||
|
|
||||||
|
legend.setParentItem(plotItem)
|
||||||
|
|
||||||
|
"""
|
||||||
|
def __init__(self, size, offset):
|
||||||
|
GraphicsWidget.__init__(self)
|
||||||
|
self.setFlag(self.ItemIgnoresTransformations)
|
||||||
|
self.layout = QtGui.QGraphicsGridLayout()
|
||||||
|
self.setLayout(self.layout)
|
||||||
|
self.items = []
|
||||||
|
self.size = size
|
||||||
|
self.offset = offset
|
||||||
|
self.setGeometry(QtCore.QRectF(self.offset[0], self.offset[1], self.size[0], self.size[1]))
|
||||||
|
|
||||||
|
def addItem(self, item, title):
|
||||||
|
"""
|
||||||
|
Add a new entry to the legend.
|
||||||
|
=========== ========================================================
|
||||||
|
Arguments
|
||||||
|
item A PlotDataItem from which the line and point style
|
||||||
|
of the item will be determined
|
||||||
|
title The title to display for this item. Simple HTML allowed.
|
||||||
|
=========== ========================================================
|
||||||
|
"""
|
||||||
|
label = LabelItem(title)
|
||||||
|
sample = ItemSample(item)
|
||||||
|
row = len(self.items)
|
||||||
|
self.items.append((sample, label))
|
||||||
|
self.layout.addItem(sample, row, 0)
|
||||||
|
self.layout.addItem(label, row, 1)
|
||||||
|
|
||||||
|
def boundingRect(self):
|
||||||
|
return QtCore.QRectF(0, 0, self.size[0], self.size[1])
|
||||||
|
|
||||||
|
def paint(self, p, *args):
|
||||||
|
p.setPen(fn.mkPen(255,255,255,100))
|
||||||
|
p.setBrush(fn.mkBrush(100,100,100,50))
|
||||||
|
p.drawRect(self.boundingRect())
|
||||||
|
|
||||||
|
|
||||||
|
class ItemSample(GraphicsWidget):
|
||||||
|
def __init__(self, item):
|
||||||
|
GraphicsWidget.__init__(self)
|
||||||
|
self.item = item
|
||||||
|
|
||||||
|
def boundingRect(self):
|
||||||
|
return QtCore.QRectF(0, 0, 20, 20)
|
||||||
|
|
||||||
|
def paint(self, p, *args):
|
||||||
|
p.setPen(fn.mkPen(self.item.opts['pen']))
|
||||||
|
p.drawLine(2, 18, 18, 2)
|
||||||
|
|
||||||
|
|
||||||
|
|
87
opengl/items/GLImageItem.py
Normal file
87
opengl/items/GLImageItem.py
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
from OpenGL.GL import *
|
||||||
|
from .. GLGraphicsItem import GLGraphicsItem
|
||||||
|
from pyqtgraph.Qt import QtGui
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
__all__ = ['GLImageItem']
|
||||||
|
|
||||||
|
class GLImageItem(GLGraphicsItem):
|
||||||
|
"""
|
||||||
|
**Bases:** :class:`GLGraphicsItem <pyqtgraph.opengl.GLGraphicsItem>`
|
||||||
|
|
||||||
|
Displays image data as a textured quad.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self, data, smooth=False):
|
||||||
|
"""
|
||||||
|
|
||||||
|
============== =======================================================================================
|
||||||
|
**Arguments:**
|
||||||
|
data Volume data to be rendered. *Must* be 3D numpy array (x, y, RGBA) with dtype=ubyte.
|
||||||
|
(See functions.makeRGBA)
|
||||||
|
smooth (bool) If True, the volume slices are rendered with linear interpolation
|
||||||
|
============== =======================================================================================
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.smooth = smooth
|
||||||
|
self.data = data
|
||||||
|
GLGraphicsItem.__init__(self)
|
||||||
|
|
||||||
|
def initializeGL(self):
|
||||||
|
glEnable(GL_TEXTURE_2D)
|
||||||
|
self.texture = glGenTextures(1)
|
||||||
|
glBindTexture(GL_TEXTURE_2D, self.texture)
|
||||||
|
if self.smooth:
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
|
||||||
|
else:
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER)
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER)
|
||||||
|
#glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER)
|
||||||
|
shape = self.data.shape
|
||||||
|
|
||||||
|
## Test texture dimensions first
|
||||||
|
glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA, shape[0], shape[1], 0, GL_RGBA, GL_UNSIGNED_BYTE, None)
|
||||||
|
if glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH) == 0:
|
||||||
|
raise Exception("OpenGL failed to create 2D texture (%dx%d); too large for this hardware." % shape[:2])
|
||||||
|
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, shape[0], shape[1], 0, GL_RGBA, GL_UNSIGNED_BYTE, self.data.transpose((1,0,2)))
|
||||||
|
glDisable(GL_TEXTURE_2D)
|
||||||
|
|
||||||
|
#self.lists = {}
|
||||||
|
#for ax in [0,1,2]:
|
||||||
|
#for d in [-1, 1]:
|
||||||
|
#l = glGenLists(1)
|
||||||
|
#self.lists[(ax,d)] = l
|
||||||
|
#glNewList(l, GL_COMPILE)
|
||||||
|
#self.drawVolume(ax, d)
|
||||||
|
#glEndList()
|
||||||
|
|
||||||
|
|
||||||
|
def paint(self):
|
||||||
|
|
||||||
|
glEnable(GL_TEXTURE_2D)
|
||||||
|
glBindTexture(GL_TEXTURE_2D, self.texture)
|
||||||
|
|
||||||
|
glEnable(GL_DEPTH_TEST)
|
||||||
|
#glDisable(GL_CULL_FACE)
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
|
||||||
|
glEnable( GL_BLEND )
|
||||||
|
glEnable( GL_ALPHA_TEST )
|
||||||
|
glColor4f(1,1,1,1)
|
||||||
|
|
||||||
|
glBegin(GL_QUADS)
|
||||||
|
glTexCoord2f(0,0)
|
||||||
|
glVertex3f(0,0,0)
|
||||||
|
glTexCoord2f(1,0)
|
||||||
|
glVertex3f(self.data.shape[0], 0, 0)
|
||||||
|
glTexCoord2f(1,1)
|
||||||
|
glVertex3f(self.data.shape[0], self.data.shape[1], 0)
|
||||||
|
glTexCoord2f(0,1)
|
||||||
|
glVertex3f(0, self.data.shape[1], 0)
|
||||||
|
glEnd()
|
||||||
|
glDisable(GL_TEXTURE_3D)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user