Added very basic LegendItem. Functional, but still missing some basic features.

Added GLImageItem and example.
This commit is contained in:
Luke Campagnola 2012-10-18 23:18:20 -04:00
parent 1c8579d4b4
commit 65ed889a77
7 changed files with 241 additions and 0 deletions

View File

@ -0,0 +1,8 @@
GLImageItem
===========
.. autoclass:: pyqtgraph.opengl.GLImageItem
:members:
.. automethod:: pyqtgraph.opengl.GLImageItem.__init__

View File

@ -0,0 +1,8 @@
LegendItem
==========
.. autoclass:: pyqtgraph.LegendItem
:members:
.. automethod:: pyqtgraph.LegendItem.__init__

47
examples/GLImageItem.py Normal file
View 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
View 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_()

View File

@ -31,6 +31,7 @@ examples = OrderedDict([
('ImageItem - draw', 'Draw.py'),
('Region-of-Interest', 'ROIExamples.py'),
('GraphicsLayout', 'GraphicsLayout.py'),
('LegendItem', 'Legend.py'),
('Text Item', 'text.py'),
('Linked Views', 'linkedViews.py'),
('Arrow', 'Arrow.py'),
@ -39,6 +40,8 @@ examples = OrderedDict([
('3D Graphics', OrderedDict([
('Volumetric', 'GLVolumeItem.py'),
('Isosurface', 'GLMeshItem.py'),
('Image', 'GLImageItem.py'),
('Scatter Plot', 'GLScatterPlotItem.py'),
])),
('Widgets', OrderedDict([
('PlotWidget', 'PlotWidget.py'),

View 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)

View 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)