merge with inp
This commit is contained in:
commit
a290a39779
@ -1078,14 +1078,29 @@ def arrayToQPath(x, y, connect='all'):
|
|||||||
should be connected, or an array of int32 values (0 or 1) indicating
|
should be connected, or an array of int32 values (0 or 1) indicating
|
||||||
connections.
|
connections.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
## Create all vertices in path. The method used below creates a binary format so that all
|
## 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,
|
## 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:
|
## so the original (slower) method is left here for emergencies:
|
||||||
#path.moveTo(x[0], y[0])
|
#path.moveTo(x[0], y[0])
|
||||||
#for i in range(1, y.shape[0]):
|
#if connect == 'all':
|
||||||
# path.lineTo(x[i], y[i])
|
#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')
|
||||||
|
|
||||||
## Speed this up using >> operator
|
## Speed this up using >> operator
|
||||||
## Format is:
|
## Format is:
|
||||||
## numVerts(i4) 0(i4)
|
## numVerts(i4) 0(i4)
|
||||||
@ -1095,76 +1110,60 @@ def arrayToQPath(x, y, connect='all'):
|
|||||||
## 0(i4)
|
## 0(i4)
|
||||||
##
|
##
|
||||||
## All values are big endian--pack using struct.pack('>d') or struct.pack('>i')
|
## All values are big endian--pack using struct.pack('>d') or struct.pack('>i')
|
||||||
|
|
||||||
path = QtGui.QPainterPath()
|
path = QtGui.QPainterPath()
|
||||||
|
|
||||||
#prof = debug.Profiler('PlotCurveItem.generatePath', disabled=True)
|
#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]
|
||||||
n = x.shape[0]
|
# create empty array, pad with extra space on either end
|
||||||
# create empty array, pad with extra space on either end
|
arr = np.empty(n+2, dtype=[('x', '>f8'), ('y', '>f8'), ('c', '>i4')])
|
||||||
arr = np.empty(n+2, dtype=[('x', '>f8'), ('y', '>f8'), ('c', '>i4')])
|
# write first two integers
|
||||||
# write first two integers
|
#prof.mark('allocate empty')
|
||||||
#prof.mark('allocate empty')
|
byteview = arr.view(dtype=np.ubyte)
|
||||||
arr.data[12:20] = struct.pack('>ii', n, 0)
|
byteview[:12] = 0
|
||||||
#prof.mark('pack header')
|
byteview.data[12:20] = struct.pack('>ii', n, 0)
|
||||||
# Fill array with vertex values
|
#prof.mark('pack header')
|
||||||
arr[1:-1]['x'] = x
|
# Fill array with vertex values
|
||||||
arr[1:-1]['y'] = y
|
arr[1:-1]['x'] = x
|
||||||
|
arr[1:-1]['y'] = y
|
||||||
# decide which points are connected by lines
|
|
||||||
if connect == 'pairs':
|
# decide which points are connected by lines
|
||||||
connect = np.empty((n/2,2), dtype=np.int32)
|
if connect == 'pairs':
|
||||||
connect[:,0] = 1
|
connect = np.empty((n/2,2), dtype=np.int32)
|
||||||
connect[:,1] = 0
|
connect[:,0] = 1
|
||||||
connect = connect.flatten()
|
connect[:,1] = 0
|
||||||
|
connect = connect.flatten()
|
||||||
if connect == 'all':
|
|
||||||
arr[1:-1]['c'] = 1
|
if connect == 'all':
|
||||||
elif isinstance(connect, np.ndarray):
|
arr[1:-1]['c'] = 1
|
||||||
arr[1:-1]['c'] = connect
|
elif isinstance(connect, np.ndarray):
|
||||||
else:
|
arr[1:-1]['c'] = connect
|
||||||
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
|
|
||||||
|
|
||||||
## Avoiding this method because QByteArray(str) leaks memory in PySide
|
|
||||||
#buf = QtCore.QByteArray(arr.data[12:lastInd+4]) # I think one unnecessary copy happens here
|
|
||||||
|
|
||||||
path.strn = arr.data[12:lastInd+4] # make sure data doesn't run away
|
|
||||||
buf = QtCore.QByteArray.fromRawData(path.strn)
|
|
||||||
#prof.mark('create buffer')
|
|
||||||
ds = QtCore.QDataStream(buf)
|
|
||||||
|
|
||||||
ds >> path
|
|
||||||
#prof.mark('load')
|
|
||||||
|
|
||||||
#prof.finish()
|
|
||||||
else:
|
else:
|
||||||
## This does exactly the same as above, but less efficiently (and more simply).
|
raise Exception('connect argument must be "all", "pairs", or array')
|
||||||
path.moveTo(x[0], y[0])
|
|
||||||
if connect == 'all':
|
#prof.mark('fill array')
|
||||||
for i in range(1, y.shape[0]):
|
# write last 0
|
||||||
path.lineTo(x[i], y[i])
|
lastInd = 20*(n+1)
|
||||||
elif connect == 'pairs':
|
byteview.data[lastInd:lastInd+4] = struct.pack('>i', 0)
|
||||||
for i in range(1, y.shape[0]):
|
#prof.mark('footer')
|
||||||
if i%2 == 0:
|
# create datastream object and stream into path
|
||||||
path.lineTo(x[i], y[i])
|
|
||||||
else:
|
## Avoiding this method because QByteArray(str) leaks memory in PySide
|
||||||
path.moveTo(x[i], y[i])
|
#buf = QtCore.QByteArray(arr.data[12:lastInd+4]) # I think one unnecessary copy happens here
|
||||||
elif isinstance(connect, np.ndarray):
|
|
||||||
for i in range(1, y.shape[0]):
|
path.strn = byteview.data[12:lastInd+4] # make sure data doesn't run away
|
||||||
if connect[i] == 1:
|
try:
|
||||||
path.lineTo(x[i], y[i])
|
buf = QtCore.QByteArray.fromRawData(path.strn)
|
||||||
else:
|
except TypeError:
|
||||||
path.moveTo(x[i], y[i])
|
buf = QtCore.QByteArray(bytes(path.strn))
|
||||||
else:
|
#prof.mark('create buffer')
|
||||||
raise Exception('connect argument must be "all", "pairs", or array')
|
ds = QtCore.QDataStream(buf)
|
||||||
|
|
||||||
|
ds >> path
|
||||||
|
#prof.mark('load')
|
||||||
|
|
||||||
|
#prof.finish()
|
||||||
|
|
||||||
return path
|
return path
|
||||||
|
|
||||||
#def isosurface(data, level):
|
#def isosurface(data, level):
|
||||||
|
@ -80,23 +80,26 @@ class GLViewWidget(QtOpenGL.QGLWidget):
|
|||||||
#self.update()
|
#self.update()
|
||||||
|
|
||||||
def setProjection(self, region=None):
|
def setProjection(self, region=None):
|
||||||
|
m = self.projectionMatrix(region)
|
||||||
|
glMatrixMode(GL_PROJECTION)
|
||||||
|
glLoadIdentity()
|
||||||
|
a = np.array(m.copyDataTo()).reshape((4,4))
|
||||||
|
glMultMatrixf(a.transpose())
|
||||||
|
|
||||||
|
def projectionMatrix(self, region=None):
|
||||||
# Xw = (Xnd + 1) * width/2 + X
|
# Xw = (Xnd + 1) * width/2 + X
|
||||||
if region is None:
|
if region is None:
|
||||||
region = (0, 0, self.width(), self.height())
|
region = (0, 0, self.width(), self.height())
|
||||||
## Create the projection matrix
|
|
||||||
glMatrixMode(GL_PROJECTION)
|
|
||||||
glLoadIdentity()
|
|
||||||
#w = self.width()
|
|
||||||
#h = self.height()
|
|
||||||
x0, y0, w, h = self.getViewport()
|
x0, y0, w, h = self.getViewport()
|
||||||
dist = self.opts['distance']
|
dist = self.opts['distance']
|
||||||
fov = self.opts['fov']
|
fov = self.opts['fov']
|
||||||
nearClip = dist * 0.001
|
nearClip = dist * 0.001
|
||||||
farClip = dist * 1000.
|
farClip = dist * 1000.
|
||||||
|
|
||||||
r = nearClip * np.tan(fov * 0.5 * np.pi / 180.)
|
r = nearClip * np.tan(fov * 0.5 * np.pi / 180.)
|
||||||
t = r * h / w
|
t = r * h / w
|
||||||
|
|
||||||
# convert screen coordinates (region) to normalized device coordinates
|
# convert screen coordinates (region) to normalized device coordinates
|
||||||
# Xnd = (Xw - X0) * 2/width - 1
|
# Xnd = (Xw - X0) * 2/width - 1
|
||||||
## Note that X0 and width in these equations must be the values used in viewport
|
## Note that X0 and width in these equations must be the values used in viewport
|
||||||
@ -104,21 +107,46 @@ class GLViewWidget(QtOpenGL.QGLWidget):
|
|||||||
right = r * ((region[0]+region[2]-x0) * (2.0/w) - 1)
|
right = r * ((region[0]+region[2]-x0) * (2.0/w) - 1)
|
||||||
bottom = t * ((region[1]-y0) * (2.0/h) - 1)
|
bottom = t * ((region[1]-y0) * (2.0/h) - 1)
|
||||||
top = t * ((region[1]+region[3]-y0) * (2.0/h) - 1)
|
top = t * ((region[1]+region[3]-y0) * (2.0/h) - 1)
|
||||||
|
|
||||||
glFrustum( left, right, bottom, top, nearClip, farClip)
|
tr = QtGui.QMatrix4x4()
|
||||||
#glFrustum(-r, r, -t, t, nearClip, farClip)
|
tr.frustum(left, right, bottom, top, nearClip, farClip)
|
||||||
|
return tr
|
||||||
|
|
||||||
def setModelview(self):
|
def setModelview(self):
|
||||||
glMatrixMode(GL_MODELVIEW)
|
glMatrixMode(GL_MODELVIEW)
|
||||||
glLoadIdentity()
|
glLoadIdentity()
|
||||||
glTranslatef( 0.0, 0.0, -self.opts['distance'])
|
m = self.viewMatrix()
|
||||||
glRotatef(self.opts['elevation']-90, 1, 0, 0)
|
a = np.array(m.copyDataTo()).reshape((4,4))
|
||||||
glRotatef(self.opts['azimuth']+90, 0, 0, -1)
|
glMultMatrixf(a.transpose())
|
||||||
|
|
||||||
|
def viewMatrix(self):
|
||||||
|
tr = QtGui.QMatrix4x4()
|
||||||
|
tr.translate( 0.0, 0.0, -self.opts['distance'])
|
||||||
|
tr.rotate(self.opts['elevation']-90, 1, 0, 0)
|
||||||
|
tr.rotate(self.opts['azimuth']+90, 0, 0, -1)
|
||||||
center = self.opts['center']
|
center = self.opts['center']
|
||||||
glTranslatef(-center.x(), -center.y(), -center.z())
|
tr.translate(-center.x(), -center.y(), -center.z())
|
||||||
|
return tr
|
||||||
|
|
||||||
|
def itemsAt(self, region=None):
|
||||||
|
#buf = np.zeros(100000, dtype=np.uint)
|
||||||
|
buf = glSelectBuffer(100000)
|
||||||
|
try:
|
||||||
|
glRenderMode(GL_SELECT)
|
||||||
|
glInitNames()
|
||||||
|
glPushName(0)
|
||||||
|
self._itemNames = {}
|
||||||
|
self.paintGL(region=region, useItemNames=True)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
hits = glRenderMode(GL_RENDER)
|
||||||
|
|
||||||
|
items = [(h.near, h.names[0]) for h in hits]
|
||||||
|
items.sort(key=lambda i: i[0])
|
||||||
|
|
||||||
|
return [self._itemNames[i[1]] for i in items]
|
||||||
|
|
||||||
def paintGL(self, region=None, viewport=None):
|
def paintGL(self, region=None, viewport=None, useItemNames=False):
|
||||||
"""
|
"""
|
||||||
viewport specifies the arguments to glViewport. If None, then we use self.opts['viewport']
|
viewport specifies the arguments to glViewport. If None, then we use self.opts['viewport']
|
||||||
region specifies the sub-region of self.opts['viewport'] that should be rendered.
|
region specifies the sub-region of self.opts['viewport'] that should be rendered.
|
||||||
@ -131,9 +159,9 @@ class GLViewWidget(QtOpenGL.QGLWidget):
|
|||||||
self.setProjection(region=region)
|
self.setProjection(region=region)
|
||||||
self.setModelview()
|
self.setModelview()
|
||||||
glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT )
|
glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT )
|
||||||
self.drawItemTree()
|
self.drawItemTree(useItemNames=useItemNames)
|
||||||
|
|
||||||
def drawItemTree(self, item=None):
|
def drawItemTree(self, item=None, useItemNames=False):
|
||||||
if item is None:
|
if item is None:
|
||||||
items = [x for x in self.items if x.parentItem() is None]
|
items = [x for x in self.items if x.parentItem() is None]
|
||||||
else:
|
else:
|
||||||
@ -146,6 +174,9 @@ class GLViewWidget(QtOpenGL.QGLWidget):
|
|||||||
if i is item:
|
if i is item:
|
||||||
try:
|
try:
|
||||||
glPushAttrib(GL_ALL_ATTRIB_BITS)
|
glPushAttrib(GL_ALL_ATTRIB_BITS)
|
||||||
|
if useItemNames:
|
||||||
|
glLoadName(id(i))
|
||||||
|
self._itemNames[id(i)] = i
|
||||||
i.paint()
|
i.paint()
|
||||||
except:
|
except:
|
||||||
import pyqtgraph.debug
|
import pyqtgraph.debug
|
||||||
@ -168,7 +199,7 @@ class GLViewWidget(QtOpenGL.QGLWidget):
|
|||||||
tr = i.transform()
|
tr = i.transform()
|
||||||
a = np.array(tr.copyDataTo()).reshape((4,4))
|
a = np.array(tr.copyDataTo()).reshape((4,4))
|
||||||
glMultMatrixf(a.transpose())
|
glMultMatrixf(a.transpose())
|
||||||
self.drawItemTree(i)
|
self.drawItemTree(i, useItemNames=useItemNames)
|
||||||
finally:
|
finally:
|
||||||
glMatrixMode(GL_MODELVIEW)
|
glMatrixMode(GL_MODELVIEW)
|
||||||
glPopMatrix()
|
glPopMatrix()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user