merge from acq4
This commit is contained in:
commit
5bd3adfa7c
63
examples/GraphItem.py
Normal file
63
examples/GraphItem.py
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Simple example of GridItem use.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
w = pg.GraphicsWindow()
|
||||||
|
v = w.addViewBox()
|
||||||
|
v.setAspectLocked()
|
||||||
|
|
||||||
|
g = pg.GraphItem()
|
||||||
|
v.addItem(g)
|
||||||
|
|
||||||
|
## Define positions of nodes
|
||||||
|
pos = np.array([
|
||||||
|
[0,0],
|
||||||
|
[10,0],
|
||||||
|
[0,10],
|
||||||
|
[10,10],
|
||||||
|
[5,5],
|
||||||
|
[15,5]
|
||||||
|
])
|
||||||
|
|
||||||
|
## Define the set of connections in the graph
|
||||||
|
adj = np.array([
|
||||||
|
[0,1],
|
||||||
|
[1,3],
|
||||||
|
[3,2],
|
||||||
|
[2,0],
|
||||||
|
[1,5],
|
||||||
|
[3,5],
|
||||||
|
])
|
||||||
|
|
||||||
|
## Define the symbol to use for each node (this is optional)
|
||||||
|
symbols = ['o','o','o','o','t','+']
|
||||||
|
|
||||||
|
## Define the line style for each connection (this is optional)
|
||||||
|
lines = np.array([
|
||||||
|
(255,0,0,255,1),
|
||||||
|
(255,0,255,255,2),
|
||||||
|
(255,0,255,255,3),
|
||||||
|
(255,255,0,255,2),
|
||||||
|
(255,0,0,255,1),
|
||||||
|
(255,255,255,255,4),
|
||||||
|
], dtype=[('red',np.ubyte),('green',np.ubyte),('blue',np.ubyte),('alpha',np.ubyte),('width',float)])
|
||||||
|
|
||||||
|
## Update the graph
|
||||||
|
g.setData(pos=pos, adj=adj, pen=lines, size=1, symbol=symbols, pxMode=False)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Start Qt event loop unless running in interactive mode or using pyside.
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import sys
|
||||||
|
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
|
||||||
|
QtGui.QApplication.instance().exec_()
|
@ -27,6 +27,7 @@ from pyqtgraph import getConfigOption
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import decimal, re
|
import decimal, re
|
||||||
import ctypes
|
import ctypes
|
||||||
|
import sys, struct
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import scipy.ndimage
|
import scipy.ndimage
|
||||||
@ -1041,6 +1042,97 @@ def colorToAlpha(data, color):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def arrayToQPath(x, y, connect='all'):
|
||||||
|
"""Convert an array of x,y coordinats to QPath as efficiently as possible.
|
||||||
|
The *connect* argument may be 'all', indicating that each point should be
|
||||||
|
connected to the next; 'pairs', indicating that each pair of points
|
||||||
|
should be connected, or an array of int32 values (0 or 1) indicating
|
||||||
|
connections.
|
||||||
|
"""
|
||||||
|
|
||||||
|
## Create all vertices in path. The method used below creates a binary format so that all
|
||||||
|
## vertices can be read in at once. This binary format may change in future versions of Qt,
|
||||||
|
## so the original (slower) method is left here for emergencies:
|
||||||
|
#path.moveTo(x[0], y[0])
|
||||||
|
#for i in range(1, y.shape[0]):
|
||||||
|
# path.lineTo(x[i], y[i])
|
||||||
|
|
||||||
|
## Speed this up using >> operator
|
||||||
|
## Format is:
|
||||||
|
## numVerts(i4) 0(i4)
|
||||||
|
## x(f8) y(f8) 0(i4) <-- 0 means this vertex does not connect
|
||||||
|
## x(f8) y(f8) 1(i4) <-- 1 means this vertex connects to the previous vertex
|
||||||
|
## ...
|
||||||
|
## 0(i4)
|
||||||
|
##
|
||||||
|
## All values are big endian--pack using struct.pack('>d') or struct.pack('>i')
|
||||||
|
|
||||||
|
path = QtGui.QPainterPath()
|
||||||
|
|
||||||
|
#prof = debug.Profiler('PlotCurveItem.generatePath', disabled=True)
|
||||||
|
if sys.version_info[0] == 2: ## So this is disabled for python 3... why??
|
||||||
|
n = x.shape[0]
|
||||||
|
# create empty array, pad with extra space on either end
|
||||||
|
arr = np.empty(n+2, dtype=[('x', '>f8'), ('y', '>f8'), ('c', '>i4')])
|
||||||
|
# write first two integers
|
||||||
|
#prof.mark('allocate empty')
|
||||||
|
arr.data[12:20] = struct.pack('>ii', n, 0)
|
||||||
|
#prof.mark('pack header')
|
||||||
|
# Fill array with vertex values
|
||||||
|
arr[1:-1]['x'] = x
|
||||||
|
arr[1:-1]['y'] = y
|
||||||
|
|
||||||
|
# decide which points are connected by lines
|
||||||
|
if connect == 'pairs':
|
||||||
|
connect = np.empty((n/2,2), dtype=np.int32)
|
||||||
|
connect[:,0] = 1
|
||||||
|
connect[:,1] = 0
|
||||||
|
connect = connect.flatten()
|
||||||
|
|
||||||
|
if connect == 'all':
|
||||||
|
arr[1:-1]['c'] = 1
|
||||||
|
elif isinstance(connect, np.ndarray):
|
||||||
|
arr[1:-1]['c'] = connect
|
||||||
|
else:
|
||||||
|
raise Exception('connect argument must be "all", "pairs", or array')
|
||||||
|
|
||||||
|
#prof.mark('fill array')
|
||||||
|
# write last 0
|
||||||
|
lastInd = 20*(n+1)
|
||||||
|
arr.data[lastInd:lastInd+4] = struct.pack('>i', 0)
|
||||||
|
#prof.mark('footer')
|
||||||
|
# create datastream object and stream into path
|
||||||
|
buf = QtCore.QByteArray(arr.data[12:lastInd+4]) # I think one unnecessary copy happens here
|
||||||
|
#prof.mark('create buffer')
|
||||||
|
ds = QtCore.QDataStream(buf)
|
||||||
|
#prof.mark('create datastream')
|
||||||
|
ds >> path
|
||||||
|
#prof.mark('load')
|
||||||
|
|
||||||
|
#prof.finish()
|
||||||
|
else:
|
||||||
|
## This does exactly the same as above, but less efficiently (and more simply).
|
||||||
|
path.moveTo(x[0], y[0])
|
||||||
|
if connect == 'all':
|
||||||
|
for i in range(1, y.shape[0]):
|
||||||
|
path.lineTo(x[i], y[i])
|
||||||
|
elif connect == 'pairs':
|
||||||
|
for i in range(1, y.shape[0]):
|
||||||
|
if i%2 == 0:
|
||||||
|
path.lineTo(x[i], y[i])
|
||||||
|
else:
|
||||||
|
path.moveTo(x[i], y[i])
|
||||||
|
elif isinstance(connect, np.ndarray):
|
||||||
|
for i in range(1, y.shape[0]):
|
||||||
|
if connect[i] == 1:
|
||||||
|
path.lineTo(x[i], y[i])
|
||||||
|
else:
|
||||||
|
path.moveTo(x[i], y[i])
|
||||||
|
else:
|
||||||
|
raise Exception('connect argument must be "all", "pairs", or array')
|
||||||
|
|
||||||
|
return path
|
||||||
|
|
||||||
#def isosurface(data, level):
|
#def isosurface(data, level):
|
||||||
#"""
|
#"""
|
||||||
#Generate isosurface from volumetric data using marching tetrahedra algorithm.
|
#Generate isosurface from volumetric data using marching tetrahedra algorithm.
|
||||||
|
@ -58,6 +58,7 @@ class AxisItem(GraphicsWidget):
|
|||||||
self.labelUnitPrefix=''
|
self.labelUnitPrefix=''
|
||||||
self.labelStyle = {}
|
self.labelStyle = {}
|
||||||
self.logMode = False
|
self.logMode = False
|
||||||
|
self.tickFont = None
|
||||||
|
|
||||||
self.textHeight = 18
|
self.textHeight = 18
|
||||||
self.tickLength = maxTickLength
|
self.tickLength = maxTickLength
|
||||||
@ -100,6 +101,14 @@ class AxisItem(GraphicsWidget):
|
|||||||
self.picture = None
|
self.picture = None
|
||||||
self.update()
|
self.update()
|
||||||
|
|
||||||
|
def setTickFont(self, font):
|
||||||
|
self.tickFont = font
|
||||||
|
self.picture = None
|
||||||
|
self.prepareGeometryChange()
|
||||||
|
## Need to re-allocate space depending on font size?
|
||||||
|
|
||||||
|
self.update()
|
||||||
|
|
||||||
def resizeEvent(self, ev=None):
|
def resizeEvent(self, ev=None):
|
||||||
#s = self.size()
|
#s = self.size()
|
||||||
|
|
||||||
@ -311,14 +320,21 @@ class AxisItem(GraphicsWidget):
|
|||||||
if linkedView is None or self.grid is False:
|
if linkedView is None or self.grid is False:
|
||||||
rect = self.mapRectFromParent(self.geometry())
|
rect = self.mapRectFromParent(self.geometry())
|
||||||
## extend rect if ticks go in negative direction
|
## extend rect if ticks go in negative direction
|
||||||
|
## also extend to account for text that flows past the edges
|
||||||
if self.orientation == 'left':
|
if self.orientation == 'left':
|
||||||
rect.setRight(rect.right() - min(0,self.tickLength))
|
#rect.setRight(rect.right() - min(0,self.tickLength))
|
||||||
|
#rect.setTop(rect.top() - 15)
|
||||||
|
#rect.setBottom(rect.bottom() + 15)
|
||||||
|
rect = rect.adjusted(0, -15, -min(0,self.tickLength), 15)
|
||||||
elif self.orientation == 'right':
|
elif self.orientation == 'right':
|
||||||
rect.setLeft(rect.left() + min(0,self.tickLength))
|
#rect.setLeft(rect.left() + min(0,self.tickLength))
|
||||||
|
rect = rect.adjusted(min(0,self.tickLength), -15, 0, 15)
|
||||||
elif self.orientation == 'top':
|
elif self.orientation == 'top':
|
||||||
rect.setBottom(rect.bottom() - min(0,self.tickLength))
|
#rect.setBottom(rect.bottom() - min(0,self.tickLength))
|
||||||
|
rect = rect.adjusted(-15, 0, 15, -min(0,self.tickLength))
|
||||||
elif self.orientation == 'bottom':
|
elif self.orientation == 'bottom':
|
||||||
rect.setTop(rect.top() + min(0,self.tickLength))
|
#rect.setTop(rect.top() + min(0,self.tickLength))
|
||||||
|
rect = rect.adjusted(-15, min(0,self.tickLength), 15, 0)
|
||||||
return rect
|
return rect
|
||||||
else:
|
else:
|
||||||
return self.mapRectFromParent(self.geometry()) | linkedView.mapRectToItem(self, linkedView.boundingRect())
|
return self.mapRectFromParent(self.geometry()) | linkedView.mapRectToItem(self, linkedView.boundingRect())
|
||||||
@ -647,6 +663,9 @@ class AxisItem(GraphicsWidget):
|
|||||||
prof.mark('draw ticks')
|
prof.mark('draw ticks')
|
||||||
|
|
||||||
## Draw text until there is no more room (or no more text)
|
## Draw text until there is no more room (or no more text)
|
||||||
|
if self.tickFont is not None:
|
||||||
|
p.setFont(self.tickFont)
|
||||||
|
|
||||||
textRects = []
|
textRects = []
|
||||||
for i in range(len(tickLevels)):
|
for i in range(len(tickLevels)):
|
||||||
## Get the list of strings to display for this level
|
## Get the list of strings to display for this level
|
||||||
|
109
pyqtgraph/graphicsItems/GraphItem.py
Normal file
109
pyqtgraph/graphicsItems/GraphItem.py
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
from .. import functions as fn
|
||||||
|
from GraphicsObject import GraphicsObject
|
||||||
|
from ScatterPlotItem import ScatterPlotItem
|
||||||
|
import pyqtgraph as pg
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
__all__ = ['GraphItem']
|
||||||
|
|
||||||
|
|
||||||
|
class GraphItem(GraphicsObject):
|
||||||
|
"""A GraphItem displays graph information (as in 'graph theory', not 'graphics') as
|
||||||
|
a set of nodes connected by lines.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, **kwds):
|
||||||
|
GraphicsObject.__init__(self)
|
||||||
|
self.scatter = ScatterPlotItem()
|
||||||
|
self.scatter.setParentItem(self)
|
||||||
|
self.adjacency = None
|
||||||
|
self.pos = None
|
||||||
|
self.picture = None
|
||||||
|
self.pen = 'default'
|
||||||
|
self.setData(**kwds)
|
||||||
|
|
||||||
|
def setData(self, **kwds):
|
||||||
|
"""
|
||||||
|
Change the data displayed by the graph.
|
||||||
|
|
||||||
|
============ =========================================================
|
||||||
|
Arguments
|
||||||
|
pos (N,2) array of the positions of each node in the graph
|
||||||
|
adj (M,2) array of connection data. Each row contains indexes
|
||||||
|
of two nodes that are connected.
|
||||||
|
pen The pen to use when drawing lines between connected
|
||||||
|
nodes. May be one of:
|
||||||
|
* QPen
|
||||||
|
* a single argument to pass to pg.mkPen
|
||||||
|
* a record array of length M
|
||||||
|
with fields (red, green, blue, alpha, width).
|
||||||
|
* None (to disable connection drawing)
|
||||||
|
* 'default' to use the default foreground color.
|
||||||
|
symbolPen The pen used for drawing nodes.
|
||||||
|
**opts All other keyword arguments are given to ScatterPlotItem
|
||||||
|
to affect the appearance of nodes (symbol, size, brush,
|
||||||
|
etc.)
|
||||||
|
============ =========================================================
|
||||||
|
"""
|
||||||
|
if 'adj' in kwds:
|
||||||
|
self.adjacency = kwds.pop('adj')
|
||||||
|
assert self.adjacency.dtype.kind in 'iu'
|
||||||
|
self.picture = None
|
||||||
|
if 'pos' in kwds:
|
||||||
|
self.pos = kwds['pos']
|
||||||
|
self.picture = None
|
||||||
|
if 'pen' in kwds:
|
||||||
|
self.setPen(kwds.pop('pen'))
|
||||||
|
self.picture = None
|
||||||
|
if 'symbolPen' in kwds:
|
||||||
|
kwds['pen'] = kwds.pop('symbolPen')
|
||||||
|
self.scatter.setData(**kwds)
|
||||||
|
self.informViewBoundsChanged()
|
||||||
|
|
||||||
|
def setPen(self, pen):
|
||||||
|
self.pen = pen
|
||||||
|
self.picture = None
|
||||||
|
|
||||||
|
def generatePicture(self):
|
||||||
|
self.picture = pg.QtGui.QPicture()
|
||||||
|
if self.pen is None or self.pos is None or self.adjacency is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
p = pg.QtGui.QPainter(self.picture)
|
||||||
|
try:
|
||||||
|
pts = self.pos[self.adjacency]
|
||||||
|
pen = self.pen
|
||||||
|
if isinstance(pen, np.ndarray):
|
||||||
|
lastPen = None
|
||||||
|
for i in range(pts.shape[0]):
|
||||||
|
pen = self.pen[i]
|
||||||
|
if np.any(pen != lastPen):
|
||||||
|
lastPen = pen
|
||||||
|
if pen.dtype.fields is None:
|
||||||
|
p.setPen(pg.mkPen(color=(pen[0], pen[1], pen[2], pen[3]), width=1))
|
||||||
|
else:
|
||||||
|
p.setPen(pg.mkPen(color=(pen['red'], pen['green'], pen['blue'], pen['alpha']), width=pen['width']))
|
||||||
|
p.drawLine(pg.QtCore.QPointF(*pts[i][0]), pg.QtCore.QPointF(*pts[i][1]))
|
||||||
|
else:
|
||||||
|
if pen == 'default':
|
||||||
|
pen = pg.getConfigOption('foreground')
|
||||||
|
p.setPen(pg.mkPen(pen))
|
||||||
|
pts = pts.reshape((pts.shape[0]*pts.shape[1], pts.shape[2]))
|
||||||
|
path = fn.arrayToQPath(x=pts[:,0], y=pts[:,1], connect='pairs')
|
||||||
|
p.drawPath(path)
|
||||||
|
finally:
|
||||||
|
p.end()
|
||||||
|
|
||||||
|
def paint(self, p, *args):
|
||||||
|
if self.picture == None:
|
||||||
|
self.generatePicture()
|
||||||
|
self.picture.play(p)
|
||||||
|
|
||||||
|
def boundingRect(self):
|
||||||
|
return self.scatter.boundingRect()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -202,7 +202,7 @@ class GraphicsItem(object):
|
|||||||
## check global cache
|
## check global cache
|
||||||
key = (dt.m11(), dt.m21(), dt.m31(), dt.m12(), dt.m22(), dt.m32(), dt.m31(), dt.m32())
|
key = (dt.m11(), dt.m21(), dt.m31(), dt.m12(), dt.m22(), dt.m32(), dt.m31(), dt.m32())
|
||||||
pv = self._pixelVectorGlobalCache.get(key, None)
|
pv = self._pixelVectorGlobalCache.get(key, None)
|
||||||
if pv is not None:
|
if direction is None and pv is not None:
|
||||||
self._pixelVectorCache = [dt, pv]
|
self._pixelVectorCache = [dt, pv]
|
||||||
return tuple(map(Point,pv)) ## return a *copy*
|
return tuple(map(Point,pv)) ## return a *copy*
|
||||||
|
|
||||||
|
@ -249,26 +249,6 @@ class PlotCurveItem(GraphicsObject):
|
|||||||
prof.finish()
|
prof.finish()
|
||||||
|
|
||||||
def generatePath(self, x, y):
|
def generatePath(self, x, y):
|
||||||
prof = debug.Profiler('PlotCurveItem.generatePath', disabled=True)
|
|
||||||
path = QtGui.QPainterPath()
|
|
||||||
|
|
||||||
## Create all vertices in path. The method used below creates a binary format so that all
|
|
||||||
## vertices can be read in at once. This binary format may change in future versions of Qt,
|
|
||||||
## so the original (slower) method is left here for emergencies:
|
|
||||||
#path.moveTo(x[0], y[0])
|
|
||||||
#for i in range(1, y.shape[0]):
|
|
||||||
# path.lineTo(x[i], y[i])
|
|
||||||
|
|
||||||
## Speed this up using >> operator
|
|
||||||
## Format is:
|
|
||||||
## numVerts(i4) 0(i4)
|
|
||||||
## x(f8) y(f8) 0(i4) <-- 0 means this vertex does not connect
|
|
||||||
## x(f8) y(f8) 1(i4) <-- 1 means this vertex connects to the previous vertex
|
|
||||||
## ...
|
|
||||||
## 0(i4)
|
|
||||||
##
|
|
||||||
## All values are big endian--pack using struct.pack('>d') or struct.pack('>i')
|
|
||||||
|
|
||||||
if self.opts['stepMode']:
|
if self.opts['stepMode']:
|
||||||
## each value in the x/y arrays generates 2 points.
|
## each value in the x/y arrays generates 2 points.
|
||||||
x2 = np.empty((len(x),2), dtype=x.dtype)
|
x2 = np.empty((len(x),2), dtype=x.dtype)
|
||||||
@ -287,40 +267,7 @@ class PlotCurveItem(GraphicsObject):
|
|||||||
y[0] = self.opts['fillLevel']
|
y[0] = self.opts['fillLevel']
|
||||||
y[-1] = self.opts['fillLevel']
|
y[-1] = self.opts['fillLevel']
|
||||||
|
|
||||||
|
path = fn.arrayToQPath(x, y, connect='all')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if sys.version_info[0] == 2: ## So this is disabled for python 3... why??
|
|
||||||
n = x.shape[0]
|
|
||||||
# create empty array, pad with extra space on either end
|
|
||||||
arr = np.empty(n+2, dtype=[('x', '>f8'), ('y', '>f8'), ('c', '>i4')])
|
|
||||||
# write first two integers
|
|
||||||
prof.mark('allocate empty')
|
|
||||||
arr.data[12:20] = struct.pack('>ii', n, 0)
|
|
||||||
prof.mark('pack header')
|
|
||||||
# Fill array with vertex values
|
|
||||||
arr[1:-1]['x'] = x
|
|
||||||
arr[1:-1]['y'] = y
|
|
||||||
arr[1:-1]['c'] = 1
|
|
||||||
prof.mark('fill array')
|
|
||||||
# write last 0
|
|
||||||
lastInd = 20*(n+1)
|
|
||||||
arr.data[lastInd:lastInd+4] = struct.pack('>i', 0)
|
|
||||||
prof.mark('footer')
|
|
||||||
# create datastream object and stream into path
|
|
||||||
buf = QtCore.QByteArray(arr.data[12:lastInd+4]) # I think one unnecessary copy happens here
|
|
||||||
prof.mark('create buffer')
|
|
||||||
ds = QtCore.QDataStream(buf)
|
|
||||||
prof.mark('create datastream')
|
|
||||||
ds >> path
|
|
||||||
prof.mark('load')
|
|
||||||
|
|
||||||
prof.finish()
|
|
||||||
else:
|
|
||||||
path.moveTo(x[0], y[0])
|
|
||||||
for i in range(1, y.shape[0]):
|
|
||||||
path.lineTo(x[i], y[i])
|
|
||||||
|
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
@ -1054,6 +1054,21 @@ class PlotItem(GraphicsWidget):
|
|||||||
"""
|
"""
|
||||||
self.getAxis(axis).setLabel(text=text, units=units, **args)
|
self.getAxis(axis).setLabel(text=text, units=units, **args)
|
||||||
|
|
||||||
|
def setLabels(self, **kwds):
|
||||||
|
"""
|
||||||
|
Convenience function allowing multiple labels and/or title to be set in one call.
|
||||||
|
Keyword arguments can be 'title', 'left', 'bottom', 'right', or 'top'.
|
||||||
|
Values may be strings or a tuple of arguments to pass to setLabel.
|
||||||
|
"""
|
||||||
|
for k,v in kwds.items():
|
||||||
|
if k == 'title':
|
||||||
|
self.setTitle(v)
|
||||||
|
else:
|
||||||
|
if isinstance(v, basestring):
|
||||||
|
v = (v,)
|
||||||
|
self.setLabel(k, *v)
|
||||||
|
|
||||||
|
|
||||||
def showLabel(self, axis, show=True):
|
def showLabel(self, axis, show=True):
|
||||||
"""
|
"""
|
||||||
Show or hide one of the plot's axis labels (the axis itself will be unaffected).
|
Show or hide one of the plot's axis labels (the axis itself will be unaffected).
|
||||||
|
@ -620,9 +620,12 @@ class ScatterPlotItem(GraphicsObject):
|
|||||||
|
|
||||||
if frac >= 1.0:
|
if frac >= 1.0:
|
||||||
## increase size of bounds based on spot size and pen width
|
## increase size of bounds based on spot size and pen width
|
||||||
px = self.pixelLength(Point(1, 0) if ax == 0 else Point(0, 1)) ## determine length of pixel along this axis
|
#px = self.pixelLength(Point(1, 0) if ax == 0 else Point(0, 1)) ## determine length of pixel along this axis
|
||||||
|
px = self.pixelVectors()[ax]
|
||||||
if px is None:
|
if px is None:
|
||||||
px = 0
|
px = 0
|
||||||
|
else:
|
||||||
|
px = px.length()
|
||||||
minIndex = np.argmin(d)
|
minIndex = np.argmin(d)
|
||||||
maxIndex = np.argmax(d)
|
maxIndex = np.argmax(d)
|
||||||
minVal = d[minIndex]
|
minVal = d[minIndex]
|
||||||
@ -668,6 +671,8 @@ class ScatterPlotItem(GraphicsObject):
|
|||||||
pts[1] = self.data['y']
|
pts[1] = self.data['y']
|
||||||
pts = fn.transformCoordinates(tr, pts)
|
pts = fn.transformCoordinates(tr, pts)
|
||||||
self.fragments = []
|
self.fragments = []
|
||||||
|
pts = np.clip(pts, -2**31, 2**31) ## prevent Qt segmentation fault.
|
||||||
|
## Still won't be able to render correctly, though.
|
||||||
for i in xrange(len(self.data)):
|
for i in xrange(len(self.data)):
|
||||||
rec = self.data[i]
|
rec = self.data[i]
|
||||||
pos = QtCore.QPointF(pts[0,i], pts[1,i])
|
pos = QtCore.QPointF(pts[0,i], pts[1,i])
|
||||||
@ -680,8 +685,10 @@ class ScatterPlotItem(GraphicsObject):
|
|||||||
self.invalidate()
|
self.invalidate()
|
||||||
|
|
||||||
def paint(self, p, *args):
|
def paint(self, p, *args):
|
||||||
|
|
||||||
#p.setPen(fn.mkPen('r'))
|
#p.setPen(fn.mkPen('r'))
|
||||||
#p.drawRect(self.boundingRect())
|
#p.drawRect(self.boundingRect())
|
||||||
|
|
||||||
if self._exportOpts is not False:
|
if self._exportOpts is not False:
|
||||||
aa = self._exportOpts.get('antialias', True)
|
aa = self._exportOpts.get('antialias', True)
|
||||||
scale = self._exportOpts.get('resolutionScale', 1.0) ## exporting to image; pixel resolution may have changed
|
scale = self._exportOpts.get('resolutionScale', 1.0) ## exporting to image; pixel resolution may have changed
|
||||||
@ -729,7 +736,6 @@ class ScatterPlotItem(GraphicsObject):
|
|||||||
|
|
||||||
self.picture.play(p)
|
self.picture.play(p)
|
||||||
|
|
||||||
|
|
||||||
def points(self):
|
def points(self):
|
||||||
for rec in self.data:
|
for rec in self.data:
|
||||||
if rec['item'] is None:
|
if rec['item'] is None:
|
||||||
|
Loading…
Reference in New Issue
Block a user