Bugfixes:
- Fixed some floating-point precision issues. (Added a workaround for QTransform.inverted() bug) - No longer putting asUnicode inside __builtin__ since this causes problems in some rare circumstances (pyshell, lazy import recipe) - Minor docstring updates
This commit is contained in:
parent
f81e94061f
commit
a41d330c29
@ -1,4 +1,5 @@
|
||||
from pyqtgraph.Qt import QtCore, QtGui
|
||||
from pyqtgraph.python2_3 import sortList
|
||||
#try:
|
||||
#from PyQt4 import QtOpenGL
|
||||
#HAVE_OPENGL = True
|
||||
|
@ -10,6 +10,7 @@ of a large group of widgets.
|
||||
|
||||
from .Qt import QtCore, QtGui
|
||||
import weakref, inspect
|
||||
from .python2_3 import asUnicode
|
||||
|
||||
|
||||
__all__ = ['WidgetGroup']
|
||||
|
@ -14,7 +14,8 @@ from .Qt import QtGui
|
||||
import os, sys
|
||||
|
||||
## check python version
|
||||
if sys.version_info[0] < 2 or (sys.version_info[0] == 2 and sys.version_info[1] != 7):
|
||||
## Allow anything >= 2.7
|
||||
if sys.version_info[0] < 2 or (sys.version_info[0] == 2 and sys.version_info[1] < 7):
|
||||
raise Exception("Pyqtgraph requires Python version 2.7 (this is %d.%d)" % (sys.version_info[0], sys.version_info[1]))
|
||||
|
||||
## helpers for 2/3 compatibility
|
||||
|
@ -13,6 +13,7 @@ import re, os, sys
|
||||
from collections import OrderedDict
|
||||
GLOBAL_PATH = None # so not thread safe.
|
||||
from . import units
|
||||
from .python2_3 import asUnicode
|
||||
|
||||
class ParseError(Exception):
|
||||
def __init__(self, message, lineNum, line, fileName=None):
|
||||
|
@ -1,4 +1,5 @@
|
||||
from pyqtgraph.Qt import QtCore, QtGui
|
||||
from pyqtgraph.python2_3 import asUnicode
|
||||
|
||||
class CmdInput(QtGui.QLineEdit):
|
||||
|
||||
|
17
functions.py
17
functions.py
@ -5,6 +5,7 @@ Copyright 2010 Luke Campagnola
|
||||
Distributed under MIT/X11 license. See license.txt for more infomation.
|
||||
"""
|
||||
|
||||
from .python2_3 import asUnicode
|
||||
Colors = {
|
||||
'b': (0,0,255,255),
|
||||
'g': (0,255,0,255),
|
||||
@ -1275,3 +1276,19 @@ def isosurface(data, level):
|
||||
|
||||
return facets
|
||||
|
||||
|
||||
|
||||
def invertQTransform(tr):
|
||||
"""Return a QTransform that is the inverse of *tr*.
|
||||
Rasises an exception if tr is not invertible.
|
||||
|
||||
Note that this function is preferred over QTransform.inverted() due to
|
||||
bugs in that method. (specifically, Qt has floating-point precision issues
|
||||
when determining whether a matrix is invertible)
|
||||
"""
|
||||
#return tr.inverted()[0]
|
||||
arr = np.array([[tr.m11(), tr.m12(), tr.m13()], [tr.m21(), tr.m22(), tr.m23()], [tr.m31(), tr.m32(), tr.m33()]])
|
||||
inv = scipy.linalg.inv(arr)
|
||||
return QtGui.QTransform(inv[0,0], inv[0,1], inv[0,2], inv[1,0], inv[1,1], inv[1,2], inv[2,0], inv[2,1])
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
from pyqtgraph.Qt import QtGui, QtCore
|
||||
from pyqtgraph.python2_3 import asUnicode
|
||||
import numpy as np
|
||||
from pyqtgraph.Point import Point
|
||||
import pyqtgraph.debug as debug
|
||||
|
@ -1,4 +1,5 @@
|
||||
from pyqtgraph.Qt import QtGui, QtCore
|
||||
from pyqtgraph.python2_3 import sortList
|
||||
import pyqtgraph.functions as fn
|
||||
from .GraphicsObject import GraphicsObject
|
||||
from .GraphicsWidget import GraphicsWidget
|
||||
|
@ -1,6 +1,7 @@
|
||||
from pyqtgraph.Qt import QtGui, QtCore
|
||||
from pyqtgraph.GraphicsScene import GraphicsScene
|
||||
from pyqtgraph.Point import Point
|
||||
import pyqtgraph.functions as fn
|
||||
import weakref
|
||||
|
||||
class GraphicsItem(object):
|
||||
@ -149,16 +150,32 @@ class GraphicsItem(object):
|
||||
"""Return vectors in local coordinates representing the width and height of a view pixel.
|
||||
If direction is specified, then return vectors parallel and orthogonal to it.
|
||||
|
||||
Return (None, None) if pixel size is not yet defined (usually because the item has not yet been displayed)."""
|
||||
Return (None, None) if pixel size is not yet defined (usually because the item has not yet been displayed)
|
||||
or if pixel size is below floating-point precision limit.
|
||||
"""
|
||||
|
||||
dt = self.deviceTransform()
|
||||
if dt is None:
|
||||
return None, None
|
||||
|
||||
if direction is None:
|
||||
direction = Point(1, 0)
|
||||
direction = Point(1, 0)
|
||||
if direction.manhattanLength() == 0:
|
||||
raise Exception("Cannot compute pixel length for 0-length vector.")
|
||||
|
||||
## attempt to re-scale direction vector to fit within the precision of the coordinate system
|
||||
if direction.x() == 0:
|
||||
r = abs(dt.m32())/(abs(dt.m12()) + abs(dt.m22()))
|
||||
elif direction.y() == 0:
|
||||
r = abs(dt.m31())/(abs(dt.m11()) + abs(dt.m21()))
|
||||
else:
|
||||
r = ((abs(dt.m32())/(abs(dt.m12()) + abs(dt.m22()))) * (abs(dt.m31())/(abs(dt.m11()) + abs(dt.m21()))))**0.5
|
||||
direction = direction * r
|
||||
|
||||
viewDir = Point(dt.map(direction) - dt.map(Point(0,0)))
|
||||
if viewDir.manhattanLength() == 0:
|
||||
return None, None ## pixel size cannot be represented on this scale
|
||||
|
||||
orthoDir = Point(viewDir[1], -viewDir[0]) ## orthogonal to line in pixel-space
|
||||
|
||||
try:
|
||||
@ -168,7 +185,7 @@ class GraphicsItem(object):
|
||||
raise Exception("Invalid direction %s" %direction)
|
||||
|
||||
|
||||
dti = dt.inverted()[0]
|
||||
dti = fn.invertQTransform(dt)
|
||||
return Point(dti.map(normView)-dti.map(Point(0,0))), Point(dti.map(normOrtho)-dti.map(Point(0,0)))
|
||||
|
||||
#vt = self.deviceTransform()
|
||||
@ -194,23 +211,26 @@ class GraphicsItem(object):
|
||||
|
||||
|
||||
def pixelSize(self):
|
||||
## deprecated
|
||||
v = self.pixelVectors()
|
||||
if v == (None, None):
|
||||
return None, None
|
||||
return (v[0].x()**2+v[0].y()**2)**0.5, (v[1].x()**2+v[1].y()**2)**0.5
|
||||
|
||||
def pixelWidth(self):
|
||||
## deprecated
|
||||
vt = self.deviceTransform()
|
||||
if vt is None:
|
||||
return 0
|
||||
vt = vt.inverted()[0]
|
||||
vt = fn.invertQTransform(vt)
|
||||
return Point(vt.map(QtCore.QPointF(1, 0))-vt.map(QtCore.QPointF(0, 0))).length()
|
||||
|
||||
def pixelHeight(self):
|
||||
## deprecated
|
||||
vt = self.deviceTransform()
|
||||
if vt is None:
|
||||
return 0
|
||||
vt = vt.inverted()[0]
|
||||
vt = fn.invertQTransform(vt)
|
||||
return Point(vt.map(QtCore.QPointF(0, 1))-vt.map(QtCore.QPointF(0, 0))).length()
|
||||
|
||||
|
||||
@ -232,7 +252,7 @@ class GraphicsItem(object):
|
||||
vt = self.deviceTransform()
|
||||
if vt is None:
|
||||
return None
|
||||
vt = vt.inverted()[0]
|
||||
vt = fn.invertQTransform(vt)
|
||||
return vt.map(obj)
|
||||
|
||||
def mapRectToDevice(self, rect):
|
||||
@ -253,7 +273,7 @@ class GraphicsItem(object):
|
||||
vt = self.deviceTransform()
|
||||
if vt is None:
|
||||
return None
|
||||
vt = vt.inverted()[0]
|
||||
vt = fn.invertQTransform(vt)
|
||||
return vt.mapRect(rect)
|
||||
|
||||
def mapToView(self, obj):
|
||||
@ -272,14 +292,14 @@ class GraphicsItem(object):
|
||||
vt = self.viewTransform()
|
||||
if vt is None:
|
||||
return None
|
||||
vt = vt.inverted()[0]
|
||||
vt = fn.invertQTransform(vt)
|
||||
return vt.map(obj)
|
||||
|
||||
def mapRectFromView(self, obj):
|
||||
vt = self.viewTransform()
|
||||
if vt is None:
|
||||
return None
|
||||
vt = vt.inverted()[0]
|
||||
vt = fn.invertQTransform(vt)
|
||||
return vt.mapRect(obj)
|
||||
|
||||
def pos(self):
|
||||
|
@ -2,6 +2,7 @@ from pyqtgraph.Qt import QtGui, QtCore
|
||||
from .UIGraphicsItem import *
|
||||
import numpy as np
|
||||
from pyqtgraph.Point import Point
|
||||
import pyqtgraph.functions as fn
|
||||
|
||||
__all__ = ['GridItem']
|
||||
class GridItem(UIGraphicsItem):
|
||||
@ -47,7 +48,7 @@ class GridItem(UIGraphicsItem):
|
||||
p = QtGui.QPainter()
|
||||
p.begin(self.picture)
|
||||
|
||||
dt = self.viewTransform().inverted()[0]
|
||||
dt = fn.invertQTransform(self.viewTransform())
|
||||
vr = self.getViewWidget().rect()
|
||||
unit = self.pixelWidth(), self.pixelHeight()
|
||||
dim = [vr.width(), vr.height()]
|
||||
@ -112,7 +113,7 @@ class GridItem(UIGraphicsItem):
|
||||
texts.append((QtCore.QPointF(x, y), "%g"%p1[ax]))
|
||||
tr = self.deviceTransform()
|
||||
#tr.scale(1.5, 1.5)
|
||||
p.setWorldTransform(tr.inverted()[0])
|
||||
p.setWorldTransform(fn.invertQTransform(tr))
|
||||
for t in texts:
|
||||
x = tr.map(t[0]) + Point(0.5, 0.5)
|
||||
p.drawText(x, t[1])
|
||||
|
@ -1053,6 +1053,7 @@ class PlotItem(GraphicsWidget):
|
||||
s.hide()
|
||||
|
||||
def hideAxis(self, axis):
|
||||
"""Hide one of the PlotItem's axes. ('left', 'bottom', 'right', or 'top')"""
|
||||
self.showAxis(axis, False)
|
||||
|
||||
def showScale(self, *args, **kargs):
|
||||
@ -1060,6 +1061,7 @@ class PlotItem(GraphicsWidget):
|
||||
return self.showAxis(*args, **kargs)
|
||||
|
||||
def hideButtons(self):
|
||||
"""Causes auto-scale button ('A' in lower-left corner) to be hidden for this PlotItem"""
|
||||
#self.ctrlBtn.hide()
|
||||
self.autoBtn.hide()
|
||||
|
||||
|
@ -800,7 +800,7 @@ class ROI(GraphicsObject):
|
||||
#print " dshape", dShape
|
||||
|
||||
## Determine transform that maps ROI bounding box to image coordinates
|
||||
tr = self.sceneTransform() * img.sceneTransform().inverted()[0]
|
||||
tr = self.sceneTransform() * fn.invertQTransform(img.sceneTransform())
|
||||
|
||||
## Modify transform to scale from image coords to data coords
|
||||
#m = QtGui.QTransform()
|
||||
@ -1251,7 +1251,7 @@ class Handle(UIGraphicsItem):
|
||||
v = dt.map(QtCore.QPointF(1, 0)) - dt.map(QtCore.QPointF(0, 0))
|
||||
va = np.arctan2(v.y(), v.x())
|
||||
|
||||
dti = dt.inverted()[0]
|
||||
dti = fn.invertQTransform(dt)
|
||||
devPos = dt.map(QtCore.QPointF(0,0))
|
||||
tr = QtGui.QTransform()
|
||||
tr.translate(devPos.x(), devPos.y())
|
||||
|
@ -1,6 +1,7 @@
|
||||
from pyqtgraph.Qt import QtCore, QtGui
|
||||
import pyqtgraph as pg
|
||||
from .UIGraphicsItem import *
|
||||
import pyqtgraph.functions as fn
|
||||
|
||||
class TextItem(UIGraphicsItem):
|
||||
"""
|
||||
@ -87,7 +88,7 @@ class TextItem(UIGraphicsItem):
|
||||
if br is None:
|
||||
return
|
||||
self.prepareGeometryChange()
|
||||
self._bounds = self.deviceTransform().inverted()[0].mapRect(br)
|
||||
self._bounds = fn.invertQTransform(self.deviceTransform()).mapRect(br)
|
||||
#print self._bounds
|
||||
|
||||
def boundingRect(self):
|
||||
|
@ -1,4 +1,5 @@
|
||||
from pyqtgraph.Qt import QtGui, QtCore
|
||||
from pyqtgraph.python2_3 import sortList
|
||||
import numpy as np
|
||||
from pyqtgraph.Point import Point
|
||||
import pyqtgraph.functions as fn
|
||||
@ -451,10 +452,8 @@ class ViewBox(GraphicsWidget):
|
||||
center = Point(vr.center())
|
||||
else:
|
||||
center = Point(center)
|
||||
|
||||
tl = center + (vr.topLeft()-center) * scale
|
||||
br = center + (vr.bottomRight()-center) * scale
|
||||
|
||||
self.setRange(QtCore.QRectF(tl, br), padding=0)
|
||||
|
||||
def translateBy(self, t):
|
||||
@ -764,7 +763,7 @@ class ViewBox(GraphicsWidget):
|
||||
|
||||
def mapToView(self, obj):
|
||||
"""Maps from the local coordinates of the ViewBox to the coordinate system displayed inside the ViewBox"""
|
||||
m = self.childTransform().inverted()[0]
|
||||
m = fn.invertQTransform(self.childTransform())
|
||||
return m.map(obj)
|
||||
|
||||
def mapFromView(self, obj):
|
||||
@ -830,7 +829,7 @@ class ViewBox(GraphicsWidget):
|
||||
mask[axis] = mv
|
||||
s = ((mask * 0.02) + 1) ** (ev.delta() * self.state['wheelScaleFactor']) # actual scaling factor
|
||||
|
||||
center = Point(self.childGroup.transform().inverted()[0].map(ev.pos()))
|
||||
center = Point(fn.invertQTransform(self.childGroup.transform()).map(ev.pos()))
|
||||
#center = ev.pos()
|
||||
|
||||
self.scaleBy(s, center)
|
||||
@ -913,8 +912,11 @@ class ViewBox(GraphicsWidget):
|
||||
dif = np.array([dif.x(), dif.y()])
|
||||
dif[0] *= -1
|
||||
s = ((mask * 0.02) + 1) ** dif
|
||||
center = Point(self.childGroup.transform().inverted()[0].map(ev.buttonDownPos(QtCore.Qt.RightButton)))
|
||||
#center = Point(ev.buttonDownPos(QtCore.Qt.RightButton))
|
||||
|
||||
tr = self.childGroup.transform()
|
||||
tr = fn.invertQTransform(tr)
|
||||
|
||||
center = Point(tr.map(ev.buttonDownPos(QtCore.Qt.RightButton)))
|
||||
self.scaleBy(s, center)
|
||||
self.sigRangeChangedManually.emit(self.state['mouseEnabled'])
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
from pyqtgraph.Qt import QtCore, QtGui
|
||||
from pyqtgraph.python2_3 import asUnicode
|
||||
from pyqtgraph.WidgetGroup import WidgetGroup
|
||||
from .axisCtrlTemplate import Ui_Form as AxisCtrlTemplate
|
||||
import weakref
|
||||
|
@ -1,4 +1,5 @@
|
||||
from pyqtgraph.Qt import QtCore, QtGui
|
||||
from pyqtgraph.python2_3 import asUnicode
|
||||
from .Parameter import Parameter, registerParameterType
|
||||
from .ParameterItem import ParameterItem
|
||||
from pyqtgraph.widgets.SpinBox import SpinBox
|
||||
|
13
python2_3.py
13
python2_3.py
@ -42,8 +42,9 @@ def sortList(l, cmpFunc):
|
||||
if sys.version_info[0] == 3:
|
||||
import builtins
|
||||
builtins.basestring = str
|
||||
builtins.asUnicode = asUnicode
|
||||
builtins.sortList = sortList
|
||||
#builtins.asUnicode = asUnicode
|
||||
#builtins.sortList = sortList
|
||||
basestring = str
|
||||
def cmp(a,b):
|
||||
if a>b:
|
||||
return 1
|
||||
@ -52,7 +53,7 @@ if sys.version_info[0] == 3:
|
||||
else:
|
||||
return 0
|
||||
builtins.cmp = cmp
|
||||
else:
|
||||
import __builtin__
|
||||
__builtin__.asUnicode = asUnicode
|
||||
__builtin__.sortList = sortList
|
||||
#else: ## don't use __builtin__ -- this confuses things like pyshell and ActiveState's lazy import recipe
|
||||
#import __builtin__
|
||||
#__builtin__.asUnicode = asUnicode
|
||||
#__builtin__.sortList = sortList
|
||||
|
@ -1,5 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from pyqtgraph.Qt import QtGui, QtCore
|
||||
from pyqtgraph.python2_3 import asUnicode
|
||||
from pyqtgraph.SignalProxy import SignalProxy
|
||||
|
||||
import pyqtgraph.functions as fn
|
||||
|
@ -1,5 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from pyqtgraph.Qt import QtGui, QtCore
|
||||
from pyqtgraph.python2_3 import asUnicode
|
||||
|
||||
import numpy as np
|
||||
try:
|
||||
|
Loading…
x
Reference in New Issue
Block a user