Minor edits and bugfixes

- fixed AxisItem sometimes drawing the same tick twice (sometimes with different text)
   - fixed handling of record arrays in setting ScatterPlotItem point data
This commit is contained in:
Luke Campagnola 2012-06-18 13:50:44 -04:00
parent a4963f93b7
commit cc94e15d1e
7 changed files with 37 additions and 116 deletions

View File

@ -1,13 +1,10 @@
#!/usr/bin/python -i
# -*- 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__), '..', '..'))
import initExample ## Add path to library (just for examples; you do not need this)
import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui
import numpy as np
import pyqtgraph as pg
## Create image to display
arr = np.ones((100, 100), dtype=float)
@ -128,100 +125,10 @@ img4.setParentItem(r4)
#v = w.addViewBox(colspan=2)
#v.invertY(True) ## Images usually have their Y-axis pointing downward
#v.setAspectLocked(True)
### Create image items, add to scene and set position
#im1 = pg.ImageItem(arr)
#im2 = pg.ImageItem(arr)
#v.addItem(im1)
#v.addItem(im2)
#im2.moveBy(110, 20)
#v.setRange(QtCore.QRectF(0, 0, 200, 120))
#im3 = pg.ImageItem()
#v2 = w.addViewBox(1,0)
#v2.addItem(im3)
#v2.setRange(QtCore.QRectF(0, 0, 60, 60))
#v2.invertY(True)
#v2.setAspectLocked(True)
##im3.moveBy(0, 130)
#im3.setZValue(10)
#im4 = pg.ImageItem()
#v3 = w.addViewBox(1,1)
#v3.addItem(im4)
#v3.setRange(QtCore.QRectF(0, 0, 60, 60))
#v3.invertY(True)
#v3.setAspectLocked(True)
##im4.moveBy(110, 130)
#im4.setZValue(10)
### create the plot
#pi1 = w.addPlot(2,0, colspan=2)
##pi1 = pg.PlotItem()
##s.addItem(pi1)
##pi1.scale(0.5, 0.5)
##pi1.setGeometry(0, 170, 300, 100)
#lastRoi = None
#def updateRoi(roi):
#global im1, im2, im3, im4, arr, lastRoi
#if roi is None:
#return
#lastRoi = roi
#arr1 = roi.getArrayRegion(im1.image, img=im1)
#im3.setImage(arr1)
#arr2 = roi.getArrayRegion(im2.image, img=im2)
#im4.setImage(arr2)
#updateRoiPlot(roi, arr1)
#def updateRoiPlot(roi, data=None):
#if data is None:
#data = roi.getArrayRegion(im1.image, img=im1)
#if data is not None:
#roi.curve.setData(data.mean(axis=1))
### Create a variety of different ROI types
#rois = []
#rois.append(pg.TestROI([0, 0], [20, 20], maxBounds=QtCore.QRectF(-10, -10, 230, 140), pen=(0,9)))
#rois.append(pg.LineROI([0, 0], [20, 20], width=5, pen=(1,9)))
#rois.append(pg.MultiLineROI([[0, 50], [50, 60], [60, 30]], width=5, pen=(2,9)))
#rois.append(pg.EllipseROI([110, 10], [30, 20], pen=(3,9)))
#rois.append(pg.CircleROI([110, 50], [20, 20], pen=(4,9)))
#rois.append(pg.LineSegmentROI([[110, 50], [20, 20]], pen=(5,9)))
#rois.append(pg.PolyLineROI([[110, 60], [20, 30], [50, 10]], pen=(6,9)))
##rois.append(pg.PolygonROI([[2,0], [2.1,0], [2,.1]], pen=(5,9)))
##rois.append(SpiralROI([20,30], [1,1], pen=mkPen(0)))
### Add each ROI to the scene and link its data to a plot curve with the same color
#for r in rois:
#v.addItem(r)
#c = pi1.plot(pen=r.pen)
#r.curve = c
#r.sigRegionChanged.connect(updateRoi)
#def updateImage():
#global im1, arr, lastRoi
#r = abs(np.random.normal(loc=0, scale=(arr.max()-arr.min())*0.1, size=arr.shape))
#im1.updateImage(arr + r)
#updateRoi(lastRoi)
#for r in rois:
#updateRoiPlot(r)
### Rapidly update one of the images with random noise
#t = QtCore.QTimer()
#t.timeout.connect(updateImage)
#t.start(50)
## Start Qt event loop unless running in interactive mode.
if sys.flags.interactive != 1:
app.exec_()
## 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

