- re-merged isocurve code
- re-enabled OpenGL on windows, added a config option for enabling/disabling OpenGL - minor bug fixes
This commit is contained in:
parent
543d56f0a6
commit
ad232ff79b
12
__init__.py
12
__init__.py
|
@ -9,7 +9,19 @@ from Qt import QtGui
|
||||||
#if QtGui.QApplication.instance() is None:
|
#if QtGui.QApplication.instance() is None:
|
||||||
#app = QtGui.QApplication([])
|
#app = QtGui.QApplication([])
|
||||||
|
|
||||||
|
## in general openGL is poorly supported in Qt.
|
||||||
|
## we only enable it where the performance benefit is critical.
|
||||||
|
## Note this only applies to 2D graphics; 3D graphics always use OpenGL.
|
||||||
|
import sys
|
||||||
|
if 'linux' in sys.platform: ## linux has numerous bugs in opengl implementation
|
||||||
|
useOpenGL = False
|
||||||
|
elif 'darwin' in sys.platform: ## openGL greatly speeds up display on mac
|
||||||
|
useOpenGL = True
|
||||||
|
else:
|
||||||
|
useOpenGL = True ## on windows there's a more even performance / bugginess tradeoff.
|
||||||
|
|
||||||
CONFIG_OPTIONS = {
|
CONFIG_OPTIONS = {
|
||||||
|
'useOpenGL': None, ## by default, this is platform-dependent (see widgets/GraphicsView). Set to True or False to explicitly enable/disable opengl.
|
||||||
'leftButtonPan': True ## if false, left button drags a rubber band for zooming in viewbox
|
'leftButtonPan': True ## if false, left button drags a rubber band for zooming in viewbox
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
89
functions.py
89
functions.py
|
@ -409,12 +409,12 @@ def affineSlice(data, shape, origin, vectors, axes, **kargs):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def makeARGB(data, lut=None, levels=None):
|
def makeARGB(data, lut=None, levels=None, useRGBA=False):
|
||||||
"""
|
"""
|
||||||
Convert a 2D or 3D array into an ARGB array suitable for building QImages
|
Convert a 2D or 3D array into an ARGB array suitable for building QImages
|
||||||
Will optionally do scaling and/or table lookups to determine final colors.
|
Will optionally do scaling and/or table lookups to determine final colors.
|
||||||
|
|
||||||
Returns the ARGB array and a boolean indicating whether there is alpha channel data.
|
Returns the ARGB array (values 0-255) and a boolean indicating whether there is alpha channel data.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
data - 2D or 3D numpy array of int/float types
|
data - 2D or 3D numpy array of int/float types
|
||||||
|
@ -433,9 +433,10 @@ def makeARGB(data, lut=None, levels=None):
|
||||||
Lookup tables can be built using GradientWidget.
|
Lookup tables can be built using GradientWidget.
|
||||||
levels - List [min, max]; optionally rescale data before converting through the
|
levels - List [min, max]; optionally rescale data before converting through the
|
||||||
lookup table. rescaled = (data-min) * len(lut) / (max-min)
|
lookup table. rescaled = (data-min) * len(lut) / (max-min)
|
||||||
|
useRGBA - If True, the data is returned in RGBA order. The default is
|
||||||
|
False, which returns in BGRA order for use with QImage.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
prof = debug.Profiler('functions.makeARGB', disabled=True)
|
prof = debug.Profiler('functions.makeARGB', disabled=True)
|
||||||
|
|
||||||
## sanity checks
|
## sanity checks
|
||||||
|
@ -580,6 +581,10 @@ def makeARGB(data, lut=None, levels=None):
|
||||||
|
|
||||||
prof.mark('4')
|
prof.mark('4')
|
||||||
|
|
||||||
|
if useRGBA:
|
||||||
|
order = [0,1,2,3] ## array comes out RGBA
|
||||||
|
else:
|
||||||
|
order = [2,1,0,3] ## for some reason, the colors line up as BGR in the final image.
|
||||||
|
|
||||||
order = [2,1,0,3] ## for some reason, the colors line up as BGR in the final image.
|
order = [2,1,0,3] ## for some reason, the colors line up as BGR in the final image.
|
||||||
if data.shape[2] == 1:
|
if data.shape[2] == 1:
|
||||||
|
@ -732,6 +737,84 @@ def rescaleData(data, scale, offset):
|
||||||
#return facets
|
#return facets
|
||||||
|
|
||||||
|
|
||||||
|
def isocurve(data, level):
|
||||||
|
"""
|
||||||
|
Generate isocurve from 2D data using marching squares algorithm.
|
||||||
|
|
||||||
|
*data* 2D numpy array of scalar values
|
||||||
|
*level* The level at which to generate an isosurface
|
||||||
|
|
||||||
|
This function is SLOW; plenty of room for optimization here.
|
||||||
|
"""
|
||||||
|
|
||||||
|
sideTable = [
|
||||||
|
[],
|
||||||
|
[0,1],
|
||||||
|
[1,2],
|
||||||
|
[0,2],
|
||||||
|
[0,3],
|
||||||
|
[1,3],
|
||||||
|
[0,1,2,3],
|
||||||
|
[2,3],
|
||||||
|
[2,3],
|
||||||
|
[0,1,2,3],
|
||||||
|
[1,3],
|
||||||
|
[0,3],
|
||||||
|
[0,2],
|
||||||
|
[1,2],
|
||||||
|
[0,1],
|
||||||
|
[]
|
||||||
|
]
|
||||||
|
|
||||||
|
edgeKey=[
|
||||||
|
[(0,1),(0,0)],
|
||||||
|
[(0,0), (1,0)],
|
||||||
|
[(1,0), (1,1)],
|
||||||
|
[(1,1), (0,1)]
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
lines = []
|
||||||
|
|
||||||
|
## mark everything below the isosurface level
|
||||||
|
mask = data < level
|
||||||
|
|
||||||
|
### make four sub-fields and compute indexes for grid cells
|
||||||
|
index = np.zeros([x-1 for x in data.shape], dtype=np.ubyte)
|
||||||
|
fields = np.empty((2,2), dtype=object)
|
||||||
|
slices = [slice(0,-1), slice(1,None)]
|
||||||
|
for i in [0,1]:
|
||||||
|
for j in [0,1]:
|
||||||
|
fields[i,j] = mask[slices[i], slices[j]]
|
||||||
|
#vertIndex = i - 2*j*i + 3*j + 4*k ## this is just to match Bourk's vertex numbering scheme
|
||||||
|
vertIndex = i+2*j
|
||||||
|
#print i,j,k," : ", fields[i,j,k], 2**vertIndex
|
||||||
|
index += fields[i,j] * 2**vertIndex
|
||||||
|
#print index
|
||||||
|
#print index
|
||||||
|
|
||||||
|
## add lines
|
||||||
|
for i in xrange(index.shape[0]): # data x-axis
|
||||||
|
for j in xrange(index.shape[1]): # data y-axis
|
||||||
|
sides = sideTable[index[i,j]]
|
||||||
|
for l in range(0, len(sides), 2): ## faces for this grid cell
|
||||||
|
edges = sides[l:l+2]
|
||||||
|
pts = []
|
||||||
|
for m in [0,1]: # points in this face
|
||||||
|
p1 = edgeKey[edges[m]][0] # p1, p2 are points at either side of an edge
|
||||||
|
p2 = edgeKey[edges[m]][1]
|
||||||
|
v1 = data[i+p1[0], j+p1[1]] # v1 and v2 are the values at p1 and p2
|
||||||
|
v2 = data[i+p2[0], j+p2[1]]
|
||||||
|
f = (level-v1) / (v2-v1)
|
||||||
|
fi = 1.0 - f
|
||||||
|
p = ( ## interpolate between corners
|
||||||
|
p1[0]*fi + p2[0]*f + i + 0.5,
|
||||||
|
p1[1]*fi + p2[1]*f + j + 0.5
|
||||||
|
)
|
||||||
|
pts.append(p)
|
||||||
|
lines.append(pts)
|
||||||
|
|
||||||
|
return lines ## a list of pairs of points
|
||||||
|
|
||||||
|
|
||||||
def isosurface(data, level):
|
def isosurface(data, level):
|
||||||
|
|
|
@ -64,6 +64,9 @@ class VTickGroup(UIGraphicsItem):
|
||||||
self.rebuildTicks()
|
self.rebuildTicks()
|
||||||
#self.valid = False
|
#self.valid = False
|
||||||
|
|
||||||
|
def dataBounds(self, *args, **kargs):
|
||||||
|
return None ## item should never affect view autoscaling
|
||||||
|
|
||||||
#def viewRangeChanged(self):
|
#def viewRangeChanged(self):
|
||||||
### called when the view is scaled
|
### called when the view is scaled
|
||||||
|
|
||||||
|
|
|
@ -820,10 +820,10 @@ class ViewBox(GraphicsWidget):
|
||||||
frac = (1.0, 1.0)
|
frac = (1.0, 1.0)
|
||||||
xr = item.dataBounds(0, frac=frac[0])
|
xr = item.dataBounds(0, frac=frac[0])
|
||||||
yr = item.dataBounds(1, frac=frac[1])
|
yr = item.dataBounds(1, frac=frac[1])
|
||||||
if xr is None:
|
if xr is None or xr == (None, None):
|
||||||
useX = False
|
useX = False
|
||||||
xr = (0,0)
|
xr = (0,0)
|
||||||
if yr is None:
|
if yr is None or yr == (None, None):
|
||||||
useY = False
|
useY = False
|
||||||
yr = (0,0)
|
yr = (0,0)
|
||||||
|
|
||||||
|
|
|
@ -405,7 +405,7 @@ class ListParameterItem(WidgetParameterItem):
|
||||||
#return vals[key]
|
#return vals[key]
|
||||||
#else:
|
#else:
|
||||||
#return key
|
#return key
|
||||||
print key, self.forward
|
#print key, self.forward
|
||||||
return self.forward[key]
|
return self.forward[key]
|
||||||
|
|
||||||
def setValue(self, val):
|
def setValue(self, val):
|
||||||
|
|
|
@ -16,6 +16,7 @@ from FileDialog import FileDialog
|
||||||
from pyqtgraph.GraphicsScene import GraphicsScene
|
from pyqtgraph.GraphicsScene import GraphicsScene
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import pyqtgraph.functions as fn
|
import pyqtgraph.functions as fn
|
||||||
|
import pyqtgraph
|
||||||
|
|
||||||
__all__ = ['GraphicsView']
|
__all__ = ['GraphicsView']
|
||||||
|
|
||||||
|
@ -38,20 +39,14 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||||
autoPixelRange=False. The exact visible range can be set with setRange().
|
autoPixelRange=False. The exact visible range can be set with setRange().
|
||||||
|
|
||||||
The view can be panned using the middle mouse button and scaled using the right mouse button if
|
The view can be panned using the middle mouse button and scaled using the right mouse button if
|
||||||
enabled via enableMouse()."""
|
enabled via enableMouse() (but ordinarily, we use ViewBox for this functionality)."""
|
||||||
self.closed = False
|
self.closed = False
|
||||||
|
|
||||||
QtGui.QGraphicsView.__init__(self, parent)
|
QtGui.QGraphicsView.__init__(self, parent)
|
||||||
|
|
||||||
## in general openGL is poorly supported in Qt.
|
|
||||||
## we only enable it where the performance benefit is critical.
|
|
||||||
if useOpenGL is None:
|
if useOpenGL is None:
|
||||||
if 'linux' in sys.platform: ## linux has numerous bugs in opengl implementation
|
useOpenGL = pyqtgraph.getConfigOption('useOpenGL')
|
||||||
useOpenGL = False
|
|
||||||
elif 'darwin' in sys.platform: ## openGL greatly speeds up display on mac
|
|
||||||
useOpenGL = True
|
|
||||||
else:
|
|
||||||
useOpenGL = False
|
|
||||||
self.useOpenGL(useOpenGL)
|
self.useOpenGL(useOpenGL)
|
||||||
|
|
||||||
self.setCacheMode(self.CacheBackground)
|
self.setCacheMode(self.CacheBackground)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user