@ -210,7 +210,7 @@ class AxisItem(GraphicsWidget):
if scale is None:
#if self.drawLabel: ## If there is a label, then we are free to rescale the values
if self.label.isVisible():
d = self.range[1] - self.range[0]
#d = self.range[1] - self.range[0]
#(scale, prefix) = fn.siScale(d / 2.)
(scale, prefix) = fn.siScale(max(abs(self.range[0]), abs(self.range[1])))
if self.labelUnits == '' and prefix in ['k', 'm']: ## If we are not showing units, wait until 1e6 before scaling.
@ -230,7 +230,7 @@ class AxisItem(GraphicsWidget):
def setRange(self, mn, mx):
"""Set the range of values displayed by the axis.
Usually this is handled automatically by linking the axis to a ViewBox with :func:`linkToView <pyqtgraph.AxisItem.linkToView>`"""
if mn in [np.nan, np.inf, -np.inf] or mx in [np.nan, np.inf, -np.inf]:
if any(np.isinf((mn, mx))) or any(np.isnan((mn, mx))):
raise Exception("Not setting range to [%s, %s]" % (str(mn), str(mx)))
self.range = [mn, mx]
if self.autoScale:
@ -259,6 +259,9 @@ class AxisItem(GraphicsWidget):
view.sigXRangeChanged.connect(self.linkedViewChanged)
def linkedViewChanged(self, view, newRange):
if self.orientation in ['right', 'left'] and view.yInverted():
self.setRange(*newRange[::-1])
else:
self.setRange(*newRange)
def boundingRect(self):
@ -365,12 +368,14 @@ class AxisItem(GraphicsWidget):
By default, this method calls tickSpacing to determine the correct tick locations.
This is a good method to override in subclasses.
"""
minVal, maxVal = sorted((minVal, maxVal))
if self.logMode:
return self.logTickValues(minVal, maxVal, size)
ticks = []
tickLevels = self.tickSpacing(minVal, maxVal, size)
allValues = []
allValues = np.array([])
for i in range(len(tickLevels)):
spacing, offset = tickLevels[i]
@ -380,8 +385,11 @@ class AxisItem(GraphicsWidget):
## determine number of ticks
num = int((maxVal-start) / spacing) + 1
values = np.arange(num) * spacing + start
values = filter(lambda x: x not in allValues, values) ## remove any ticks that were present in higher levels
allValues.extend(values)
## remove any ticks that were present in higher levels
## we assume here that if the difference between a tick value and a previously seen tick value
## is less than spacing/100, then they are 'equal' and we can ignore the new tick.
values = filter(lambda x: all(np.abs(allValues-x) > spacing*0.01), values)
allValues = np.concatenate([allValues, values])
ticks.append((spacing, values))
return ticks

View File

@ -1,6 +1,10 @@
from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph.functions as fn
from .GraphicsWidget import GraphicsWidget
## Must be imported at the end to avoid cyclic-dependency hell:
from .ViewBox import ViewBox
from .PlotItem import PlotItem
from .LabelItem import LabelItem
__all__ = ['GraphicsLayout']
class GraphicsLayout(GraphicsWidget):
@ -34,7 +38,7 @@ class GraphicsLayout(GraphicsWidget):
return self.currentCol-colspan
def nextCol(self, *args, **kargs):
"""Advance to next column for automatic item placement"""
"""Alias of nextColumn"""
return self.nextColumn(*args, **kargs)
def addPlot(self, row=None, col=None, rowspan=1, colspan=1, **kargs):
@ -131,7 +135,3 @@ class GraphicsLayout(GraphicsWidget):
self.removeItem(i)
## Must be imported at the end to avoid cyclic-dependency hell:
from .ViewBox import ViewBox
from .PlotItem import PlotItem
from .LabelItem import LabelItem

View File

@ -371,7 +371,6 @@ class PlotDataItem(GraphicsObject):
#self.curves.append(curve)
if scatterArgs['symbol'] is not None:
print scatterArgs
self.scatter.setData(x=x, y=y, **scatterArgs)
self.scatter.show()
else:

View File

@ -330,6 +330,13 @@ class ScatterPlotItem(GraphicsObject):
if isinstance(data, np.ndarray) or isinstance(data, list):
if len(data) != len(dataSet):
raise Exception("Length of meta data does not match number of points (%d != %d)" % (len(data), len(dataSet)))
## Bug: If data is a numpy record array, then items from that array must be copied to dataSet one at a time.
## (otherwise they are converted to tuples and thus lose their field names.
if isinstance(data, np.ndarray) and len(data.dtype.fields) > 1:
for i, rec in enumerate(data):
dataSet['data'][i] = rec
else:
dataSet['data'] = data
def setPxMode(self, mode, update=True):

View File

@ -47,9 +47,9 @@ class CheckTable(QtGui.QWidget):
check.row = name
self.layout.addWidget(check, row, col)
checks.append(check)
col += 1
if name in self.oldRows:
check.setChecked(self.oldRows[name])
check.setChecked(self.oldRows[name][col])
col += 1
#QtCore.QObject.connect(check, QtCore.SIGNAL('stateChanged(int)'), self.checkChanged)
check.stateChanged.connect(self.checkChanged)
self.rowNames.append(name)

View File

@ -7,6 +7,6 @@ class GraphicsLayoutWidget(GraphicsView):
def __init__(self, parent=None, **kargs):
GraphicsView.__init__(self, parent)
self.ci = GraphicsLayout(**kargs)
for n in ['nextRow', 'nextCol', 'nextColumn', 'addPlot', 'addViewBox', 'addItem', 'getItem', 'addLabel', 'addLayout']:
for n in ['nextRow', 'nextCol', 'nextColumn', 'addPlot', 'addViewBox', 'addItem', 'getItem', 'addLabel', 'addLayout', 'addLabel', 'addViewBox', 'removeItem', 'itemIndex', 'clear']:
setattr(self, n, getattr(self.ci, n))
self.setCentralItem(self.ci)