Merge branch 'develop' into pyqtgraph-core

This commit is contained in:
Luke Campagnola 2013-12-23 11:16:39 -05:00
commit 1dae1def22
147 changed files with 1390 additions and 1277 deletions

View File

@ -1,19 +1,11 @@
from pyqtgraph.Qt import QtCore, QtGui
from pyqtgraph.python2_3 import sortList
#try:
#from PyQt4 import QtOpenGL
#HAVE_OPENGL = True
#except ImportError:
#HAVE_OPENGL = False
from ..Qt import QtCore, QtGui
from ..python2_3 import sortList
import weakref
from pyqtgraph.Point import Point
import pyqtgraph.functions as fn
import pyqtgraph.ptime as ptime
from ..Point import Point
from .. import functions as fn
from .. import ptime as ptime
from .mouseEvents import *
import pyqtgraph.debug as debug
from . import exportDialog
from .. import debug as debug
if hasattr(QtCore, 'PYQT_VERSION'):
try:
@ -520,27 +512,20 @@ class GraphicsScene(QtGui.QGraphicsScene):
============== ==================================================
"""
#items = self.itemsNearEvent(ev)
menusToAdd = []
while item is not self:
item = item.parentItem()
if item is None:
item = self
if not hasattr(item, "getContextMenus"):
continue
subMenus = item.getContextMenus(event) or []
if isinstance(subMenus, list): ## so that some items (like FlowchartViewBox) can return multiple menus
menusToAdd.extend(subMenus)
else:
menusToAdd.append(subMenus)
subMenus = item.getContextMenus(event)
if subMenus is None:
continue
if type(subMenus) is not list: ## so that some items (like FlowchartViewBox) can return multiple menus
subMenus = [subMenus]
for sm in subMenus:
menusToAdd.append(sm)
if len(menusToAdd) > 0:
if menusToAdd:
menu.addSeparator()
for m in menusToAdd:
@ -559,6 +544,7 @@ class GraphicsScene(QtGui.QGraphicsScene):
def showExportDialog(self):
if self.exportDialog is None:
from . import exportDialog
self.exportDialog = exportDialog.ExportDialog(self)
self.exportDialog.show(self.contextMenuItem)

View File

@ -1,6 +1,8 @@
from pyqtgraph.Qt import QtCore, QtGui, USE_PYSIDE
import pyqtgraph as pg
import pyqtgraph.exporters as exporters
from ..Qt import QtCore, QtGui, USE_PYSIDE
from .. import exporters as exporters
from .. import functions as fn
from ..graphicsItems.ViewBox import ViewBox
from ..graphicsItems.PlotItem import PlotItem
if USE_PYSIDE:
from . import exportDialogTemplate_pyside as exportDialogTemplate
@ -18,7 +20,7 @@ class ExportDialog(QtGui.QWidget):
self.scene = scene
self.selectBox = QtGui.QGraphicsRectItem()
self.selectBox.setPen(pg.mkPen('y', width=3, style=QtCore.Qt.DashLine))
self.selectBox.setPen(fn.mkPen('y', width=3, style=QtCore.Qt.DashLine))
self.selectBox.hide()
self.scene.addItem(self.selectBox)
@ -35,10 +37,10 @@ class ExportDialog(QtGui.QWidget):
def show(self, item=None):
if item is not None:
## Select next exportable parent of the item originally clicked on
while not isinstance(item, pg.ViewBox) and not isinstance(item, pg.PlotItem) and item is not None:
while not isinstance(item, ViewBox) and not isinstance(item, PlotItem) and item is not None:
item = item.parentItem()
## if this is a ViewBox inside a PlotItem, select the parent instead.
if isinstance(item, pg.ViewBox) and isinstance(item.parentItem(), pg.PlotItem):
if isinstance(item, ViewBox) and isinstance(item.parentItem(), PlotItem):
item = item.parentItem()
self.updateItemList(select=item)
self.setVisible(True)
@ -64,9 +66,9 @@ class ExportDialog(QtGui.QWidget):
def updateItemTree(self, item, treeItem, select=None):
si = None
if isinstance(item, pg.ViewBox):
if isinstance(item, ViewBox):
si = QtGui.QTreeWidgetItem(['ViewBox'])
elif isinstance(item, pg.PlotItem):
elif isinstance(item, PlotItem):
si = QtGui.QTreeWidgetItem(['Plot'])
if si is not None:

View File

@ -92,7 +92,7 @@
<customwidget>
<class>ParameterTree</class>
<extends>QTreeWidget</extends>
<header>pyqtgraph.parametertree</header>
<header>..parametertree</header>
</customwidget>
</customwidgets>
<resources/>

View File

@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file './GraphicsScene/exportDialogTemplate.ui'
# Form implementation generated from reading ui file './pyqtgraph/GraphicsScene/exportDialogTemplate.ui'
#
# Created: Wed Jan 30 21:02:28 2013
# by: PyQt4 UI code generator 4.9.3
# Created: Mon Dec 23 10:10:52 2013
# by: PyQt4 UI code generator 4.10
#
# WARNING! All changes made in this file will be lost!
@ -12,7 +12,16 @@ from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_Form(object):
def setupUi(self, Form):
@ -57,12 +66,12 @@ class Ui_Form(object):
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Export", None, QtGui.QApplication.UnicodeUTF8))
self.label.setText(QtGui.QApplication.translate("Form", "Item to export:", None, QtGui.QApplication.UnicodeUTF8))
self.label_2.setText(QtGui.QApplication.translate("Form", "Export format", None, QtGui.QApplication.UnicodeUTF8))
self.exportBtn.setText(QtGui.QApplication.translate("Form", "Export", None, QtGui.QApplication.UnicodeUTF8))
self.closeBtn.setText(QtGui.QApplication.translate("Form", "Close", None, QtGui.QApplication.UnicodeUTF8))
self.label_3.setText(QtGui.QApplication.translate("Form", "Export options", None, QtGui.QApplication.UnicodeUTF8))
self.copyBtn.setText(QtGui.QApplication.translate("Form", "Copy", None, QtGui.QApplication.UnicodeUTF8))
Form.setWindowTitle(_translate("Form", "Export", None))
self.label.setText(_translate("Form", "Item to export:", None))
self.label_2.setText(_translate("Form", "Export format", None))
self.exportBtn.setText(_translate("Form", "Export", None))
self.closeBtn.setText(_translate("Form", "Close", None))
self.label_3.setText(_translate("Form", "Export options", None))
self.copyBtn.setText(_translate("Form", "Copy", None))
from pyqtgraph.parametertree import ParameterTree
from ..parametertree import ParameterTree

View File

@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file './GraphicsScene/exportDialogTemplate.ui'
# Form implementation generated from reading ui file './pyqtgraph/GraphicsScene/exportDialogTemplate.ui'
#
# Created: Wed Jan 30 21:02:28 2013
# by: pyside-uic 0.2.13 running on PySide 1.1.1
# Created: Mon Dec 23 10:10:53 2013
# by: pyside-uic 0.2.14 running on PySide 1.1.2
#
# WARNING! All changes made in this file will be lost!
@ -60,4 +60,4 @@ class Ui_Form(object):
self.label_3.setText(QtGui.QApplication.translate("Form", "Export options", None, QtGui.QApplication.UnicodeUTF8))
self.copyBtn.setText(QtGui.QApplication.translate("Form", "Copy", None, QtGui.QApplication.UnicodeUTF8))
from pyqtgraph.parametertree import ParameterTree
from ..parametertree import ParameterTree

View File

@ -1,7 +1,7 @@
from pyqtgraph.Point import Point
from pyqtgraph.Qt import QtCore, QtGui
from ..Point import Point
from ..Qt import QtCore, QtGui
import weakref
import pyqtgraph.ptime as ptime
from .. import ptime as ptime
class MouseDragEvent(object):
"""

52
Qt.py
View File

@ -1,4 +1,14 @@
## Do all Qt imports from here to allow easier PyQt / PySide compatibility
"""
This module exists to smooth out some of the differences between PySide and PyQt4:
* Automatically import either PyQt4 or PySide depending on availability
* Allow to import QtCore/QtGui pyqtgraph.Qt without specifying which Qt wrapper
you want to use.
* Declare QtCore.Signal, .Slot in PyQt4
* Declare loadUiType function for Pyside
"""
import sys, re
## Automatically determine whether to use PyQt or PySide.
@ -23,8 +33,41 @@ if USE_PYSIDE:
from PySide import QtGui, QtCore, QtOpenGL, QtSvg
import PySide
VERSION_INFO = 'PySide ' + PySide.__version__
# Make a loadUiType function like PyQt has
# Credit:
# http://stackoverflow.com/questions/4442286/python-code-genration-with-pyside-uic/14195313#14195313
def loadUiType(uiFile):
"""
Pyside "loadUiType" command like PyQt4 has one, so we have to convert the ui file to py code in-memory first and then execute it in a special frame to retrieve the form_class.
"""
import pysideuic
import xml.etree.ElementTree as xml
from io import StringIO
parsed = xml.parse(uiFile)
widget_class = parsed.find('widget').get('class')
form_class = parsed.find('class').text
with open(uiFile, 'r') as f:
o = StringIO()
frame = {}
pysideuic.compileUi(f, o, indent=0)
pyc = compile(o.getvalue(), '<string>', 'exec')
exec(pyc, frame)
#Fetch the base_class and form class based on their type in the xml from designer
form_class = frame['Ui_%s'%form_class]
base_class = eval('QtGui.%s'%widget_class)
return form_class, base_class
else:
from PyQt4 import QtGui, QtCore
from PyQt4 import QtGui, QtCore, uic
try:
from PyQt4 import QtSvg
except ImportError:
@ -34,6 +77,9 @@ else:
except ImportError:
pass
loadUiType = uic.loadUiType
QtCore.Signal = QtCore.pyqtSignal
VERSION_INFO = 'PyQt4 ' + QtCore.PYQT_VERSION_STR + ' Qt ' + QtCore.QT_VERSION_STR
@ -43,6 +89,6 @@ versionReq = [4, 7]
QtVersion = PySide.QtCore.__version__ if USE_PYSIDE else QtCore.QT_VERSION_STR
m = re.match(r'(\d+)\.(\d+).*', QtVersion)
if m is not None and list(map(int, m.groups())) < versionReq:
print(map(int, m.groups()))
print(list(map(int, m.groups())))
raise Exception('pyqtgraph requires Qt version >= %d.%d (your version is %s)' % (versionReq[0], versionReq[1], QtVersion))

View File

@ -2,7 +2,6 @@
from .Qt import QtCore, QtGui
from .Point import Point
import numpy as np
import pyqtgraph as pg
class SRTTransform(QtGui.QTransform):
"""Transform that can always be represented as a combination of 3 matrices: scale * rotate * translate
@ -77,7 +76,7 @@ class SRTTransform(QtGui.QTransform):
self.update()
def setFromMatrix4x4(self, m):
m = pg.SRTTransform3D(m)
m = SRTTransform3D(m)
angle, axis = m.getRotation()
if angle != 0 and (axis[0] != 0 or axis[1] != 0 or axis[2] != 1):
print("angle: %s axis: %s" % (str(angle), str(axis)))
@ -256,4 +255,4 @@ if __name__ == '__main__':
w1.sigRegionChanged.connect(update)
#w2.sigRegionChanged.connect(update2)
from .SRTTransform3D import SRTTransform3D

View File

@ -1,17 +1,17 @@
# -*- coding: utf-8 -*-
from .Qt import QtCore, QtGui
from .Vector import Vector
from .SRTTransform import SRTTransform
import pyqtgraph as pg
from .Transform3D import Transform3D
from .Vector import Vector
import numpy as np
import scipy.linalg
class SRTTransform3D(pg.Transform3D):
class SRTTransform3D(Transform3D):
"""4x4 Transform matrix that can always be represented as a combination of 3 matrices: scale * rotate * translate
This transform has no shear; angles are always preserved.
"""
def __init__(self, init=None):
pg.Transform3D.__init__(self)
Transform3D.__init__(self)
self.reset()
if init is None:
return
@ -44,14 +44,14 @@ class SRTTransform3D(pg.Transform3D):
def getScale(self):
return pg.Vector(self._state['scale'])
return Vector(self._state['scale'])
def getRotation(self):
"""Return (angle, axis) of rotation"""
return self._state['angle'], pg.Vector(self._state['axis'])
return self._state['angle'], Vector(self._state['axis'])
def getTranslation(self):
return pg.Vector(self._state['pos'])
return Vector(self._state['pos'])
def reset(self):
self._state = {
@ -169,7 +169,7 @@ class SRTTransform3D(pg.Transform3D):
def as2D(self):
"""Return a QTransform representing the x,y portion of this transform (if possible)"""
return pg.SRTTransform(self)
return SRTTransform(self)
#def __div__(self, t):
#"""A / B == B^-1 * A"""
@ -202,11 +202,11 @@ class SRTTransform3D(pg.Transform3D):
self.update()
def update(self):
pg.Transform3D.setToIdentity(self)
Transform3D.setToIdentity(self)
## modifications to the transform are multiplied on the right, so we need to reverse order here.
pg.Transform3D.translate(self, *self._state['pos'])
pg.Transform3D.rotate(self, self._state['angle'], *self._state['axis'])
pg.Transform3D.scale(self, *self._state['scale'])
Transform3D.translate(self, *self._state['pos'])
Transform3D.rotate(self, self._state['angle'], *self._state['axis'])
Transform3D.scale(self, *self._state['scale'])
def __repr__(self):
return str(self.saveState())
@ -311,4 +311,4 @@ if __name__ == '__main__':
w1.sigRegionChanged.connect(update)
#w2.sigRegionChanged.connect(update2)
from .SRTTransform import SRTTransform

View File

@ -1,4 +1,4 @@
from pyqtgraph.Qt import QtCore, QtGui
from .Qt import QtCore, QtGui
class ThreadsafeTimer(QtCore.QObject):
"""

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
from .Qt import QtCore, QtGui
import pyqtgraph as pg
from . import functions as fn
import numpy as np
class Transform3D(QtGui.QMatrix4x4):
@ -26,7 +26,7 @@ class Transform3D(QtGui.QMatrix4x4):
Extends QMatrix4x4.map() to allow mapping (3, ...) arrays of coordinates
"""
if isinstance(obj, np.ndarray) and obj.ndim >= 2 and obj.shape[0] in (2,3):
return pg.transformCoordinates(self, obj)
return fn.transformCoordinates(self, obj)
else:
return QtGui.QMatrix4x4.map(self, obj)

View File

@ -4,7 +4,7 @@ PyQtGraph - Scientific Graphics and GUI Library for Python
www.pyqtgraph.org
"""
__version__ = None
__version__ = '0.9.8'
### import all the goodies and add some helper functions for easy CLI use
@ -130,56 +130,119 @@ if __version__ is None and not hasattr(sys, 'frozen') and sys.version_info[0] ==
## Import almost everything to make it available from a single namespace
## don't import the more complex systems--canvas, parametertree, flowchart, dockarea
## these must be imported separately.
from . import frozenSupport
def importModules(path, globals, locals, excludes=()):
"""Import all modules residing within *path*, return a dict of name: module pairs.
#from . import frozenSupport
#def importModules(path, globals, locals, excludes=()):
#"""Import all modules residing within *path*, return a dict of name: module pairs.
Note that *path* MUST be relative to the module doing the import.
"""
d = os.path.join(os.path.split(globals['__file__'])[0], path)
files = set()
for f in frozenSupport.listdir(d):
if frozenSupport.isdir(os.path.join(d, f)) and f not in ['__pycache__', 'tests']:
files.add(f)
elif f[-3:] == '.py' and f != '__init__.py':
files.add(f[:-3])
elif f[-4:] == '.pyc' and f != '__init__.pyc':
files.add(f[:-4])
#Note that *path* MUST be relative to the module doing the import.
#"""
#d = os.path.join(os.path.split(globals['__file__'])[0], path)
#files = set()
#for f in frozenSupport.listdir(d):
#if frozenSupport.isdir(os.path.join(d, f)) and f not in ['__pycache__', 'tests']:
#files.add(f)
#elif f[-3:] == '.py' and f != '__init__.py':
#files.add(f[:-3])
#elif f[-4:] == '.pyc' and f != '__init__.pyc':
#files.add(f[:-4])
mods = {}
path = path.replace(os.sep, '.')
for modName in files:
if modName in excludes:
continue
try:
if len(path) > 0:
modName = path + '.' + modName
#mod = __import__(modName, globals, locals, fromlist=['*'])
mod = __import__(modName, globals, locals, ['*'], 1)
mods[modName] = mod
except:
import traceback
traceback.print_stack()
sys.excepthook(*sys.exc_info())
print("[Error importing module: %s]" % modName)
#mods = {}
#path = path.replace(os.sep, '.')
#for modName in files:
#if modName in excludes:
#continue
#try:
#if len(path) > 0:
#modName = path + '.' + modName
#print( "from .%s import * " % modName)
#mod = __import__(modName, globals, locals, ['*'], 1)
#mods[modName] = mod
#except:
#import traceback
#traceback.print_stack()
#sys.excepthook(*sys.exc_info())
#print("[Error importing module: %s]" % modName)
return mods
#return mods
def importAll(path, globals, locals, excludes=()):
"""Given a list of modules, import all names from each module into the global namespace."""
mods = importModules(path, globals, locals, excludes)
for mod in mods.values():
if hasattr(mod, '__all__'):
names = mod.__all__
else:
names = [n for n in dir(mod) if n[0] != '_']
for k in names:
if hasattr(mod, k):
globals[k] = getattr(mod, k)
#def importAll(path, globals, locals, excludes=()):
#"""Given a list of modules, import all names from each module into the global namespace."""
#mods = importModules(path, globals, locals, excludes)
#for mod in mods.values():
#if hasattr(mod, '__all__'):
#names = mod.__all__
#else:
#names = [n for n in dir(mod) if n[0] != '_']
#for k in names:
#if hasattr(mod, k):
#globals[k] = getattr(mod, k)
importAll('graphicsItems', globals(), locals())
importAll('widgets', globals(), locals(),
excludes=['MatplotlibWidget', 'RawImageWidget', 'RemoteGraphicsView'])
# Dynamic imports are disabled. This causes too many problems.
#importAll('graphicsItems', globals(), locals())
#importAll('widgets', globals(), locals(),
#excludes=['MatplotlibWidget', 'RawImageWidget', 'RemoteGraphicsView'])
from .graphicsItems.VTickGroup import *
from .graphicsItems.GraphicsWidget import *
from .graphicsItems.ScaleBar import *
from .graphicsItems.PlotDataItem import *
from .graphicsItems.GraphItem import *
from .graphicsItems.TextItem import *
from .graphicsItems.GraphicsLayout import *
from .graphicsItems.UIGraphicsItem import *
from .graphicsItems.GraphicsObject import *
from .graphicsItems.PlotItem import *
from .graphicsItems.ROI import *
from .graphicsItems.InfiniteLine import *
from .graphicsItems.HistogramLUTItem import *
from .graphicsItems.GridItem import *
from .graphicsItems.GradientLegend import *
from .graphicsItems.GraphicsItem import *
from .graphicsItems.BarGraphItem import *
from .graphicsItems.ViewBox import *
from .graphicsItems.ArrowItem import *
from .graphicsItems.ImageItem import *
from .graphicsItems.AxisItem import *
from .graphicsItems.LabelItem import *
from .graphicsItems.CurvePoint import *
from .graphicsItems.GraphicsWidgetAnchor import *
from .graphicsItems.PlotCurveItem import *
from .graphicsItems.ButtonItem import *
from .graphicsItems.GradientEditorItem import *
from .graphicsItems.MultiPlotItem import *
from .graphicsItems.ErrorBarItem import *
from .graphicsItems.IsocurveItem import *
from .graphicsItems.LinearRegionItem import *
from .graphicsItems.FillBetweenItem import *
from .graphicsItems.LegendItem import *
from .graphicsItems.ScatterPlotItem import *
from .graphicsItems.ItemGroup import *
from .widgets.MultiPlotWidget import *
from .widgets.ScatterPlotWidget import *
from .widgets.ColorMapWidget import *
from .widgets.FileDialog import *
from .widgets.ValueLabel import *
from .widgets.HistogramLUTWidget import *
from .widgets.CheckTable import *
from .widgets.BusyCursor import *
from .widgets.PlotWidget import *
from .widgets.ComboBox import *
from .widgets.GradientWidget import *
from .widgets.DataFilterWidget import *
from .widgets.SpinBox import *
from .widgets.JoystickButton import *
from .widgets.GraphicsLayoutWidget import *
from .widgets.TreeWidget import *
from .widgets.PathButton import *
from .widgets.VerticalLabel import *
from .widgets.FeedbackButton import *
from .widgets.ColorButton import *
from .widgets.DataTreeWidget import *
from .widgets.GraphicsView import *
from .widgets.LayoutWidget import *
from .widgets.TableWidget import *
from .widgets.ProgressDialog import *
from .imageview import *
from .WidgetGroup import *
@ -194,6 +257,7 @@ from .SignalProxy import *
from .colormap import *
from .ptime import time
##############################################################
## PyQt and PySide both are prone to crashing on exit.
## There are two general approaches to dealing with this:
@ -292,6 +356,7 @@ def plot(*args, **kargs):
dataArgs[k] = kargs[k]
w = PlotWindow(**pwArgs)
if len(args) > 0 or len(dataArgs) > 0:
w.plot(*args, **dataArgs)
plots.append(w)
w.show()

View File

@ -3,29 +3,21 @@ if __name__ == '__main__':
import sys, os
md = os.path.dirname(os.path.abspath(__file__))
sys.path = [os.path.dirname(md), os.path.join(md, '..', '..', '..')] + sys.path
#print md
#from pyqtgraph.GraphicsView import GraphicsView
#import pyqtgraph.graphicsItems as graphicsItems
#from pyqtgraph.PlotWidget import PlotWidget
from pyqtgraph.Qt import QtGui, QtCore, USE_PYSIDE
from pyqtgraph.graphicsItems.ROI import ROI
from pyqtgraph.graphicsItems.ViewBox import ViewBox
from pyqtgraph.graphicsItems.GridItem import GridItem
from ..Qt import QtGui, QtCore, USE_PYSIDE
from ..graphicsItems.ROI import ROI
from ..graphicsItems.ViewBox import ViewBox
from ..graphicsItems.GridItem import GridItem
if USE_PYSIDE:
from .CanvasTemplate_pyside import *
else:
from .CanvasTemplate_pyqt import *
#import DataManager
import numpy as np
from pyqtgraph import debug
#import pyqtgraph as pg
from .. import debug
import weakref
from .CanvasManager import CanvasManager
#import items
from .CanvasItem import CanvasItem, GroupCanvasItem
class Canvas(QtGui.QWidget):

View File

@ -1,13 +1,13 @@
# -*- coding: utf-8 -*-
from pyqtgraph.Qt import QtGui, QtCore, QtSvg, USE_PYSIDE
from pyqtgraph.graphicsItems.ROI import ROI
import pyqtgraph as pg
from ..Qt import QtGui, QtCore, QtSvg, USE_PYSIDE
from ..graphicsItems.ROI import ROI
from .. import SRTTransform, ItemGroup
if USE_PYSIDE:
from . import TransformGuiTemplate_pyside as TransformGuiTemplate
else:
from . import TransformGuiTemplate_pyqt as TransformGuiTemplate
from pyqtgraph import debug
from .. import debug
class SelectBox(ROI):
def __init__(self, scalable=False, rotatable=True):
@ -96,7 +96,7 @@ class CanvasItem(QtCore.QObject):
if 'transform' in self.opts:
self.baseTransform = self.opts['transform']
else:
self.baseTransform = pg.SRTTransform()
self.baseTransform = SRTTransform()
if 'pos' in self.opts and self.opts['pos'] is not None:
self.baseTransform.translate(self.opts['pos'])
if 'angle' in self.opts and self.opts['angle'] is not None:
@ -124,8 +124,8 @@ class CanvasItem(QtCore.QObject):
self.itemScale = QtGui.QGraphicsScale()
self._graphicsItem.setTransformations([self.itemRotation, self.itemScale])
self.tempTransform = pg.SRTTransform() ## holds the additional transform that happens during a move - gets added to the userTransform when move is done.
self.userTransform = pg.SRTTransform() ## stores the total transform of the object
self.tempTransform = SRTTransform() ## holds the additional transform that happens during a move - gets added to the userTransform when move is done.
self.userTransform = SRTTransform() ## stores the total transform of the object
self.resetUserTransform()
## now happens inside resetUserTransform -> selectBoxToItem
@ -200,7 +200,7 @@ class CanvasItem(QtCore.QObject):
#flip = self.transformGui.mirrorImageCheck.isChecked()
#tr = self.userTransform.saveState()
inv = pg.SRTTransform()
inv = SRTTransform()
inv.scale(-1, 1)
self.userTransform = self.userTransform * inv
self.updateTransform()
@ -231,7 +231,7 @@ class CanvasItem(QtCore.QObject):
if not self.isMovable():
return
self.rotate(180.)
# inv = pg.SRTTransform()
# inv = SRTTransform()
# inv.scale(-1, -1)
# self.userTransform = self.userTransform * inv #flip lr/ud
# s=self.updateTransform()
@ -316,7 +316,7 @@ class CanvasItem(QtCore.QObject):
def resetTemporaryTransform(self):
self.tempTransform = pg.SRTTransform() ## don't use Transform.reset()--this transform might be used elsewhere.
self.tempTransform = SRTTransform() ## don't use Transform.reset()--this transform might be used elsewhere.
self.updateTransform()
def transform(self):
@ -368,7 +368,7 @@ class CanvasItem(QtCore.QObject):
try:
#self.userTranslate = pg.Point(tr['trans'])
#self.userRotate = tr['rot']
self.userTransform = pg.SRTTransform(tr)
self.userTransform = SRTTransform(tr)
self.updateTransform()
self.selectBoxFromUser() ## move select box to match
@ -377,7 +377,7 @@ class CanvasItem(QtCore.QObject):
except:
#self.userTranslate = pg.Point([0,0])
#self.userRotate = 0
self.userTransform = pg.SRTTransform()
self.userTransform = SRTTransform()
debug.printExc("Failed to load transform:")
#print "set transform", self, self.userTranslate
@ -504,6 +504,6 @@ class GroupCanvasItem(CanvasItem):
def __init__(self, **opts):
defOpts = {'movable': False, 'scalable': False}
defOpts.update(opts)
item = pg.ItemGroup()
item = ItemGroup()
CanvasItem.__init__(self, item, **defOpts)

View File

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
from pyqtgraph.Qt import QtCore, QtGui
from ..Qt import QtCore, QtGui
if not hasattr(QtCore, 'Signal'):
QtCore.Signal = QtCore.pyqtSignal
import weakref

View File

@ -131,12 +131,12 @@
<customwidget>
<class>TreeWidget</class>
<extends>QTreeWidget</extends>
<header>pyqtgraph.widgets.TreeWidget</header>
<header>..widgets.TreeWidget</header>
</customwidget>
<customwidget>
<class>GraphicsView</class>
<extends>QGraphicsView</extends>
<header>pyqtgraph.widgets.GraphicsView</header>
<header>..widgets.GraphicsView</header>
</customwidget>
<customwidget>
<class>CanvasCombo</class>

View File

@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file './canvas/CanvasTemplate.ui'
# Form implementation generated from reading ui file './pyqtgraph/canvas/CanvasTemplate.ui'
#
# Created: Sun Sep 9 14:41:30 2012
# by: PyQt4 UI code generator 4.9.1
# Created: Mon Dec 23 10:10:52 2013
# by: PyQt4 UI code generator 4.10
#
# WARNING! All changes made in this file will be lost!
@ -12,7 +12,16 @@ from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_Form(object):
def setupUi(self, Form):
@ -85,16 +94,16 @@ class Ui_Form(object):
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
self.storeSvgBtn.setText(QtGui.QApplication.translate("Form", "Store SVG", None, QtGui.QApplication.UnicodeUTF8))
self.storePngBtn.setText(QtGui.QApplication.translate("Form", "Store PNG", None, QtGui.QApplication.UnicodeUTF8))
self.autoRangeBtn.setText(QtGui.QApplication.translate("Form", "Auto Range", None, QtGui.QApplication.UnicodeUTF8))
self.redirectCheck.setToolTip(QtGui.QApplication.translate("Form", "Check to display all local items in a remote canvas.", None, QtGui.QApplication.UnicodeUTF8))
self.redirectCheck.setText(QtGui.QApplication.translate("Form", "Redirect", None, QtGui.QApplication.UnicodeUTF8))
self.resetTransformsBtn.setText(QtGui.QApplication.translate("Form", "Reset Transforms", None, QtGui.QApplication.UnicodeUTF8))
self.mirrorSelectionBtn.setText(QtGui.QApplication.translate("Form", "Mirror Selection", None, QtGui.QApplication.UnicodeUTF8))
self.reflectSelectionBtn.setText(QtGui.QApplication.translate("Form", "MirrorXY", None, QtGui.QApplication.UnicodeUTF8))
Form.setWindowTitle(_translate("Form", "Form", None))
self.storeSvgBtn.setText(_translate("Form", "Store SVG", None))
self.storePngBtn.setText(_translate("Form", "Store PNG", None))
self.autoRangeBtn.setText(_translate("Form", "Auto Range", None))
self.redirectCheck.setToolTip(_translate("Form", "Check to display all local items in a remote canvas.", None))
self.redirectCheck.setText(_translate("Form", "Redirect", None))
self.resetTransformsBtn.setText(_translate("Form", "Reset Transforms", None))
self.mirrorSelectionBtn.setText(_translate("Form", "Mirror Selection", None))
self.reflectSelectionBtn.setText(_translate("Form", "MirrorXY", None))
from pyqtgraph.widgets.GraphicsView import GraphicsView
from ..widgets.TreeWidget import TreeWidget
from CanvasManager import CanvasCombo
from pyqtgraph.widgets.TreeWidget import TreeWidget
from ..widgets.GraphicsView import GraphicsView

View File

@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file './canvas/CanvasTemplate.ui'
# Form implementation generated from reading ui file './pyqtgraph/canvas/CanvasTemplate.ui'
#
# Created: Sun Sep 9 14:41:30 2012
# by: pyside-uic 0.2.13 running on PySide 1.1.0
# Created: Mon Dec 23 10:10:52 2013
# by: pyside-uic 0.2.14 running on PySide 1.1.2
#
# WARNING! All changes made in this file will be lost!
@ -90,6 +90,6 @@ class Ui_Form(object):
self.mirrorSelectionBtn.setText(QtGui.QApplication.translate("Form", "Mirror Selection", None, QtGui.QApplication.UnicodeUTF8))
self.reflectSelectionBtn.setText(QtGui.QApplication.translate("Form", "MirrorXY", None, QtGui.QApplication.UnicodeUTF8))
from pyqtgraph.widgets.GraphicsView import GraphicsView
from ..widgets.TreeWidget import TreeWidget
from CanvasManager import CanvasCombo
from pyqtgraph.widgets.TreeWidget import TreeWidget
from ..widgets.GraphicsView import GraphicsView

View File

@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file './canvas/TransformGuiTemplate.ui'
# Form implementation generated from reading ui file './pyqtgraph/canvas/TransformGuiTemplate.ui'
#
# Created: Sun Sep 9 14:41:30 2012
# by: PyQt4 UI code generator 4.9.1
# Created: Mon Dec 23 10:10:52 2013
# by: PyQt4 UI code generator 4.10
#
# WARNING! All changes made in this file will be lost!
@ -12,7 +12,16 @@ from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_Form(object):
def setupUi(self, Form):
@ -51,10 +60,10 @@ class Ui_Form(object):
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
self.translateLabel.setText(QtGui.QApplication.translate("Form", "Translate:", None, QtGui.QApplication.UnicodeUTF8))
self.rotateLabel.setText(QtGui.QApplication.translate("Form", "Rotate:", None, QtGui.QApplication.UnicodeUTF8))
self.scaleLabel.setText(QtGui.QApplication.translate("Form", "Scale:", None, QtGui.QApplication.UnicodeUTF8))
self.mirrorImageBtn.setText(QtGui.QApplication.translate("Form", "Mirror", None, QtGui.QApplication.UnicodeUTF8))
self.reflectImageBtn.setText(QtGui.QApplication.translate("Form", "Reflect", None, QtGui.QApplication.UnicodeUTF8))
Form.setWindowTitle(_translate("Form", "Form", None))
self.translateLabel.setText(_translate("Form", "Translate:", None))
self.rotateLabel.setText(_translate("Form", "Rotate:", None))
self.scaleLabel.setText(_translate("Form", "Scale:", None))
self.mirrorImageBtn.setText(_translate("Form", "Mirror", None))
self.reflectImageBtn.setText(_translate("Form", "Reflect", None))

View File

@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file './canvas/TransformGuiTemplate.ui'
# Form implementation generated from reading ui file './pyqtgraph/canvas/TransformGuiTemplate.ui'
#
# Created: Sun Sep 9 14:41:30 2012
# by: pyside-uic 0.2.13 running on PySide 1.1.0
# Created: Mon Dec 23 10:10:52 2013
# by: pyside-uic 0.2.14 running on PySide 1.1.2
#
# WARNING! All changes made in this file will be lost!

View File

@ -1,6 +1,6 @@
import numpy as np
import scipy.interpolate
from pyqtgraph.Qt import QtGui, QtCore
from .Qt import QtGui, QtCore
class ColorMap(object):
"""

View File

@ -1,5 +1,5 @@
from pyqtgraph.Qt import QtCore, QtGui
from pyqtgraph.python2_3 import asUnicode
from ..Qt import QtCore, QtGui
from ..python2_3 import asUnicode
class CmdInput(QtGui.QLineEdit):

View File

@ -1,14 +1,14 @@
from pyqtgraph.Qt import QtCore, QtGui, USE_PYSIDE
from ..Qt import QtCore, QtGui, USE_PYSIDE
import sys, re, os, time, traceback, subprocess
import pyqtgraph as pg
if USE_PYSIDE:
from . import template_pyside as template
else:
from . import template_pyqt as template
import pyqtgraph.exceptionHandling as exceptionHandling
from .. import exceptionHandling as exceptionHandling
import pickle
from .. import getConfigOption
class ConsoleWidget(QtGui.QWidget):
"""
@ -281,7 +281,7 @@ class ConsoleWidget(QtGui.QWidget):
def stackItemDblClicked(self, item):
editor = self.editor
if editor is None:
editor = pg.getConfigOption('editorCommand')
editor = getConfigOption('editorCommand')
if editor is None:
return
tb = self.currentFrame()

View File

@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file './console/template.ui'
# Form implementation generated from reading ui file './pyqtgraph/console/template.ui'
#
# Created: Sun Sep 9 14:41:30 2012
# by: PyQt4 UI code generator 4.9.1
# Created: Mon Dec 23 10:10:53 2013
# by: PyQt4 UI code generator 4.10
#
# WARNING! All changes made in this file will be lost!
@ -12,7 +12,16 @@ from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_Form(object):
def setupUi(self, Form):
@ -97,15 +106,15 @@ class Ui_Form(object):
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Console", None, QtGui.QApplication.UnicodeUTF8))
self.historyBtn.setText(QtGui.QApplication.translate("Form", "History..", None, QtGui.QApplication.UnicodeUTF8))
self.exceptionBtn.setText(QtGui.QApplication.translate("Form", "Exceptions..", None, QtGui.QApplication.UnicodeUTF8))
self.exceptionGroup.setTitle(QtGui.QApplication.translate("Form", "Exception Handling", None, QtGui.QApplication.UnicodeUTF8))
self.catchAllExceptionsBtn.setText(QtGui.QApplication.translate("Form", "Show All Exceptions", None, QtGui.QApplication.UnicodeUTF8))
self.catchNextExceptionBtn.setText(QtGui.QApplication.translate("Form", "Show Next Exception", None, QtGui.QApplication.UnicodeUTF8))
self.onlyUncaughtCheck.setText(QtGui.QApplication.translate("Form", "Only Uncaught Exceptions", None, QtGui.QApplication.UnicodeUTF8))
self.runSelectedFrameCheck.setText(QtGui.QApplication.translate("Form", "Run commands in selected stack frame", None, QtGui.QApplication.UnicodeUTF8))
self.exceptionInfoLabel.setText(QtGui.QApplication.translate("Form", "Exception Info", None, QtGui.QApplication.UnicodeUTF8))
self.clearExceptionBtn.setText(QtGui.QApplication.translate("Form", "Clear Exception", None, QtGui.QApplication.UnicodeUTF8))
Form.setWindowTitle(_translate("Form", "Console", None))
self.historyBtn.setText(_translate("Form", "History..", None))
self.exceptionBtn.setText(_translate("Form", "Exceptions..", None))
self.exceptionGroup.setTitle(_translate("Form", "Exception Handling", None))
self.catchAllExceptionsBtn.setText(_translate("Form", "Show All Exceptions", None))
self.catchNextExceptionBtn.setText(_translate("Form", "Show Next Exception", None))
self.onlyUncaughtCheck.setText(_translate("Form", "Only Uncaught Exceptions", None))
self.runSelectedFrameCheck.setText(_translate("Form", "Run commands in selected stack frame", None))
self.exceptionInfoLabel.setText(_translate("Form", "Exception Info", None))
self.clearExceptionBtn.setText(_translate("Form", "Clear Exception", None))
from .CmdInput import CmdInput

View File

@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file './console/template.ui'
# Form implementation generated from reading ui file './pyqtgraph/console/template.ui'
#
# Created: Sun Sep 9 14:41:30 2012
# by: pyside-uic 0.2.13 running on PySide 1.1.0
# Created: Mon Dec 23 10:10:53 2013
# by: pyside-uic 0.2.14 running on PySide 1.1.2
#
# WARNING! All changes made in this file will be lost!

163
debug.py
View File

@ -5,6 +5,8 @@ Copyright 2010 Luke Campagnola
Distributed under MIT/X11 license. See license.txt for more infomation.
"""
from __future__ import print_function
import sys, traceback, time, gc, re, types, weakref, inspect, os, cProfile
from . import ptime
from numpy import ndarray
@ -365,82 +367,125 @@ class GarbageWatcher(object):
return self.objs[item]
class Profiler:
class Profiler(object):
"""Simple profiler allowing measurement of multiple time intervals.
Arguments:
msg: message to print at start and finish of profiling
disabled: If true, profiler does nothing (so you can leave it in place)
delayed: If true, all messages are printed after call to finish()
(this can result in more accurate time step measurements)
globalDelay: if True, all nested profilers delay printing until the top level finishes
By default, profilers are disabled. To enable profiling, set the
environment variable `PYQTGRAPHPROFILE` to a comma-separated list of
fully-qualified names of profiled functions.
Calling a profiler registers a message (defaulting to an increasing
counter) that contains the time elapsed since the last call. When the
profiler is about to be garbage-collected, the messages are passed to the
outer profiler if one is running, or printed to stdout otherwise.
If `delayed` is set to False, messages are immediately printed instead.
Example:
prof = Profiler('Function')
def function(...):
profiler = Profiler()
... do stuff ...
prof.mark('did stuff')
profiler('did stuff')
... do other stuff ...
prof.mark('did other stuff')
prof.finish()
profiler('did other stuff')
# profiler is garbage-collected and flushed at function end
If this function is a method of class C, setting `PYQTGRAPHPROFILE` to
"C.function" (without the module name) will enable this profiler.
For regular functions, use the qualified name of the function, stripping
only the initial "pyqtgraph." prefix from the module.
"""
depth = 0
msgs = []
def __init__(self, msg="Profiler", disabled=False, delayed=True, globalDelay=True):
self.disabled = disabled
if disabled:
return
_profilers = os.environ.get("PYQTGRAPHPROFILE", "")
_depth = 0
_msgs = []
self.markCount = 0
self.finished = False
self.depth = Profiler.depth
Profiler.depth += 1
if not globalDelay:
self.msgs = []
self.delayed = delayed
self.msg = " "*self.depth + msg
msg2 = self.msg + " >>> Started"
if self.delayed:
self.msgs.append(msg2)
class DisabledProfiler(object):
def __init__(self, *args, **kwds):
pass
def __call__(self, *args):
pass
def finish(self):
pass
def mark(self, msg=None):
pass
_disabledProfiler = DisabledProfiler()
if _profilers:
_profilers = _profilers.split(",")
def __new__(cls, msg=None, disabled='env', delayed=True):
"""Optionally create a new profiler based on caller's qualname.
"""
if disabled is True:
return cls._disabledProfiler
# determine the qualified name of the caller function
caller_frame = sys._getframe(1)
try:
caller_object_type = type(caller_frame.f_locals["self"])
except KeyError: # we are in a regular function
qualifier = caller_frame.f_globals["__name__"].split(".", 1)[1]
else: # we are in a method
qualifier = caller_object_type.__name__
func_qualname = qualifier + "." + caller_frame.f_code.co_name
if func_qualname not in cls._profilers: # don't do anything
return cls._disabledProfiler
# create an actual profiling object
cls._depth += 1
obj = super(Profiler, cls).__new__(cls)
obj._name = msg or func_qualname
obj._delayed = delayed
obj._markCount = 0
obj._finished = False
obj._firstTime = obj._lastTime = ptime.time()
obj._newMsg("> Entering " + obj._name)
return obj
else:
print(msg2)
self.t0 = ptime.time()
self.t1 = self.t0
def __new__(cls, delayed=True):
return lambda msg=None: None
def __call__(self, msg=None):
"""Register or print a new message with timing information.
"""
if msg is None:
msg = str(self._markCount)
self._markCount += 1
newTime = ptime.time()
self._newMsg(" %s: %0.4f ms",
msg, (newTime - self._lastTime) * 1000)
self._lastTime = newTime
def mark(self, msg=None):
if self.disabled:
return
self(msg)
if msg is None:
msg = str(self.markCount)
self.markCount += 1
t1 = ptime.time()
msg2 = " "+self.msg+" "+msg+" "+"%gms" % ((t1-self.t1)*1000)
if self.delayed:
self.msgs.append(msg2)
def _newMsg(self, msg, *args):
msg = " " * (self._depth - 1) + msg
if self._delayed:
self._msgs.append((msg, args))
else:
print(msg2)
self.t1 = ptime.time() ## don't measure time it took to print
print(msg % args)
def __del__(self):
self.finish()
def finish(self, msg=None):
if self.disabled or self.finished:
"""Add a final message; flush the message list if no parent profiler.
"""
if self._finished:
return
self._finished = True
if msg is not None:
self.mark(msg)
t1 = ptime.time()
msg = self.msg + ' <<< Finished, total time: %gms' % ((t1-self.t0)*1000)
if self.delayed:
self.msgs.append(msg)
if self.depth == 0:
for line in self.msgs:
print(line)
Profiler.msgs = []
else:
print(msg)
Profiler.depth = self.depth
self.finished = True
self(msg)
self._newMsg("< Exiting %s, total time: %0.4f ms",
self._name, (ptime.time() - self._firstTime) * 1000)
type(self)._depth -= 1
if self._depth < 1 and self._msgs:
print("\n".join([m[0]%m[1] for m in self._msgs]))
type(self)._msgs = []

View File

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
from pyqtgraph.Qt import QtCore, QtGui
from ..Qt import QtCore, QtGui
import weakref
class Container(object):
@ -241,6 +241,13 @@ class TContainer(Container, QtGui.QWidget):
else:
w.label.setDim(True)
def raiseDock(self, dock):
"""Move *dock* to the top of the stack"""
self.stack.currentWidget().label.setDim(True)
self.stack.setCurrentWidget(dock)
dock.label.setDim(False)
def type(self):
return 'tab'

View File

@ -1,7 +1,7 @@
from pyqtgraph.Qt import QtCore, QtGui
from ..Qt import QtCore, QtGui
from .DockDrop import *
from pyqtgraph.widgets.VerticalLabel import VerticalLabel
from ..widgets.VerticalLabel import VerticalLabel
class Dock(QtGui.QWidget, DockDrop):
@ -209,6 +209,11 @@ class Dock(QtGui.QWidget, DockDrop):
self.setOrientation(force=True)
def raiseDock(self):
"""If this Dock is stacked underneath others, raise it to the top."""
self.container().raiseDock(self)
def close(self):
"""Remove this dock from the DockArea it lives inside."""
self.setParent(None)

View File

@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
from pyqtgraph.Qt import QtCore, QtGui
from ..Qt import QtCore, QtGui
from .Container import *
from .DockDrop import *
from .Dock import Dock
import pyqtgraph.debug as debug
from .. import debug as debug
import weakref
## TODO:

View File

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
from pyqtgraph.Qt import QtCore, QtGui
from ..Qt import QtCore, QtGui
class DockDrop(object):
"""Provides dock-dropping methods"""

View File

@ -1,8 +1,7 @@
import pyqtgraph as pg
from pyqtgraph.Qt import QtGui, QtCore
from ..Qt import QtGui, QtCore
from .Exporter import Exporter
from pyqtgraph.parametertree import Parameter
from ..parametertree import Parameter
from .. import PlotItem
__all__ = ['CSVExporter']
@ -22,7 +21,7 @@ class CSVExporter(Exporter):
def export(self, fileName=None):
if not isinstance(self.item, pg.PlotItem):
if not isinstance(self.item, PlotItem):
raise Exception("Must have a PlotItem selected for CSV export.")
if fileName is None:
@ -33,8 +32,14 @@ class CSVExporter(Exporter):
data = []
header = []
for c in self.item.curves:
data.append(c.getData())
header.extend(['x', 'y'])
cd = c.getData()
if cd[0] is None:
continue
data.append(cd)
name = ''
if hasattr(c, 'implements') and c.implements('plotData') and c.name() is not None:
name = c.name().replace('"', '""') + '_'
header.extend(['"'+name+'x"', '"'+name+'y"'])
if self.params['separator'] == 'comma':
sep = ','
@ -44,7 +49,7 @@ class CSVExporter(Exporter):
fd.write(sep.join(header) + '\n')
i = 0
numFormat = '%%0.%dg' % self.params['precision']
numRows = reduce(max, [len(d[0]) for d in data])
numRows = max([len(d[0]) for d in data])
for i in range(numRows):
for d in data:
if i < len(d[0]):
@ -54,6 +59,6 @@ class CSVExporter(Exporter):
fd.write('\n')
fd.close()
CSVExporter.register()

View File

@ -1,7 +1,7 @@
from pyqtgraph.widgets.FileDialog import FileDialog
import pyqtgraph as pg
from pyqtgraph.Qt import QtGui, QtCore, QtSvg
from pyqtgraph.python2_3 import asUnicode
from ..widgets.FileDialog import FileDialog
from ..Qt import QtGui, QtCore, QtSvg
from ..python2_3 import asUnicode
from ..GraphicsScene import GraphicsScene
import os, re
LastExportDirectory = None
@ -11,6 +11,14 @@ class Exporter(object):
Abstract class used for exporting graphics to file / printer / whatever.
"""
allowCopy = False # subclasses set this to True if they can use the copy buffer
Exporters = []
@classmethod
def register(cls):
"""
Used to register Exporter classes to appear in the export dialog.
"""
Exporter.Exporters.append(cls)
def __init__(self, item):
"""
@ -20,9 +28,6 @@ class Exporter(object):
object.__init__(self)
self.item = item
#def item(self):
#return self.item
def parameters(self):
"""Return the parameters used to configure this exporter."""
raise Exception("Abstract method must be overridden in subclass.")
@ -72,20 +77,20 @@ class Exporter(object):
self.export(fileName=fileName, **self.fileDialog.opts)
def getScene(self):
if isinstance(self.item, pg.GraphicsScene):
if isinstance(self.item, GraphicsScene):
return self.item
else:
return self.item.scene()
def getSourceRect(self):
if isinstance(self.item, pg.GraphicsScene):
if isinstance(self.item, GraphicsScene):
w = self.item.getViewWidget()
return w.viewportTransform().inverted()[0].mapRect(w.rect())
else:
return self.item.sceneBoundingRect()
def getTargetRect(self):
if isinstance(self.item, pg.GraphicsScene):
if isinstance(self.item, GraphicsScene):
return self.item.getViewWidget().rect()
else:
return self.item.mapRectToDevice(self.item.boundingRect())
@ -131,45 +136,4 @@ class Exporter(object):
return preItems + rootItem + postItems
def render(self, painter, targetRect, sourceRect, item=None):
#if item is None:
#item = self.item
#preItems = []
#postItems = []
#if isinstance(item, QtGui.QGraphicsScene):
#childs = [i for i in item.items() if i.parentItem() is None]
#rootItem = []
#else:
#childs = item.childItems()
#rootItem = [item]
#childs.sort(lambda a,b: cmp(a.zValue(), b.zValue()))
#while len(childs) > 0:
#ch = childs.pop(0)
#if int(ch.flags() & ch.ItemStacksBehindParent) > 0 or (ch.zValue() < 0 and int(ch.flags() & ch.ItemNegativeZStacksBehindParent) > 0):
#preItems.extend(tree)
#else:
#postItems.extend(tree)
#for ch in preItems:
#self.render(painter, sourceRect, targetRect, item=ch)
### paint root here
#for ch in postItems:
#self.render(painter, sourceRect, targetRect, item=ch)
self.getScene().render(painter, QtCore.QRectF(targetRect), QtCore.QRectF(sourceRect))
#def writePs(self, fileName=None, item=None):
#if fileName is None:
#self.fileSaveDialog(self.writeSvg, filter="PostScript (*.ps)")
#return
#if item is None:
#item = self
#printer = QtGui.QPrinter(QtGui.QPrinter.HighResolution)
#printer.setOutputFileName(fileName)
#painter = QtGui.QPainter(printer)
#self.render(painter)
#painter.end()
#def writeToPrinter(self):
#pass

View File

@ -1,7 +1,7 @@
from .Exporter import Exporter
from pyqtgraph.parametertree import Parameter
from pyqtgraph.Qt import QtGui, QtCore, QtSvg, USE_PYSIDE
import pyqtgraph as pg
from ..parametertree import Parameter
from ..Qt import QtGui, QtCore, QtSvg, USE_PYSIDE\
from .. import functions as fn
import numpy as np
__all__ = ['ImageExporter']
@ -73,7 +73,7 @@ class ImageExporter(Exporter):
bg[:,:,1] = color.green()
bg[:,:,2] = color.red()
bg[:,:,3] = color.alpha()
self.png = pg.makeQImage(bg, alpha=True)
self.png = fn.makeQImage(bg, alpha=True)
## set resolution of image:
origTargetRect = self.getTargetRect()
@ -98,4 +98,5 @@ class ImageExporter(Exporter):
else:
self.png.save(fileName)
ImageExporter.register()

View File

@ -1,7 +1,7 @@
import pyqtgraph as pg
from pyqtgraph.Qt import QtGui, QtCore
from ..Qt import QtGui, QtCore
from .Exporter import Exporter
from .. import PlotItem
from .. import functions as fn
__all__ = ['MatplotlibExporter']
@ -17,7 +17,7 @@ class MatplotlibExporter(Exporter):
def export(self, fileName=None):
if isinstance(self.item, pg.PlotItem):
if isinstance(self.item, PlotItem):
mpw = MatplotlibWindow()
MatplotlibExporter.windows.append(mpw)
fig = mpw.getFigure()
@ -29,23 +29,23 @@ class MatplotlibExporter(Exporter):
for item in self.item.curves:
x, y = item.getData()
opts = item.opts
pen = pg.mkPen(opts['pen'])
pen = fn.mkPen(opts['pen'])
if pen.style() == QtCore.Qt.NoPen:
linestyle = ''
else:
linestyle = '-'
color = tuple([c/255. for c in pg.colorTuple(pen.color())])
color = tuple([c/255. for c in fn.colorTuple(pen.color())])
symbol = opts['symbol']
if symbol == 't':
symbol = '^'
symbolPen = pg.mkPen(opts['symbolPen'])
symbolBrush = pg.mkBrush(opts['symbolBrush'])
markeredgecolor = tuple([c/255. for c in pg.colorTuple(symbolPen.color())])
markerfacecolor = tuple([c/255. for c in pg.colorTuple(symbolBrush.color())])
symbolPen = fn.mkPen(opts['symbolPen'])
symbolBrush = fn.mkBrush(opts['symbolBrush'])
markeredgecolor = tuple([c/255. for c in fn.colorTuple(symbolPen.color())])
markerfacecolor = tuple([c/255. for c in fn.colorTuple(symbolBrush.color())])
if opts['fillLevel'] is not None and opts['fillBrush'] is not None:
fillBrush = pg.mkBrush(opts['fillBrush'])
fillcolor = tuple([c/255. for c in pg.colorTuple(fillBrush.color())])
fillBrush = fn.mkBrush(opts['fillBrush'])
fillcolor = tuple([c/255. for c in fn.colorTuple(fillBrush.color())])
ax.fill_between(x=x, y1=y, y2=opts['fillLevel'], facecolor=fillcolor)
ax.plot(x, y, marker=symbol, color=color, linewidth=pen.width(), linestyle=linestyle, markeredgecolor=markeredgecolor, markerfacecolor=markerfacecolor)
@ -57,11 +57,12 @@ class MatplotlibExporter(Exporter):
else:
raise Exception("Matplotlib export currently only works with plot items")
MatplotlibExporter.register()
class MatplotlibWindow(QtGui.QMainWindow):
def __init__(self):
import pyqtgraph.widgets.MatplotlibWidget
from .. import widgets.MatplotlibWidget
QtGui.QMainWindow.__init__(self)
self.mpl = pyqtgraph.widgets.MatplotlibWidget.MatplotlibWidget()
self.setCentralWidget(self.mpl)
@ -72,3 +73,5 @@ class MatplotlibWindow(QtGui.QMainWindow):
def closeEvent(self, ev):
MatplotlibExporter.windows.remove(self)

View File

@ -1,6 +1,6 @@
from .Exporter import Exporter
from pyqtgraph.parametertree import Parameter
from pyqtgraph.Qt import QtGui, QtCore, QtSvg
from ..parametertree import Parameter
from ..Qt import QtGui, QtCore, QtSvg
import re
__all__ = ['PrintExporter']
@ -63,3 +63,6 @@ class PrintExporter(Exporter):
finally:
self.setExportMode(False)
painter.end()
#PrintExporter.register()

View File

@ -1,8 +1,9 @@
from .Exporter import Exporter
from pyqtgraph.python2_3 import asUnicode
from pyqtgraph.parametertree import Parameter
from pyqtgraph.Qt import QtGui, QtCore, QtSvg
import pyqtgraph as pg
from ..python2_3 import asUnicode
from ..parametertree import Parameter
from ..Qt import QtGui, QtCore, QtSvg
from .. import debug
from .. import functions as fn
import re
import xml.dom.minidom as xml
import numpy as np
@ -156,7 +157,7 @@ def _generateItemSvg(item, nodes=None, root=None):
##
## Both 2 and 3 can be addressed by drawing all items in world coordinates.
prof = pg.debug.Profiler('generateItemSvg %s' % str(item), disabled=True)
profiler = debug.Profiler()
if nodes is None: ## nodes maps all node IDs to their XML element.
## this allows us to ensure all elements receive unique names.
@ -196,17 +197,12 @@ def _generateItemSvg(item, nodes=None, root=None):
tr2 = QtGui.QTransform()
tr2.translate(-rootPos.x(), -rootPos.y())
tr = tr * tr2
#print item, pg.SRTTransform(tr)
#tr.translate(item.pos().x(), item.pos().y())
#tr = tr * item.transform()
arr = QtCore.QByteArray()
buf = QtCore.QBuffer(arr)
svg = QtSvg.QSvgGenerator()
svg.setOutputDevice(buf)
dpi = QtGui.QDesktopWidget().physicalDpiX()
### not really sure why this works, but it seems to be important:
#self.svg.setSize(QtCore.QSize(self.params['width']*dpi/90., self.params['height']*dpi/90.))
svg.setResolution(dpi)
p = QtGui.QPainter()
@ -235,12 +231,12 @@ def _generateItemSvg(item, nodes=None, root=None):
print(doc.toxml())
raise
prof.mark('render')
profiler('render')
## Get rid of group transformation matrices by applying
## transformation to inner coordinates
correctCoordinates(g1, item)
prof.mark('correct')
profiler('correct')
## make sure g1 has the transformation matrix
#m = (tr.m11(), tr.m12(), tr.m21(), tr.m22(), tr.m31(), tr.m32())
#g1.setAttribute('transform', "matrix(%f,%f,%f,%f,%f,%f)" % m)
@ -290,7 +286,7 @@ def _generateItemSvg(item, nodes=None, root=None):
childGroup = g1.ownerDocument.createElement('g')
childGroup.setAttribute('clip-path', 'url(#%s)' % clip)
g1.appendChild(childGroup)
prof.mark('clipping')
profiler('clipping')
## Add all child items as sub-elements.
childs.sort(key=lambda c: c.zValue())
@ -299,8 +295,7 @@ def _generateItemSvg(item, nodes=None, root=None):
if cg is None:
continue
childGroup.appendChild(cg) ### this isn't quite right--some items draw below their parent (good enough for now)
prof.mark('children')
prof.finish()
profiler('children')
return g1
def correctCoordinates(node, item):
@ -351,7 +346,7 @@ def correctCoordinates(node, item):
if ch.tagName == 'polyline':
removeTransform = True
coords = np.array([[float(a) for a in c.split(',')] for c in ch.getAttribute('points').strip().split(' ')])
coords = pg.transformCoordinates(tr, coords, transpose=True)
coords = fn.transformCoordinates(tr, coords, transpose=True)
ch.setAttribute('points', ' '.join([','.join([str(a) for a in c]) for c in coords]))
elif ch.tagName == 'path':
removeTransform = True
@ -366,7 +361,7 @@ def correctCoordinates(node, item):
x = x[1:]
else:
t = ''
nc = pg.transformCoordinates(tr, np.array([[float(x),float(y)]]), transpose=True)
nc = fn.transformCoordinates(tr, np.array([[float(x),float(y)]]), transpose=True)
newCoords += t+str(nc[0,0])+','+str(nc[0,1])+' '
ch.setAttribute('d', newCoords)
elif ch.tagName == 'text':
@ -376,7 +371,7 @@ def correctCoordinates(node, item):
#[float(ch.getAttribute('x')), float(ch.getAttribute('y'))],
#[float(ch.getAttribute('font-size')), 0],
#[0,0]])
#c = pg.transformCoordinates(tr, c, transpose=True)
#c = fn.transformCoordinates(tr, c, transpose=True)
#ch.setAttribute('x', str(c[0,0]))
#ch.setAttribute('y', str(c[0,1]))
#fs = c[1]-c[2]
@ -398,13 +393,17 @@ def correctCoordinates(node, item):
## correct line widths if needed
if removeTransform and ch.getAttribute('vector-effect') != 'non-scaling-stroke':
w = float(grp.getAttribute('stroke-width'))
s = pg.transformCoordinates(tr, np.array([[w,0], [0,0]]), transpose=True)
s = fn.transformCoordinates(tr, np.array([[w,0], [0,0]]), transpose=True)
w = ((s[0]-s[1])**2).sum()**0.5
ch.setAttribute('stroke-width', str(w))
if removeTransform:
grp.removeAttribute('transform')
SVGExporter.register()
def itemTransform(item, root):
## Return the transformation mapping item to root
## (actually to parent coordinate system of root)
@ -440,36 +439,10 @@ def itemTransform(item, root):
tr = item.sceneTransform()
else:
tr = itemTransform(nextRoot, root) * item.itemTransform(nextRoot)[0]
#pos = QtGui.QTransform()
#pos.translate(root.pos().x(), root.pos().y())
#tr = pos * root.transform() * item.itemTransform(root)[0]
return tr
#def correctStroke(node, item, root, width=1):
##print "==============", item, node
#if node.hasAttribute('stroke-width'):
#width = float(node.getAttribute('stroke-width'))
#if node.getAttribute('vector-effect') == 'non-scaling-stroke':
#node.removeAttribute('vector-effect')
#if isinstance(root, QtGui.QGraphicsScene):
#w = item.mapFromScene(pg.Point(width,0))
#o = item.mapFromScene(pg.Point(0,0))
#else:
#w = item.mapFromItem(root, pg.Point(width,0))
#o = item.mapFromItem(root, pg.Point(0,0))
#w = w-o
##print " ", w, o, w-o
#w = (w.x()**2 + w.y()**2) ** 0.5
##print " ", w
#node.setAttribute('stroke-width', str(w))
#for ch in node.childNodes:
#if isinstance(ch, xml.Element):
#correctStroke(ch, item, root, width)
def cleanXml(node):
## remove extraneous text; let the xml library do the formatting.
hasElement = False

View File

@ -1,27 +1,11 @@
Exporters = []
from pyqtgraph import importModules
#from .. import frozenSupport
import os
d = os.path.split(__file__)[0]
#files = []
#for f in frozenSupport.listdir(d):
#if frozenSupport.isdir(os.path.join(d, f)) and f != '__pycache__':
#files.append(f)
#elif f[-3:] == '.py' and f not in ['__init__.py', 'Exporter.py']:
#files.append(f[:-3])
#for modName in files:
#mod = __import__(modName, globals(), locals(), fromlist=['*'])
for mod in importModules('', globals(), locals(), excludes=['Exporter']).values():
if hasattr(mod, '__all__'):
names = mod.__all__
else:
names = [n for n in dir(mod) if n[0] != '_']
for k in names:
if hasattr(mod, k):
Exporters.append(getattr(mod, k))
from .Exporter import Exporter
from .ImageExporter import *
from .SVGExporter import *
from .Matplotlib import *
from .CSVExporter import *
from .PrintExporter import *
def listExporters():
return Exporters[:]
return Exporter.Exporters[:]

View File

@ -1,8 +1,9 @@
# -*- coding: utf-8 -*-
from pyqtgraph.Qt import QtCore, QtGui, USE_PYSIDE
from ..Qt import QtCore, QtGui, USE_PYSIDE
from .Node import *
from pyqtgraph.pgcollections import OrderedDict
from pyqtgraph.widgets.TreeWidget import *
from ..pgcollections import OrderedDict
from ..widgets.TreeWidget import *
from .. import FileDialog, DataTreeWidget
## pyside and pyqt use incompatible ui files.
if USE_PYSIDE:
@ -14,11 +15,10 @@ else:
from .Terminal import Terminal
from numpy import ndarray
from . import library
from pyqtgraph.debug import printExc
import pyqtgraph.configfile as configfile
import pyqtgraph.dockarea as dockarea
import pyqtgraph as pg
from .library import LIBRARY
from ..debug import printExc
from .. import configfile as configfile
from .. import dockarea as dockarea
from . import FlowchartGraphicsView
def strDict(d):
@ -67,7 +67,8 @@ class Flowchart(Node):
sigChartLoaded = QtCore.Signal()
sigStateChanged = QtCore.Signal()
def __init__(self, terminals=None, name=None, filePath=None):
def __init__(self, terminals=None, name=None, filePath=None, library=None):
self.library = library or LIBRARY
if name is None:
name = "Flowchart"
if terminals is None:
@ -105,6 +106,10 @@ class Flowchart(Node):
for name, opts in terminals.items():
self.addTerminal(name, **opts)
def setLibrary(self, lib):
self.library = lib
self.widget().chartWidget.buildMenu()
def setInput(self, **args):
"""Set the input values of the flowchart. This will automatically propagate
the new values throughout the flowchart, (possibly) causing the output to change.
@ -194,7 +199,7 @@ class Flowchart(Node):
break
n += 1
node = library.getNodeType(nodeType)(name)
node = self.library.getNodeType(nodeType)(name)
self.addNode(node, name, pos)
return node
@ -532,7 +537,7 @@ class Flowchart(Node):
startDir = self.filePath
if startDir is None:
startDir = '.'
self.fileDialog = pg.FileDialog(None, "Load Flowchart..", startDir, "Flowchart (*.fc)")
self.fileDialog = FileDialog(None, "Load Flowchart..", startDir, "Flowchart (*.fc)")
#self.fileDialog.setFileMode(QtGui.QFileDialog.AnyFile)
#self.fileDialog.setAcceptMode(QtGui.QFileDialog.AcceptSave)
self.fileDialog.show()
@ -553,7 +558,7 @@ class Flowchart(Node):
startDir = self.filePath
if startDir is None:
startDir = '.'
self.fileDialog = pg.FileDialog(None, "Save Flowchart..", startDir, "Flowchart (*.fc)")
self.fileDialog = FileDialog(None, "Save Flowchart..", startDir, "Flowchart (*.fc)")
#self.fileDialog.setFileMode(QtGui.QFileDialog.AnyFile)
self.fileDialog.setAcceptMode(QtGui.QFileDialog.AcceptSave)
#self.fileDialog.setDirectory(startDir)
@ -816,7 +821,7 @@ class FlowchartWidget(dockarea.DockArea):
self.selDescLabel = QtGui.QLabel()
self.selNameLabel = QtGui.QLabel()
self.selDescLabel.setWordWrap(True)
self.selectedTree = pg.DataTreeWidget()
self.selectedTree = DataTreeWidget()
#self.selectedTree.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
#self.selInfoLayout.addWidget(self.selNameLabel)
self.selInfoLayout.addWidget(self.selDescLabel)
@ -846,13 +851,13 @@ class FlowchartWidget(dockarea.DockArea):
self.nodeMenu.triggered.disconnect(self.nodeMenuTriggered)
self.nodeMenu = None
self.subMenus = []
library.loadLibrary(reloadLibs=True)
self.chart.library.reload()
self.buildMenu()
def buildMenu(self, pos=None):
self.nodeMenu = QtGui.QMenu()
self.subMenus = []
for section, nodes in library.getNodeTree().items():
for section, nodes in self.chart.library.getNodeTree().items():
menu = QtGui.QMenu(section)
self.nodeMenu.addMenu(menu)
for name in nodes:

View File

@ -107,12 +107,12 @@
<customwidget>
<class>TreeWidget</class>
<extends>QTreeWidget</extends>
<header>pyqtgraph.widgets.TreeWidget</header>
<header>..widgets.TreeWidget</header>
</customwidget>
<customwidget>
<class>FeedbackButton</class>
<extends>QPushButton</extends>
<header>pyqtgraph.widgets.FeedbackButton</header>
<header>..widgets.FeedbackButton</header>
</customwidget>
</customwidgets>
<resources/>

View File

@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file './flowchart/FlowchartCtrlTemplate.ui'
# Form implementation generated from reading ui file './pyqtgraph/flowchart/FlowchartCtrlTemplate.ui'
#
# Created: Sun Sep 9 14:41:30 2012
# by: PyQt4 UI code generator 4.9.1
# Created: Mon Dec 23 10:10:50 2013
# by: PyQt4 UI code generator 4.10
#
# WARNING! All changes made in this file will be lost!
@ -12,7 +12,16 @@ from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_Form(object):
def setupUi(self, Form):
@ -60,12 +69,12 @@ class Ui_Form(object):
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
self.loadBtn.setText(QtGui.QApplication.translate("Form", "Load..", None, QtGui.QApplication.UnicodeUTF8))
self.saveBtn.setText(QtGui.QApplication.translate("Form", "Save", None, QtGui.QApplication.UnicodeUTF8))
self.saveAsBtn.setText(QtGui.QApplication.translate("Form", "As..", None, QtGui.QApplication.UnicodeUTF8))
self.reloadBtn.setText(QtGui.QApplication.translate("Form", "Reload Libs", None, QtGui.QApplication.UnicodeUTF8))
self.showChartBtn.setText(QtGui.QApplication.translate("Form", "Flowchart", None, QtGui.QApplication.UnicodeUTF8))
Form.setWindowTitle(_translate("Form", "Form", None))
self.loadBtn.setText(_translate("Form", "Load..", None))
self.saveBtn.setText(_translate("Form", "Save", None))
self.saveAsBtn.setText(_translate("Form", "As..", None))
self.reloadBtn.setText(_translate("Form", "Reload Libs", None))
self.showChartBtn.setText(_translate("Form", "Flowchart", None))
from pyqtgraph.widgets.FeedbackButton import FeedbackButton
from pyqtgraph.widgets.TreeWidget import TreeWidget
from ..widgets.TreeWidget import TreeWidget
from ..widgets.FeedbackButton import FeedbackButton

View File

@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file './flowchart/FlowchartCtrlTemplate.ui'
# Form implementation generated from reading ui file './pyqtgraph/flowchart/FlowchartCtrlTemplate.ui'
#
# Created: Sun Sep 9 14:41:30 2012
# by: pyside-uic 0.2.13 running on PySide 1.1.0
# Created: Mon Dec 23 10:10:51 2013
# by: pyside-uic 0.2.14 running on PySide 1.1.2
#
# WARNING! All changes made in this file will be lost!
@ -62,5 +62,5 @@ class Ui_Form(object):
self.reloadBtn.setText(QtGui.QApplication.translate("Form", "Reload Libs", None, QtGui.QApplication.UnicodeUTF8))
self.showChartBtn.setText(QtGui.QApplication.translate("Form", "Flowchart", None, QtGui.QApplication.UnicodeUTF8))
from pyqtgraph.widgets.FeedbackButton import FeedbackButton
from pyqtgraph.widgets.TreeWidget import TreeWidget
from ..widgets.TreeWidget import TreeWidget
from ..widgets.FeedbackButton import FeedbackButton

View File

@ -1,8 +1,8 @@
# -*- coding: utf-8 -*-
from pyqtgraph.Qt import QtGui, QtCore
from pyqtgraph.widgets.GraphicsView import GraphicsView
from pyqtgraph.GraphicsScene import GraphicsScene
from pyqtgraph.graphicsItems.ViewBox import ViewBox
from ..Qt import QtGui, QtCore
from ..widgets.GraphicsView import GraphicsView
from ..GraphicsScene import GraphicsScene
from ..graphicsItems.ViewBox import ViewBox
#class FlowchartGraphicsView(QtGui.QGraphicsView):
class FlowchartGraphicsView(GraphicsView):

View File

@ -85,12 +85,12 @@
<customwidget>
<class>DataTreeWidget</class>
<extends>QTreeWidget</extends>
<header>pyqtgraph.widgets.DataTreeWidget</header>
<header>..widgets.DataTreeWidget</header>
</customwidget>
<customwidget>
<class>FlowchartGraphicsView</class>
<extends>QGraphicsView</extends>
<header>pyqtgraph.flowchart.FlowchartGraphicsView</header>
<header>..flowchart.FlowchartGraphicsView</header>
</customwidget>
</customwidgets>
<resources/>

View File

@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file './flowchart/FlowchartTemplate.ui'
# Form implementation generated from reading ui file './pyqtgraph/flowchart/FlowchartTemplate.ui'
#
# Created: Sun Feb 24 19:47:29 2013
# by: PyQt4 UI code generator 4.9.3
# Created: Mon Dec 23 10:10:51 2013
# by: PyQt4 UI code generator 4.10
#
# WARNING! All changes made in this file will be lost!
@ -12,7 +12,16 @@ from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_Form(object):
def setupUi(self, Form):
@ -53,7 +62,7 @@ class Ui_Form(object):
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
Form.setWindowTitle(_translate("Form", "Form", None))
from pyqtgraph.widgets.DataTreeWidget import DataTreeWidget
from pyqtgraph.flowchart.FlowchartGraphicsView import FlowchartGraphicsView
from ..flowchart.FlowchartGraphicsView import FlowchartGraphicsView
from ..widgets.DataTreeWidget import DataTreeWidget

View File

@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file './flowchart/FlowchartTemplate.ui'
# Form implementation generated from reading ui file './pyqtgraph/flowchart/FlowchartTemplate.ui'
#
# Created: Sun Feb 24 19:47:30 2013
# by: pyside-uic 0.2.13 running on PySide 1.1.1
# Created: Mon Dec 23 10:10:51 2013
# by: pyside-uic 0.2.14 running on PySide 1.1.2
#
# WARNING! All changes made in this file will be lost!
@ -50,5 +50,5 @@ class Ui_Form(object):
def retranslateUi(self, Form):
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
from pyqtgraph.widgets.DataTreeWidget import DataTreeWidget
from pyqtgraph.flowchart.FlowchartGraphicsView import FlowchartGraphicsView
from ..flowchart.FlowchartGraphicsView import FlowchartGraphicsView
from ..widgets.DataTreeWidget import DataTreeWidget

View File

@ -1,10 +1,10 @@
# -*- coding: utf-8 -*-
from pyqtgraph.Qt import QtCore, QtGui
from pyqtgraph.graphicsItems.GraphicsObject import GraphicsObject
import pyqtgraph.functions as fn
from ..Qt import QtCore, QtGui
from ..graphicsItems.GraphicsObject import GraphicsObject
from .. import functions as fn
from .Terminal import *
from pyqtgraph.pgcollections import OrderedDict
from pyqtgraph.debug import *
from ..pgcollections import OrderedDict
from ..debug import *
import numpy as np
from .eq import *
@ -618,9 +618,6 @@ class NodeGraphicsItem(GraphicsObject):
def getMenu(self):
return self.menu
def getContextMenus(self, event):
return [self.menu]
def raiseContextMenu(self, ev):
menu = self.scene().addParentContextMenus(self, self.getMenu(), ev)
pos = ev.screenPos()

84
flowchart/NodeLibrary.py Normal file
View File

@ -0,0 +1,84 @@
from ..pgcollections import OrderedDict
from .Node import Node
def isNodeClass(cls):
try:
if not issubclass(cls, Node):
return False
except:
return False
return hasattr(cls, 'nodeName')
class NodeLibrary:
"""
A library of flowchart Node types. Custom libraries may be built to provide
each flowchart with a specific set of allowed Node types.
"""
def __init__(self):
self.nodeList = OrderedDict()
self.nodeTree = OrderedDict()
def addNodeType(self, nodeClass, paths, override=False):
"""
Register a new node type. If the type's name is already in use,
an exception will be raised (unless override=True).
Arguments:
nodeClass - a subclass of Node (must have typ.nodeName)
paths - list of tuples specifying the location(s) this
type will appear in the library tree.
override - if True, overwrite any class having the same name
"""
if not isNodeClass(nodeClass):
raise Exception("Object %s is not a Node subclass" % str(nodeClass))
name = nodeClass.nodeName
if not override and name in self.nodeList:
raise Exception("Node type name '%s' is already registered." % name)
self.nodeList[name] = nodeClass
for path in paths:
root = self.nodeTree
for n in path:
if n not in root:
root[n] = OrderedDict()
root = root[n]
root[name] = nodeClass
def getNodeType(self, name):
try:
return self.nodeList[name]
except KeyError:
raise Exception("No node type called '%s'" % name)
def getNodeTree(self):
return self.nodeTree
def copy(self):
"""
Return a copy of this library.
"""
lib = NodeLibrary()
lib.nodeList = self.nodeList.copy()
lib.nodeTree = self.treeCopy(self.nodeTree)
return lib
@staticmethod
def treeCopy(tree):
copy = OrderedDict()
for k,v in tree.items():
if isNodeClass(v):
copy[k] = v
else:
copy[k] = NodeLibrary.treeCopy(v)
return copy
def reload(self):
"""
Reload Node classes in this library.
"""
raise NotImplementedError()

View File

@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
from pyqtgraph.Qt import QtCore, QtGui
from ..Qt import QtCore, QtGui
import weakref
from pyqtgraph.graphicsItems.GraphicsObject import GraphicsObject
import pyqtgraph.functions as fn
from pyqtgraph.Point import Point
from ..graphicsItems.GraphicsObject import GraphicsObject
from .. import functions as fn
from ..Point import Point
#from PySide import QtCore, QtGui
from .eq import *
@ -437,10 +437,6 @@ class TerminalGraphicsItem(GraphicsObject):
multi = self.menu.multiAct.isChecked()
self.term.setMultiValue(multi)
## probably never need this
#def getContextMenus(self, ev):
#return [self.getMenu()]
def removeSelf(self):
self.term.node().removeTerminal(self.term)

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
from numpy import ndarray, bool_
from pyqtgraph.metaarray import MetaArray
from ..metaarray import MetaArray
def eq(a, b):
"""The great missing equivalence function: Guaranteed evaluation to a single bool value."""

View File

@ -1,12 +1,12 @@
# -*- coding: utf-8 -*-
from ..Node import Node
from pyqtgraph.Qt import QtGui, QtCore
from ...Qt import QtGui, QtCore
import numpy as np
from .common import *
from pyqtgraph.SRTTransform import SRTTransform
from pyqtgraph.Point import Point
from pyqtgraph.widgets.TreeWidget import TreeWidget
from pyqtgraph.graphicsItems.LinearRegionItem import LinearRegionItem
from ...SRTTransform import SRTTransform
from ...Point import Point
from ...widgets.TreeWidget import TreeWidget
from ...graphicsItems.LinearRegionItem import LinearRegionItem
from . import functions

View File

@ -1,11 +1,10 @@
# -*- coding: utf-8 -*-
from ..Node import Node
import weakref
#from pyqtgraph import graphicsItems
from pyqtgraph.Qt import QtCore, QtGui
from pyqtgraph.graphicsItems.ScatterPlotItem import ScatterPlotItem
from pyqtgraph.graphicsItems.PlotCurveItem import PlotCurveItem
from pyqtgraph import PlotDataItem
from ...Qt import QtCore, QtGui
from ...graphicsItems.ScatterPlotItem import ScatterPlotItem
from ...graphicsItems.PlotCurveItem import PlotCurveItem
from ... import PlotDataItem
from .common import *
import numpy as np

View File

@ -1,14 +1,14 @@
# -*- coding: utf-8 -*-
from pyqtgraph.Qt import QtCore, QtGui
from ...Qt import QtCore, QtGui
from ..Node import Node
from scipy.signal import detrend
from scipy.ndimage import median_filter, gaussian_filter
#from pyqtgraph.SignalProxy import SignalProxy
#from ...SignalProxy import SignalProxy
from . import functions
from .common import *
import numpy as np
import pyqtgraph.metaarray as metaarray
from ... import metaarray as metaarray
class Downsample(CtrlNode):

View File

@ -1,103 +1,28 @@
# -*- coding: utf-8 -*-
from pyqtgraph.pgcollections import OrderedDict
from pyqtgraph import importModules
from ...pgcollections import OrderedDict
import os, types
from pyqtgraph.debug import printExc
from ..Node import Node
import pyqtgraph.reload as reload
from ...debug import printExc
from ..NodeLibrary import NodeLibrary, isNodeClass
from ... import reload as reload
NODE_LIST = OrderedDict() ## maps name:class for all registered Node subclasses
NODE_TREE = OrderedDict() ## categorized tree of Node subclasses
# Build default library
LIBRARY = NodeLibrary()
def getNodeType(name):
try:
return NODE_LIST[name]
except KeyError:
raise Exception("No node type called '%s'" % name)
# For backward compatibility, expose the default library's properties here:
NODE_LIST = LIBRARY.nodeList
NODE_TREE = LIBRARY.nodeTree
registerNodeType = LIBRARY.addNodeType
getNodeTree = LIBRARY.getNodeTree
getNodeType = LIBRARY.getNodeType
def getNodeTree():
return NODE_TREE
def registerNodeType(cls, paths, override=False):
"""
Register a new node type. If the type's name is already in use,
an exception will be raised (unless override=True).
Arguments:
cls - a subclass of Node (must have typ.nodeName)
paths - list of tuples specifying the location(s) this
type will appear in the library tree.
override - if True, overwrite any class having the same name
"""
if not isNodeClass(cls):
raise Exception("Object %s is not a Node subclass" % str(cls))
name = cls.nodeName
if not override and name in NODE_LIST:
raise Exception("Node type name '%s' is already registered." % name)
NODE_LIST[name] = cls
for path in paths:
root = NODE_TREE
for n in path:
if n not in root:
root[n] = OrderedDict()
root = root[n]
root[name] = cls
# Add all nodes to the default library
from . import Data, Display, Filters, Operators
for mod in [Data, Display, Filters, Operators]:
nodes = [getattr(mod, name) for name in dir(mod) if isNodeClass(getattr(mod, name))]
for node in nodes:
LIBRARY.addNodeType(node, [(mod.__name__.split('.')[-1],)])
def isNodeClass(cls):
try:
if not issubclass(cls, Node):
return False
except:
return False
return hasattr(cls, 'nodeName')
def loadLibrary(reloadLibs=False, libPath=None):
"""Import all Node subclasses found within files in the library module."""
global NODE_LIST, NODE_TREE
#if libPath is None:
#libPath = os.path.dirname(os.path.abspath(__file__))
if reloadLibs:
reload.reloadAll(libPath)
mods = importModules('', globals(), locals())
#for f in frozenSupport.listdir(libPath):
#pathName, ext = os.path.splitext(f)
#if ext not in ('.py', '.pyc') or '__init__' in pathName or '__pycache__' in pathName:
#continue
#try:
##print "importing from", f
#mod = __import__(pathName, globals(), locals())
#except:
#printExc("Error loading flowchart library %s:" % pathName)
#continue
for name, mod in mods.items():
nodes = []
for n in dir(mod):
o = getattr(mod, n)
if isNodeClass(o):
#print " ", str(o)
registerNodeType(o, [(name,)], override=reloadLibs)
#nodes.append((o.nodeName, o))
#if len(nodes) > 0:
#NODE_TREE[name] = OrderedDict(nodes)
#NODE_LIST.extend(nodes)
#NODE_LIST = OrderedDict(NODE_LIST)
def reloadLibrary():
loadLibrary(reloadLibs=True)
loadLibrary()
#NODE_LIST = []
#for o in locals().values():
#if type(o) is type(AddNode) and issubclass(o, Node) and o is not Node and hasattr(o, 'nodeName'):
#NODE_LIST.append((o.nodeName, o))
#NODE_LIST.sort(lambda a,b: cmp(a[0], b[0]))
#NODE_LIST = OrderedDict(NODE_LIST)

View File

@ -1,12 +1,12 @@
# -*- coding: utf-8 -*-
from pyqtgraph.Qt import QtCore, QtGui
from pyqtgraph.widgets.SpinBox import SpinBox
#from pyqtgraph.SignalProxy import SignalProxy
from pyqtgraph.WidgetGroup import WidgetGroup
from ...Qt import QtCore, QtGui
from ...widgets.SpinBox import SpinBox
#from ...SignalProxy import SignalProxy
from ...WidgetGroup import WidgetGroup
#from ColorMapper import ColorMapper
from ..Node import Node
import numpy as np
from pyqtgraph.widgets.ColorButton import ColorButton
from ...widgets.ColorButton import ColorButton
try:
import metaarray
HAVE_METAARRAY = True

View File

@ -1,6 +1,6 @@
import scipy
import numpy as np
from pyqtgraph.metaarray import MetaArray
from ...metaarray import MetaArray
def downsample(data, n, axis=0, xvals='subsample'):
"""Downsample by averaging points together across axis.

View File

@ -24,7 +24,7 @@ SI_PREFIXES_ASCII = 'yzafpnum kMGTPEZY'
from .Qt import QtGui, QtCore, USE_PYSIDE
import pyqtgraph as pg
from . import getConfigOption, setConfigOptions
import numpy as np
import decimal, re
import ctypes
@ -33,11 +33,11 @@ import sys, struct
try:
import scipy.ndimage
HAVE_SCIPY = True
if pg.getConfigOption('useWeave'):
if getConfigOption('useWeave'):
try:
import scipy.weave
except ImportError:
pg.setConfigOptions(useWeave=False)
setConfigOptions(useWeave=False)
except ImportError:
HAVE_SCIPY = False
@ -620,7 +620,7 @@ def rescaleData(data, scale, offset, dtype=None):
dtype = np.dtype(dtype)
try:
if not pg.getConfigOption('useWeave'):
if not getConfigOption('useWeave'):
raise Exception('Weave is disabled; falling back to slower version.')
## require native dtype when using weave
@ -647,10 +647,10 @@ def rescaleData(data, scale, offset, dtype=None):
newData = newData.astype(dtype)
data = newData.reshape(data.shape)
except:
if pg.getConfigOption('useWeave'):
if pg.getConfigOption('weaveDebug'):
if getConfigOption('useWeave'):
if getConfigOption('weaveDebug'):
debug.printExc("Error; disabling weave.")
pg.setConfigOption('useWeave', False)
setConfigOptions(useWeave=False)
#p = np.poly1d([scale, -offset*scale])
#data = p(data).astype(dtype)
@ -775,32 +775,13 @@ def makeARGB(data, lut=None, levels=None, scale=None, useRGBA=False):
is BGRA).
============ ==================================================================================
"""
prof = debug.Profiler('functions.makeARGB', disabled=True)
profile = debug.Profiler()
if lut is not None and not isinstance(lut, np.ndarray):
lut = np.array(lut)
if levels is not None and not isinstance(levels, np.ndarray):
levels = np.array(levels)
## sanity checks
#if data.ndim == 3:
#if data.shape[2] not in (3,4):
#raise Exception("data.shape[2] must be 3 or 4")
##if lut is not None:
##raise Exception("can not use lookup table with 3D data")
#elif data.ndim != 2:
#raise Exception("data must be 2D or 3D")
#if lut is not None:
##if lut.ndim == 2:
##if lut.shape[1] :
##raise Exception("lut.shape[1] must be 3 or 4")
##elif lut.ndim != 1:
##raise Exception("lut must be 1D or 2D")
#if lut.dtype != np.ubyte:
#raise Exception('lookup table must have dtype=ubyte (got %s instead)' % str(lut.dtype))
if levels is not None:
if levels.ndim == 1:
if len(levels) != 2:
@ -813,18 +794,8 @@ def makeARGB(data, lut=None, levels=None, scale=None, useRGBA=False):
else:
print(levels)
raise Exception("levels argument must be 1D or 2D.")
#levels = np.array(levels)
#if levels.shape == (2,):
#pass
#elif levels.shape in [(3,2), (4,2)]:
#if data.ndim == 3:
#raise Exception("Can not use 2D levels with 3D data.")
#if lut is not None:
#raise Exception('Can not use 2D levels and lookup table together.')
#else:
#raise Exception("Levels must have shape (2,) or (3,2) or (4,2)")
prof.mark('1')
profile()
if scale is None:
if lut is not None:
@ -851,8 +822,8 @@ def makeARGB(data, lut=None, levels=None, scale=None, useRGBA=False):
if minVal == maxVal:
maxVal += 1e-16
data = rescaleData(data, scale/(maxVal-minVal), minVal, dtype=int)
prof.mark('2')
profile()
## apply LUT if given
if lut is not None:
@ -860,39 +831,41 @@ def makeARGB(data, lut=None, levels=None, scale=None, useRGBA=False):
else:
if data.dtype is not np.ubyte:
data = np.clip(data, 0, 255).astype(np.ubyte)
prof.mark('3')
profile()
## copy data into ARGB ordered array
imgData = np.empty(data.shape[:2]+(4,), dtype=np.ubyte)
if data.ndim == 2:
data = data[..., np.newaxis]
prof.mark('4')
profile()
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.
if data.shape[2] == 1:
if data.ndim == 2:
# This is tempting:
# imgData[..., :3] = data[..., np.newaxis]
# ..but it turns out this is faster:
for i in range(3):
imgData[..., order[i]] = data[..., 0]
imgData[..., i] = data
elif data.shape[2] == 1:
for i in range(3):
imgData[..., i] = data[..., 0]
else:
for i in range(0, data.shape[2]):
imgData[..., order[i]] = data[..., i]
imgData[..., i] = data[..., order[i]]
prof.mark('5')
profile()
if data.shape[2] == 4:
alpha = True
else:
if data.ndim == 2 or data.shape[2] == 3:
alpha = False
imgData[..., 3] = 255
else:
alpha = True
prof.mark('6')
prof.finish()
profile()
return imgData, alpha
@ -923,7 +896,7 @@ def makeQImage(imgData, alpha=None, copy=True, transpose=True):
=========== ===================================================================
"""
## create QImage from buffer
prof = debug.Profiler('functions.makeQImage', disabled=True)
profile = debug.Profiler()
## If we didn't explicitly specify alpha, check the array shape.
if alpha is None:
@ -948,6 +921,8 @@ def makeQImage(imgData, alpha=None, copy=True, transpose=True):
if transpose:
imgData = imgData.transpose((1, 0, 2)) ## QImage expects the row/column order to be opposite
profile()
if not imgData.flags['C_CONTIGUOUS']:
if copy is False:
extra = ' (try setting transpose=False)' if transpose else ''
@ -988,11 +963,10 @@ def makeQImage(imgData, alpha=None, copy=True, transpose=True):
#except AttributeError: ## happens when image data is non-contiguous
#buf = imgData.data
#prof.mark('1')
#profiler()
#qimage = QtGui.QImage(buf, imgData.shape[1], imgData.shape[0], imgFormat)
#prof.mark('2')
#profiler()
#qimage.data = imgData
#prof.finish()
#return qimage
def imageToArray(img, copy=False, transpose=True):
@ -1112,16 +1086,16 @@ def arrayToQPath(x, y, connect='all'):
path = QtGui.QPainterPath()
#prof = debug.Profiler('PlotCurveItem.generatePath', disabled=True)
#profiler = debug.Profiler()
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')
#profiler('allocate empty')
byteview = arr.view(dtype=np.ubyte)
byteview[:12] = 0
byteview.data[12:20] = struct.pack('>ii', n, 0)
#prof.mark('pack header')
#profiler('pack header')
# Fill array with vertex values
arr[1:-1]['x'] = x
arr[1:-1]['y'] = y
@ -1142,11 +1116,11 @@ def arrayToQPath(x, y, connect='all'):
else:
raise Exception('connect argument must be "all", "pairs", or array')
#prof.mark('fill array')
#profiler('fill array')
# write last 0
lastInd = 20*(n+1)
byteview.data[lastInd:lastInd+4] = struct.pack('>i', 0)
#prof.mark('footer')
#profiler('footer')
# create datastream object and stream into path
## Avoiding this method because QByteArray(str) leaks memory in PySide
@ -1157,13 +1131,11 @@ def arrayToQPath(x, y, connect='all'):
buf = QtCore.QByteArray.fromRawData(path.strn)
except TypeError:
buf = QtCore.QByteArray(bytes(path.strn))
#prof.mark('create buffer')
#profiler('create buffer')
ds = QtCore.QDataStream(buf)
ds >> path
#prof.mark('load')
#prof.finish()
#profiler('load')
return path
@ -1890,7 +1862,7 @@ def isosurface(data, level):
faces = np.empty((totFaces, 3), dtype=np.uint32)
ptr = 0
#import debug
#p = debug.Profiler('isosurface', disabled=False)
#p = debug.Profiler()
## this helps speed up an indexing operation later on
cs = np.array(cutEdges.strides)//cutEdges.itemsize
@ -1902,32 +1874,32 @@ def isosurface(data, level):
for i in range(1,6):
### expensive:
#p.mark('1')
#profiler()
cells = np.argwhere(nFaces == i) ## all cells which require i faces (argwhere is expensive)
#p.mark('2')
#profiler()
if cells.shape[0] == 0:
continue
#cellInds = index[(cells*ins[np.newaxis,:]).sum(axis=1)]
cellInds = index[cells[:,0], cells[:,1], cells[:,2]] ## index values of cells to process for this round
#p.mark('3')
#profiler()
### expensive:
verts = faceShiftTables[i][cellInds]
#p.mark('4')
#profiler()
verts[...,:3] += cells[:,np.newaxis,np.newaxis,:] ## we now have indexes into cutEdges
verts = verts.reshape((verts.shape[0]*i,)+verts.shape[2:])
#p.mark('5')
#profiler()
### expensive:
#print verts.shape
verts = (verts * cs[np.newaxis, np.newaxis, :]).sum(axis=2)
#vertInds = cutEdges[verts[...,0], verts[...,1], verts[...,2], verts[...,3]] ## and these are the vertex indexes we want.
vertInds = cutEdges[verts]
#p.mark('6')
#profiler()
nv = vertInds.shape[0]
#p.mark('7')
#profiler()
faces[ptr:ptr+nv] = vertInds #.reshape((nv, 3))
#p.mark('8')
#profiler()
ptr += nv
return vertexes, faces

View File

@ -1,5 +1,5 @@
from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph.functions as fn
from ..Qt import QtGui, QtCore
from .. import functions as fn
import numpy as np
__all__ = ['ArrowItem']

View File

@ -1,11 +1,11 @@
from pyqtgraph.Qt import QtGui, QtCore
from pyqtgraph.python2_3 import asUnicode
from ..Qt import QtGui, QtCore
from ..python2_3 import asUnicode
import numpy as np
from pyqtgraph.Point import Point
import pyqtgraph.debug as debug
from ..Point import Point
from .. import debug as debug
import weakref
import pyqtgraph.functions as fn
import pyqtgraph as pg
from .. import functions as fn
from .. import getConfigOption
from .GraphicsWidget import GraphicsWidget
__all__ = ['AxisItem']
@ -268,8 +268,8 @@ class AxisItem(GraphicsWidget):
def pen(self):
if self._pen is None:
return fn.mkPen(pg.getConfigOption('foreground'))
return pg.mkPen(self._pen)
return fn.mkPen(getConfigOption('foreground'))
return fn.mkPen(self._pen)
def setPen(self, pen):
"""
@ -280,8 +280,8 @@ class AxisItem(GraphicsWidget):
self._pen = pen
self.picture = None
if pen is None:
pen = pg.getConfigOption('foreground')
self.labelStyle['color'] = '#' + pg.colorStr(pg.mkPen(pen).color())[:6]
pen = getConfigOption('foreground')
self.labelStyle['color'] = '#' + fn.colorStr(fn.mkPen(pen).color())[:6]
self.setLabel()
self.update()
@ -404,25 +404,22 @@ class AxisItem(GraphicsWidget):
return self.mapRectFromParent(self.geometry()) | linkedView.mapRectToItem(self, linkedView.boundingRect())
def paint(self, p, opt, widget):
prof = debug.Profiler('AxisItem.paint', disabled=True)
profiler = debug.Profiler()
if self.picture is None:
try:
picture = QtGui.QPicture()
painter = QtGui.QPainter(picture)
specs = self.generateDrawSpecs(painter)
prof.mark('generate specs')
profiler('generate specs')
if specs is not None:
self.drawPicture(painter, *specs)
prof.mark('draw picture')
profiler('draw picture')
finally:
painter.end()
self.picture = picture
#p.setRenderHint(p.Antialiasing, False) ## Sometimes we get a segfault here ???
#p.setRenderHint(p.TextAntialiasing, True)
self.picture.play(p)
prof.finish()
def setTicks(self, ticks):
"""Explicitly determine which ticks to display.
@ -626,7 +623,7 @@ class AxisItem(GraphicsWidget):
be drawn, then generates from this a set of drawing commands to be
interpreted by drawPicture().
"""
prof = debug.Profiler("AxisItem.generateDrawSpecs", disabled=True)
profiler = debug.Profiler()
#bounds = self.boundingRect()
bounds = self.mapRectFromParent(self.geometry())
@ -706,7 +703,7 @@ class AxisItem(GraphicsWidget):
xMin = min(xRange)
xMax = max(xRange)
prof.mark('init')
profiler('init')
tickPositions = [] # remembers positions of previously drawn ticks
@ -744,7 +741,7 @@ class AxisItem(GraphicsWidget):
color.setAlpha(lineAlpha)
tickPen.setColor(color)
tickSpecs.append((tickPen, Point(p1), Point(p2)))
prof.mark('compute ticks')
profiler('compute ticks')
## This is where the long axis line should be drawn
@ -857,7 +854,7 @@ class AxisItem(GraphicsWidget):
#p.setPen(self.pen())
#p.drawText(rect, textFlags, vstr)
textSpecs.append((rect, textFlags, vstr))
prof.mark('compute text')
profiler('compute text')
## update max text size if needed.
self._updateMaxTextSize(textSize2)
@ -865,7 +862,7 @@ class AxisItem(GraphicsWidget):
return (axisSpec, tickSpecs, textSpecs)
def drawPicture(self, p, axisSpec, tickSpecs, textSpecs):
prof = debug.Profiler("AxisItem.drawPicture", disabled=True)
profiler = debug.Profiler()
p.setRenderHint(p.Antialiasing, False)
p.setRenderHint(p.TextAntialiasing, True)
@ -880,7 +877,7 @@ class AxisItem(GraphicsWidget):
for pen, p1, p2 in tickSpecs:
p.setPen(pen)
p.drawLine(p1, p2)
prof.mark('draw ticks')
profiler('draw ticks')
## Draw all text
if self.tickFont is not None:
@ -889,9 +886,7 @@ class AxisItem(GraphicsWidget):
for rect, flags, text in textSpecs:
p.drawText(rect, flags, text)
#p.drawRect(rect)
prof.mark('draw text')
prof.finish()
profiler('draw text')
def show(self):

View File

@ -1,8 +1,10 @@
import pyqtgraph as pg
from pyqtgraph.Qt import QtGui, QtCore
from ..Qt import QtGui, QtCore
from .GraphicsObject import GraphicsObject
from .. import getConfigOption
from .. import functions as fn
import numpy as np
__all__ = ['BarGraphItem']
class BarGraphItem(GraphicsObject):
@ -61,7 +63,7 @@ class BarGraphItem(GraphicsObject):
pens = self.opts['pens']
if pen is None and pens is None:
pen = pg.getConfigOption('foreground')
pen = getConfigOption('foreground')
brush = self.opts['brush']
brushes = self.opts['brushes']
@ -112,13 +114,13 @@ class BarGraphItem(GraphicsObject):
raise Exception('must specify either y1 or height')
height = y1 - y0
p.setPen(pg.mkPen(pen))
p.setBrush(pg.mkBrush(brush))
p.setPen(fn.mkPen(pen))
p.setBrush(fn.mkBrush(brush))
for i in range(len(x0)):
if pens is not None:
p.setPen(pg.mkPen(pens[i]))
p.setPen(fn.mkPen(pens[i]))
if brushes is not None:
p.setBrush(pg.mkBrush(brushes[i]))
p.setBrush(fn.mkBrush(brushes[i]))
if np.isscalar(y0):
y = y0

View File

@ -1,4 +1,4 @@
from pyqtgraph.Qt import QtGui, QtCore
from ..Qt import QtGui, QtCore
from .GraphicsObject import GraphicsObject
__all__ = ['ButtonItem']

View File

@ -1,7 +1,7 @@
from pyqtgraph.Qt import QtGui, QtCore
from ..Qt import QtGui, QtCore
from . import ArrowItem
import numpy as np
from pyqtgraph.Point import Point
from ..Point import Point
import weakref
from .GraphicsObject import GraphicsObject

View File

@ -1,6 +1,7 @@
import pyqtgraph as pg
from pyqtgraph.Qt import QtGui, QtCore
from ..Qt import QtGui, QtCore
from .GraphicsObject import GraphicsObject
from .. import getConfigOption
from .. import functions as fn
__all__ = ['ErrorBarItem']
@ -121,8 +122,8 @@ class ErrorBarItem(GraphicsObject):
self.drawPath()
pen = self.opts['pen']
if pen is None:
pen = pg.getConfigOption('foreground')
p.setPen(pg.mkPen(pen))
pen = getConfigOption('foreground')
p.setPen(fn.mkPen(pen))
p.drawPath(self.path)
def boundingRect(self):

View File

@ -1,23 +1,24 @@
import pyqtgraph as pg
from ..Qt import QtGui
from .. import functions as fn
class FillBetweenItem(pg.QtGui.QGraphicsPathItem):
class FillBetweenItem(QtGui.QGraphicsPathItem):
"""
GraphicsItem filling the space between two PlotDataItems.
"""
def __init__(self, p1, p2, brush=None):
pg.QtGui.QGraphicsPathItem.__init__(self)
QtGui.QGraphicsPathItem.__init__(self)
self.p1 = p1
self.p2 = p2
p1.sigPlotChanged.connect(self.updatePath)
p2.sigPlotChanged.connect(self.updatePath)
if brush is not None:
self.setBrush(pg.mkBrush(brush))
self.setBrush(fn.mkBrush(brush))
self.setZValue(min(p1.zValue(), p2.zValue())-1)
self.updatePath()
def updatePath(self):
p1 = self.p1.curve.path
p2 = self.p2.curve.path
path = pg.QtGui.QPainterPath()
path = QtGui.QPainterPath()
path.addPolygon(p1.toSubpathPolygons()[0] + p2.toReversed().toSubpathPolygons()[0])
self.setPath(path)

View File

@ -1,11 +1,11 @@
from pyqtgraph.Qt import QtGui, QtCore
from pyqtgraph.python2_3 import sortList
import pyqtgraph.functions as fn
from ..Qt import QtGui, QtCore
from ..python2_3 import sortList
from .. import functions as fn
from .GraphicsObject import GraphicsObject
from .GraphicsWidget import GraphicsWidget
import weakref
from pyqtgraph.pgcollections import OrderedDict
from pyqtgraph.colormap import ColorMap
from ..pgcollections import OrderedDict
from ..colormap import ColorMap
import numpy as np

View File

@ -1,6 +1,6 @@
from pyqtgraph.Qt import QtGui, QtCore
from ..Qt import QtGui, QtCore
from .UIGraphicsItem import *
import pyqtgraph.functions as fn
from .. import functions as fn
__all__ = ['GradientLegend']

View File

@ -1,8 +1,9 @@
from .. import functions as fn
from .GraphicsObject import GraphicsObject
from .ScatterPlotItem import ScatterPlotItem
import pyqtgraph as pg
from ..Qt import QtGui, QtCore
import numpy as np
from .. import getConfigOption
__all__ = ['GraphItem']
@ -71,11 +72,11 @@ class GraphItem(GraphicsObject):
self.picture = None
def generatePicture(self):
self.picture = pg.QtGui.QPicture()
self.picture = QtGui.QPicture()
if self.pen is None or self.pos is None or self.adjacency is None:
return
p = pg.QtGui.QPainter(self.picture)
p = QtGui.QPainter(self.picture)
try:
pts = self.pos[self.adjacency]
pen = self.pen
@ -86,14 +87,14 @@ class GraphItem(GraphicsObject):
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))
p.setPen(fn.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]))
p.setPen(fn.mkPen(color=(pen['red'], pen['green'], pen['blue'], pen['alpha']), width=pen['width']))
p.drawLine(QtCore.QPointF(*pts[i][0]), QtCore.QPointF(*pts[i][1]))
else:
if pen == 'default':
pen = pg.getConfigOption('foreground')
p.setPen(pg.mkPen(pen))
pen = getConfigOption('foreground')
p.setPen(fn.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)
@ -103,7 +104,7 @@ class GraphItem(GraphicsObject):
def paint(self, p, *args):
if self.picture == None:
self.generatePicture()
if pg.getConfigOption('antialias') is True:
if getConfigOption('antialias') is True:
p.setRenderHint(p.Antialiasing)
self.picture.play(p)

View File

@ -1,9 +1,9 @@
from pyqtgraph.Qt import QtGui, QtCore
from pyqtgraph.GraphicsScene import GraphicsScene
from pyqtgraph.Point import Point
import pyqtgraph.functions as fn
from ..Qt import QtGui, QtCore
from ..GraphicsScene import GraphicsScene
from ..Point import Point
from .. import functions as fn
import weakref
from pyqtgraph.pgcollections import OrderedDict
from ..pgcollections import OrderedDict
import operator, sys
class FiniteCache(OrderedDict):
@ -585,3 +585,6 @@ class GraphicsItem(object):
#def update(self):
#self._qtBaseClass.update(self)
#print "Update:", self
def getContextMenus(self, event):
return [self.getMenu()] if hasattr(self, "getMenu") else []

View File

@ -1,5 +1,5 @@
from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph.functions as fn
from ..Qt import QtGui, QtCore
from .. import functions as fn
from .GraphicsWidget import GraphicsWidget
## Must be imported at the end to avoid cyclic-dependency hell:
from .ViewBox import ViewBox

View File

@ -1,4 +1,4 @@
from pyqtgraph.Qt import QtGui, QtCore, USE_PYSIDE
from ..Qt import QtGui, QtCore, USE_PYSIDE
if not USE_PYSIDE:
import sip
from .GraphicsItem import GraphicsItem

View File

@ -1,5 +1,5 @@
from pyqtgraph.Qt import QtGui, QtCore
from pyqtgraph.GraphicsScene import GraphicsScene
from ..Qt import QtGui, QtCore
from ..GraphicsScene import GraphicsScene
from .GraphicsItem import GraphicsItem
__all__ = ['GraphicsWidget']

View File

@ -1,8 +1,8 @@
from pyqtgraph.Qt import QtGui, QtCore
from ..Qt import QtGui, QtCore
from .UIGraphicsItem import *
import numpy as np
from pyqtgraph.Point import Point
import pyqtgraph.functions as fn
from ..Point import Point
from .. import functions as fn
__all__ = ['GridItem']
class GridItem(UIGraphicsItem):

View File

@ -3,8 +3,8 @@ GraphicsWidget displaying an image histogram along with gradient editor. Can be
"""
from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph.functions as fn
from ..Qt import QtGui, QtCore
from .. import functions as fn
from .GraphicsWidget import GraphicsWidget
from .ViewBox import *
from .GradientEditorItem import *
@ -12,10 +12,10 @@ from .LinearRegionItem import *
from .PlotDataItem import *
from .AxisItem import *
from .GridItem import *
from pyqtgraph.Point import Point
import pyqtgraph.functions as fn
from ..Point import Point
from .. import functions as fn
import numpy as np
import pyqtgraph.debug as debug
from .. import debug as debug
__all__ = ['HistogramLUTItem']
@ -184,19 +184,18 @@ class HistogramLUTItem(GraphicsWidget):
self.update()
def imageChanged(self, autoLevel=False, autoRange=False):
prof = debug.Profiler('HistogramLUTItem.imageChanged', disabled=True)
profiler = debug.Profiler()
h = self.imageItem.getHistogram()
prof.mark('get histogram')
profiler('get histogram')
if h[0] is None:
return
self.plot.setData(*h)
prof.mark('set plot')
profiler('set plot')
if autoLevel:
mn = h[0][0]
mx = h[0][-1]
self.region.setRegion([mn, mx])
prof.mark('set region')
prof.finish()
profiler('set region')
def getLevels(self):
return self.region.getRegion()

View File

@ -1,8 +1,8 @@
from pyqtgraph.Qt import QtGui, QtCore
from ..Qt import QtGui, QtCore
import numpy as np
import collections
import pyqtgraph.functions as fn
import pyqtgraph.debug as debug
from .. import functions as fn
from .. import debug as debug
from .GraphicsObject import GraphicsObject
__all__ = ['ImageItem']
@ -188,7 +188,7 @@ class ImageItem(GraphicsObject):
border Sets the pen used when drawing the image border. Default is None.
================= =========================================================================
"""
prof = debug.Profiler('ImageItem.setImage', disabled=True)
profile = debug.Profiler()
gotNewData = False
if image is None:
@ -202,7 +202,7 @@ class ImageItem(GraphicsObject):
self.prepareGeometryChange()
self.informViewBoundsChanged()
prof.mark('1')
profile()
if autoLevels is None:
if 'levels' in kargs:
@ -218,23 +218,22 @@ class ImageItem(GraphicsObject):
mn = 0
mx = 255
kargs['levels'] = [mn,mx]
prof.mark('2')
profile()
self.setOpts(update=False, **kargs)
prof.mark('3')
profile()
self.qimage = None
self.update()
prof.mark('4')
profile()
if gotNewData:
self.sigImageChanged.emit()
prof.finish()
def updateImage(self, *args, **kargs):
## used for re-rendering qimage from self.image.
@ -250,7 +249,7 @@ class ImageItem(GraphicsObject):
def render(self):
prof = debug.Profiler('ImageItem.render', disabled=True)
profile = debug.Profiler()
if self.image is None or self.image.size == 0:
return
if isinstance(self.lut, collections.Callable):
@ -260,30 +259,27 @@ class ImageItem(GraphicsObject):
#print lut.shape
#print self.lut
argb, alpha = fn.makeARGB(self.image, lut=lut, levels=self.levels)
self.qimage = fn.makeQImage(argb, alpha)
prof.finish()
argb, alpha = fn.makeARGB(self.image.transpose((1, 0, 2)[:self.image.ndim]), lut=lut, levels=self.levels)
self.qimage = fn.makeQImage(argb, alpha, transpose=False)
def paint(self, p, *args):
prof = debug.Profiler('ImageItem.paint', disabled=True)
profile = debug.Profiler()
if self.image is None:
return
if self.qimage is None:
self.render()
if self.qimage is None:
return
prof.mark('render QImage')
profile('render QImage')
if self.paintMode is not None:
p.setCompositionMode(self.paintMode)
prof.mark('set comp mode')
profile('set comp mode')
p.drawImage(QtCore.QPointF(0,0), self.qimage)
prof.mark('p.drawImage')
profile('p.drawImage')
if self.border is not None:
p.setPen(self.border)
p.drawRect(self.boundingRect())
prof.finish()
def save(self, fileName, *args):
"""Save this image to file. Note that this saves the visible image (after scale/color changes), not the original data."""

View File

@ -1,7 +1,7 @@
from pyqtgraph.Qt import QtGui, QtCore
from pyqtgraph.Point import Point
from ..Qt import QtGui, QtCore
from ..Point import Point
from .GraphicsObject import GraphicsObject
import pyqtgraph.functions as fn
from .. import functions as fn
import numpy as np
import weakref

View File

@ -1,8 +1,8 @@
from .GraphicsObject import *
import pyqtgraph.functions as fn
from pyqtgraph.Qt import QtGui, QtCore
from .. import functions as fn
from ..Qt import QtGui, QtCore
class IsocurveItem(GraphicsObject):

View File

@ -1,4 +1,4 @@
from pyqtgraph.Qt import QtGui, QtCore
from ..Qt import QtGui, QtCore
from .GraphicsObject import GraphicsObject
__all__ = ['ItemGroup']

View File

@ -1,8 +1,8 @@
from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph.functions as fn
import pyqtgraph as pg
from ..Qt import QtGui, QtCore
from .. import functions as fn
from .GraphicsWidget import GraphicsWidget
from .GraphicsWidgetAnchor import GraphicsWidgetAnchor
from .. import getConfigOption
__all__ = ['LabelItem']
@ -54,7 +54,7 @@ class LabelItem(GraphicsWidget, GraphicsWidgetAnchor):
color = self.opts['color']
if color is None:
color = pg.getConfigOption('foreground')
color = getConfigOption('foreground')
color = fn.mkColor(color)
optlist.append('color: #' + fn.colorStr(color)[:6])
if 'size' in opts:

View File

@ -3,8 +3,9 @@ from .LabelItem import LabelItem
from ..Qt import QtGui, QtCore
from .. import functions as fn
from ..Point import Point
from .ScatterPlotItem import ScatterPlotItem
from .PlotDataItem import PlotDataItem
from .GraphicsWidgetAnchor import GraphicsWidgetAnchor
import pyqtgraph as pg
__all__ = ['LegendItem']
class LegendItem(GraphicsWidget, GraphicsWidgetAnchor):
@ -152,21 +153,21 @@ class ItemSample(GraphicsWidget):
p.setPen(fn.mkPen(None))
p.drawPolygon(QtGui.QPolygonF([QtCore.QPointF(2,18), QtCore.QPointF(18,2), QtCore.QPointF(18,18)]))
if not isinstance(self.item, pg.ScatterPlotItem):
if not isinstance(self.item, ScatterPlotItem):
p.setPen(fn.mkPen(opts['pen']))
p.drawLine(2, 18, 18, 2)
symbol = opts.get('symbol', None)
if symbol is not None:
if isinstance(self.item, pg.PlotDataItem):
if isinstance(self.item, PlotDataItem):
opts = self.item.scatter.opts
pen = pg.mkPen(opts['pen'])
brush = pg.mkBrush(opts['brush'])
pen = fn.mkPen(opts['pen'])
brush = fn.mkBrush(opts['brush'])
size = opts['size']
p.translate(10,10)
path = pg.graphicsItems.ScatterPlotItem.drawSymbol(p, symbol, size, pen, brush)
path = ScatterPlotItem.drawSymbol(p, symbol, size, pen, brush)

View File

@ -1,8 +1,8 @@
from pyqtgraph.Qt import QtGui, QtCore
from ..Qt import QtGui, QtCore
from .UIGraphicsItem import UIGraphicsItem
from .InfiniteLine import InfiniteLine
import pyqtgraph.functions as fn
import pyqtgraph.debug as debug
from .. import functions as fn
from .. import debug as debug
__all__ = ['LinearRegionItem']
@ -140,12 +140,11 @@ class LinearRegionItem(UIGraphicsItem):
return br.normalized()
def paint(self, p, *args):
#prof = debug.Profiler('LinearRegionItem.paint')
profiler = debug.Profiler()
UIGraphicsItem.paint(self, p, *args)
p.setBrush(self.currentBrush)
p.setPen(fn.mkPen(None))
p.drawRect(self.boundingRect())
#prof.finish()
def dataBounds(self, axis, frac=1.0, orthoRange=None):
if axis == self.orientation:

View File

@ -1,17 +1,17 @@
from pyqtgraph.Qt import QtGui, QtCore
from ..Qt import QtGui, QtCore
try:
from pyqtgraph.Qt import QtOpenGL
from ..Qt import QtOpenGL
HAVE_OPENGL = True
except:
HAVE_OPENGL = False
import numpy as np
from .GraphicsObject import GraphicsObject
import pyqtgraph.functions as fn
from pyqtgraph import debug
from pyqtgraph.Point import Point
import pyqtgraph as pg
from .. import functions as fn
from ..Point import Point
import struct, sys
from .. import getConfigOption
from .. import debug
__all__ = ['PlotCurveItem']
class PlotCurveItem(GraphicsObject):
@ -53,9 +53,6 @@ class PlotCurveItem(GraphicsObject):
"""
GraphicsObject.__init__(self, kargs.get('parent', None))
self.clear()
self.path = None
self.fillPath = None
self._boundsCache = [None, None]
## this is disastrous for performance.
#self.setCacheMode(QtGui.QGraphicsItem.DeviceCoordinateCache)
@ -68,8 +65,9 @@ class PlotCurveItem(GraphicsObject):
'brush': None,
'stepMode': False,
'name': None,
'antialias': pg.getConfigOption('antialias'),\
'antialias': getConfigOption('antialias'),
'connect': 'all',
'mouseWidth': 8, # width of shape responding to mouse click
}
self.setClickable(kargs.get('clickable', False))
self.setData(*args, **kargs)
@ -80,9 +78,20 @@ class PlotCurveItem(GraphicsObject):
return ints
return interface in ints
def setClickable(self, s):
"""Sets whether the item responds to mouse clicks."""
def name(self):
return self.opts.get('name', None)
def setClickable(self, s, width=None):
"""Sets whether the item responds to mouse clicks.
The *width* argument specifies the width in pixels orthogonal to the
curve that will respond to a mouse click.
"""
self.clickable = s
if width is not None:
self.opts['mouseWidth'] = width
self._mouseShape = None
self._boundingRect = None
def getData(self):
@ -148,6 +157,8 @@ class PlotCurveItem(GraphicsObject):
w += pen.widthF()*0.7072
if spen is not None and spen.isCosmetic() and spen.style() != QtCore.Qt.NoPen:
w = max(w, spen.widthF()*0.7072)
if self.clickable:
w = max(w, self.opts['mouseWidth']//2 + 1)
return w
def boundingRect(self):
@ -171,6 +182,7 @@ class PlotCurveItem(GraphicsObject):
#px += self._maxSpotWidth * 0.5
#py += self._maxSpotWidth * 0.5
self._boundingRect = QtCore.QRectF(xmn-px, ymn-py, (2*px)+xmx-xmn, (2*py)+ymx-ymn)
return self._boundingRect
def viewTransformChanged(self):
@ -281,7 +293,7 @@ class PlotCurveItem(GraphicsObject):
self.updateData(*args, **kargs)
def updateData(self, *args, **kargs):
prof = debug.Profiler('PlotCurveItem.updateData', disabled=True)
profiler = debug.Profiler()
if len(args) == 1:
kargs['y'] = args[0]
@ -304,7 +316,7 @@ class PlotCurveItem(GraphicsObject):
if 'complex' in str(data.dtype):
raise Exception("Can not plot complex data types.")
prof.mark("data checks")
profiler("data checks")
#self.setCacheMode(QtGui.QGraphicsItem.NoCache) ## Disabling and re-enabling the cache works around a bug in Qt 4.6 causing the cached results to display incorrectly
## Test this bug with test_PlotWidget and zoom in on the animated plot
@ -314,7 +326,7 @@ class PlotCurveItem(GraphicsObject):
self.yData = kargs['y'].view(np.ndarray)
self.xData = kargs['x'].view(np.ndarray)
prof.mark('copy')
profiler('copy')
if 'stepMode' in kargs:
self.opts['stepMode'] = kargs['stepMode']
@ -328,6 +340,7 @@ class PlotCurveItem(GraphicsObject):
self.path = None
self.fillPath = None
self._mouseShape = None
#self.xDisp = self.yDisp = None
if 'name' in kargs:
@ -346,12 +359,11 @@ class PlotCurveItem(GraphicsObject):
self.opts['antialias'] = kargs['antialias']
prof.mark('set')
profiler('set')
self.update()
prof.mark('update')
profiler('update')
self.sigPlotChanged.emit(self)
prof.mark('emit')
prof.finish()
profiler('emit')
def generatePath(self, x, y):
if self.opts['stepMode']:
@ -377,35 +389,31 @@ class PlotCurveItem(GraphicsObject):
return path
def shape(self):
def getPath(self):
if self.path is None:
try:
self.path = self.generatePath(*self.getData())
except:
x,y = self.getData()
if x is None or len(x) == 0 or y is None or len(y) == 0:
return QtGui.QPainterPath()
self.path = self.generatePath(*self.getData())
self.fillPath = None
self._mouseShape = None
return self.path
@pg.debug.warnOnException ## raising an exception here causes crash
@debug.warnOnException ## raising an exception here causes crash
def paint(self, p, opt, widget):
prof = debug.Profiler('PlotCurveItem.paint '+str(id(self)), disabled=True)
profiler = debug.Profiler()
if self.xData is None:
return
if HAVE_OPENGL and pg.getConfigOption('enableExperimental') and isinstance(widget, QtOpenGL.QGLWidget):
if HAVE_OPENGL and getConfigOption('enableExperimental') and isinstance(widget, QtOpenGL.QGLWidget):
self.paintGL(p, opt, widget)
return
x = None
y = None
if self.path is None:
x,y = self.getData()
if x is None or len(x) == 0 or y is None or len(y) == 0:
return
self.path = self.generatePath(x,y)
self.fillPath = None
path = self.getPath()
path = self.path
prof.mark('generate path')
profiler('generate path')
if self._exportOpts is not False:
aa = self._exportOpts.get('antialias', True)
@ -426,9 +434,9 @@ class PlotCurveItem(GraphicsObject):
p2.closeSubpath()
self.fillPath = p2
prof.mark('generate fill path')
profiler('generate fill path')
p.fillPath(self.fillPath, self.opts['brush'])
prof.mark('draw fill path')
profiler('draw fill path')
sp = fn.mkPen(self.opts['shadowPen'])
cp = fn.mkPen(self.opts['pen'])
@ -451,10 +459,9 @@ class PlotCurveItem(GraphicsObject):
p.drawPath(path)
p.setPen(cp)
p.drawPath(path)
prof.mark('drawPath')
profiler('drawPath')
#print "Render hints:", int(p.renderHints())
prof.finish()
#p.setPen(QtGui.QPen(QtGui.QColor(255,0,0)))
#p.drawRect(self.boundingRect())
@ -524,15 +531,38 @@ class PlotCurveItem(GraphicsObject):
self.xDisp = None ## display values (after log / fft)
self.yDisp = None
self.path = None
self.fillPath = None
self._mouseShape = None
self._mouseBounds = None
self._boundsCache = [None, None]
#del self.xData, self.yData, self.xDisp, self.yDisp, self.path
def mouseShape(self):
"""
Return a QPainterPath representing the clickable shape of the curve
"""
if self._mouseShape is None:
view = self.getViewBox()
if view is None:
return QtGui.QPainterPath()
stroker = QtGui.QPainterPathStroker()
path = self.getPath()
path = self.mapToItem(view, path)
stroker.setWidth(self.opts['mouseWidth'])
mousePath = stroker.createStroke(path)
self._mouseShape = self.mapFromItem(view, mousePath)
return self._mouseShape
def mouseClickEvent(self, ev):
if not self.clickable or ev.button() != QtCore.Qt.LeftButton:
return
if self.mouseShape().contains(ev.pos()):
ev.accept()
self.sigClicked.emit(self)
class ROIPlotItem(PlotCurveItem):
"""Plot curve that monitors an ROI and image for changes to automatically replot."""
def __init__(self, roi, data, img, axes=(0,1), xVals=None, color=None):

View File

@ -1,12 +1,12 @@
import pyqtgraph.metaarray as metaarray
from pyqtgraph.Qt import QtCore
from .. import metaarray as metaarray
from ..Qt import QtCore
from .GraphicsObject import GraphicsObject
from .PlotCurveItem import PlotCurveItem
from .ScatterPlotItem import ScatterPlotItem
import numpy as np
import pyqtgraph.functions as fn
import pyqtgraph.debug as debug
import pyqtgraph as pg
from .. import functions as fn
from .. import debug as debug
from .. import getConfigOption
class PlotDataItem(GraphicsObject):
"""
@ -152,7 +152,7 @@ class PlotDataItem(GraphicsObject):
'symbolBrush': (50, 50, 150),
'pxMode': True,
'antialias': pg.getConfigOption('antialias'),
'antialias': getConfigOption('antialias'),
'pointMode': None,
'downsample': 1,
@ -170,6 +170,9 @@ class PlotDataItem(GraphicsObject):
return ints
return interface in ints
def name(self):
return self.opts.get('name', None)
def boundingRect(self):
return QtCore.QRectF() ## let child items handle this
@ -333,7 +336,7 @@ class PlotDataItem(GraphicsObject):
See :func:`__init__() <pyqtgraph.PlotDataItem.__init__>` for details; it accepts the same arguments.
"""
#self.clear()
prof = debug.Profiler('PlotDataItem.setData (0x%x)' % id(self), disabled=True)
profiler = debug.Profiler()
y = None
x = None
if len(args) == 1:
@ -383,7 +386,7 @@ class PlotDataItem(GraphicsObject):
if 'y' in kargs:
y = kargs['y']
prof.mark('interpret data')
profiler('interpret data')
## pull in all style arguments.
## Use self.opts to fill in anything not present in kargs.
@ -432,10 +435,10 @@ class PlotDataItem(GraphicsObject):
self.xClean = self.yClean = None
self.xDisp = None
self.yDisp = None
prof.mark('set data')
profiler('set data')
self.updateItems()
prof.mark('update items')
profiler('update items')
self.informViewBoundsChanged()
#view = self.getViewBox()
@ -443,9 +446,7 @@ class PlotDataItem(GraphicsObject):
#view.itemBoundsChanged(self) ## inform view so it can update its range if it wants
self.sigPlotChanged.emit(self)
prof.mark('emit')
prof.finish()
profiler('emit')
def updateItems(self):

View File

@ -16,16 +16,16 @@ This class is very heavily featured:
- Control panel with a huge feature set including averaging, decimation,
display, power spectrum, svg/png export, plot linking, and more.
"""
from pyqtgraph.Qt import QtGui, QtCore, QtSvg, USE_PYSIDE
import pyqtgraph.pixmaps
from ...Qt import QtGui, QtCore, QtSvg, USE_PYSIDE
from ... import pixmaps
if USE_PYSIDE:
from .plotConfigTemplate_pyside import *
else:
from .plotConfigTemplate_pyqt import *
import pyqtgraph.functions as fn
from pyqtgraph.widgets.FileDialog import FileDialog
from ... import functions as fn
from ...widgets.FileDialog import FileDialog
import weakref
import numpy as np
import os
@ -37,7 +37,7 @@ from .. LegendItem import LegendItem
from .. GraphicsWidget import GraphicsWidget
from .. ButtonItem import ButtonItem
from .. InfiniteLine import InfiniteLine
from pyqtgraph.WidgetGroup import WidgetGroup
from ...WidgetGroup import WidgetGroup
__all__ = ['PlotItem']
@ -129,7 +129,7 @@ class PlotItem(GraphicsWidget):
path = os.path.dirname(__file__)
#self.autoImageFile = os.path.join(path, 'auto.png')
#self.lockImageFile = os.path.join(path, 'lock.png')
self.autoBtn = ButtonItem(pyqtgraph.pixmaps.getPixmap('auto'), 14, self)
self.autoBtn = ButtonItem(pixmaps.getPixmap('auto'), 14, self)
self.autoBtn.mode = 'auto'
self.autoBtn.clicked.connect(self.autoBtnClicked)
#self.autoBtn.hide()
@ -339,9 +339,8 @@ class PlotItem(GraphicsWidget):
self.ctrl.gridAlphaSlider.setValue(v)
#def paint(self, *args):
#prof = debug.Profiler('PlotItem.paint', disabled=True)
#prof = debug.Profiler()
#QtGui.QGraphicsWidget.paint(self, *args)
#prof.finish()
## bad idea.
#def __getattr__(self, attr): ## wrap ms
@ -515,7 +514,9 @@ class PlotItem(GraphicsWidget):
if 'ignoreBounds' in kargs:
vbargs['ignoreBounds'] = kargs['ignoreBounds']
self.vb.addItem(item, *args, **vbargs)
name = None
if hasattr(item, 'implements') and item.implements('plotData'):
name = item.name()
self.dataItems.append(item)
#self.plotChanged()
@ -548,7 +549,7 @@ class PlotItem(GraphicsWidget):
#c.connect(c, QtCore.SIGNAL('plotChanged'), self.plotChanged)
#item.sigPlotChanged.connect(self.plotChanged)
#self.plotChanged()
name = kargs.get('name', getattr(item, 'opts', {}).get('name', None))
#name = kargs.get('name', getattr(item, 'opts', {}).get('name', None))
if name is not None and hasattr(self, 'legend') and self.legend is not None:
self.legend.addItem(item, name=name)

View File

@ -2,8 +2,8 @@
# Form implementation generated from reading ui file './pyqtgraph/graphicsItems/PlotItem/plotConfigTemplate.ui'
#
# Created: Mon Jul 1 23:21:08 2013
# by: PyQt4 UI code generator 4.9.3
# Created: Mon Dec 23 10:10:51 2013
# by: PyQt4 UI code generator 4.10
#
# WARNING! All changes made in this file will be lost!
@ -12,7 +12,16 @@ from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_Form(object):
def setupUi(self, Form):
@ -139,35 +148,35 @@ class Ui_Form(object):
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
self.averageGroup.setToolTip(QtGui.QApplication.translate("Form", "Display averages of the curves displayed in this plot. The parameter list allows you to choose parameters to average over (if any are available).", None, QtGui.QApplication.UnicodeUTF8))
self.averageGroup.setTitle(QtGui.QApplication.translate("Form", "Average", None, QtGui.QApplication.UnicodeUTF8))
self.clipToViewCheck.setToolTip(QtGui.QApplication.translate("Form", "Plot only the portion of each curve that is visible. This assumes X values are uniformly spaced.", None, QtGui.QApplication.UnicodeUTF8))
self.clipToViewCheck.setText(QtGui.QApplication.translate("Form", "Clip to View", None, QtGui.QApplication.UnicodeUTF8))
self.maxTracesCheck.setToolTip(QtGui.QApplication.translate("Form", "If multiple curves are displayed in this plot, check this box to limit the number of traces that are displayed.", None, QtGui.QApplication.UnicodeUTF8))
self.maxTracesCheck.setText(QtGui.QApplication.translate("Form", "Max Traces:", None, QtGui.QApplication.UnicodeUTF8))
self.downsampleCheck.setText(QtGui.QApplication.translate("Form", "Downsample", None, QtGui.QApplication.UnicodeUTF8))
self.peakRadio.setToolTip(QtGui.QApplication.translate("Form", "Downsample by drawing a saw wave that follows the min and max of the original data. This method produces the best visual representation of the data but is slower.", None, QtGui.QApplication.UnicodeUTF8))
self.peakRadio.setText(QtGui.QApplication.translate("Form", "Peak", None, QtGui.QApplication.UnicodeUTF8))
self.maxTracesSpin.setToolTip(QtGui.QApplication.translate("Form", "If multiple curves are displayed in this plot, check \"Max Traces\" and set this value to limit the number of traces that are displayed.", None, QtGui.QApplication.UnicodeUTF8))
self.forgetTracesCheck.setToolTip(QtGui.QApplication.translate("Form", "If MaxTraces is checked, remove curves from memory after they are hidden (saves memory, but traces can not be un-hidden).", None, QtGui.QApplication.UnicodeUTF8))
self.forgetTracesCheck.setText(QtGui.QApplication.translate("Form", "Forget hidden traces", None, QtGui.QApplication.UnicodeUTF8))
self.meanRadio.setToolTip(QtGui.QApplication.translate("Form", "Downsample by taking the mean of N samples.", None, QtGui.QApplication.UnicodeUTF8))
self.meanRadio.setText(QtGui.QApplication.translate("Form", "Mean", None, QtGui.QApplication.UnicodeUTF8))
self.subsampleRadio.setToolTip(QtGui.QApplication.translate("Form", "Downsample by taking the first of N samples. This method is fastest and least accurate.", None, QtGui.QApplication.UnicodeUTF8))
self.subsampleRadio.setText(QtGui.QApplication.translate("Form", "Subsample", None, QtGui.QApplication.UnicodeUTF8))
self.autoDownsampleCheck.setToolTip(QtGui.QApplication.translate("Form", "Automatically downsample data based on the visible range. This assumes X values are uniformly spaced.", None, QtGui.QApplication.UnicodeUTF8))
self.autoDownsampleCheck.setText(QtGui.QApplication.translate("Form", "Auto", None, QtGui.QApplication.UnicodeUTF8))
self.downsampleSpin.setToolTip(QtGui.QApplication.translate("Form", "Downsample data before plotting. (plot every Nth sample)", None, QtGui.QApplication.UnicodeUTF8))
self.downsampleSpin.setSuffix(QtGui.QApplication.translate("Form", "x", None, QtGui.QApplication.UnicodeUTF8))
self.fftCheck.setText(QtGui.QApplication.translate("Form", "Power Spectrum (FFT)", None, QtGui.QApplication.UnicodeUTF8))
self.logXCheck.setText(QtGui.QApplication.translate("Form", "Log X", None, QtGui.QApplication.UnicodeUTF8))
self.logYCheck.setText(QtGui.QApplication.translate("Form", "Log Y", None, QtGui.QApplication.UnicodeUTF8))
self.pointsGroup.setTitle(QtGui.QApplication.translate("Form", "Points", None, QtGui.QApplication.UnicodeUTF8))
self.autoPointsCheck.setText(QtGui.QApplication.translate("Form", "Auto", None, QtGui.QApplication.UnicodeUTF8))
self.xGridCheck.setText(QtGui.QApplication.translate("Form", "Show X Grid", None, QtGui.QApplication.UnicodeUTF8))
self.yGridCheck.setText(QtGui.QApplication.translate("Form", "Show Y Grid", None, QtGui.QApplication.UnicodeUTF8))
self.label.setText(QtGui.QApplication.translate("Form", "Opacity", None, QtGui.QApplication.UnicodeUTF8))
self.alphaGroup.setTitle(QtGui.QApplication.translate("Form", "Alpha", None, QtGui.QApplication.UnicodeUTF8))
self.autoAlphaCheck.setText(QtGui.QApplication.translate("Form", "Auto", None, QtGui.QApplication.UnicodeUTF8))
Form.setWindowTitle(_translate("Form", "Form", None))
self.averageGroup.setToolTip(_translate("Form", "Display averages of the curves displayed in this plot. The parameter list allows you to choose parameters to average over (if any are available).", None))
self.averageGroup.setTitle(_translate("Form", "Average", None))
self.clipToViewCheck.setToolTip(_translate("Form", "Plot only the portion of each curve that is visible. This assumes X values are uniformly spaced.", None))
self.clipToViewCheck.setText(_translate("Form", "Clip to View", None))
self.maxTracesCheck.setToolTip(_translate("Form", "If multiple curves are displayed in this plot, check this box to limit the number of traces that are displayed.", None))
self.maxTracesCheck.setText(_translate("Form", "Max Traces:", None))
self.downsampleCheck.setText(_translate("Form", "Downsample", None))
self.peakRadio.setToolTip(_translate("Form", "Downsample by drawing a saw wave that follows the min and max of the original data. This method produces the best visual representation of the data but is slower.", None))
self.peakRadio.setText(_translate("Form", "Peak", None))
self.maxTracesSpin.setToolTip(_translate("Form", "If multiple curves are displayed in this plot, check \"Max Traces\" and set this value to limit the number of traces that are displayed.", None))
self.forgetTracesCheck.setToolTip(_translate("Form", "If MaxTraces is checked, remove curves from memory after they are hidden (saves memory, but traces can not be un-hidden).", None))
self.forgetTracesCheck.setText(_translate("Form", "Forget hidden traces", None))
self.meanRadio.setToolTip(_translate("Form", "Downsample by taking the mean of N samples.", None))
self.meanRadio.setText(_translate("Form", "Mean", None))
self.subsampleRadio.setToolTip(_translate("Form", "Downsample by taking the first of N samples. This method is fastest and least accurate.", None))
self.subsampleRadio.setText(_translate("Form", "Subsample", None))
self.autoDownsampleCheck.setToolTip(_translate("Form", "Automatically downsample data based on the visible range. This assumes X values are uniformly spaced.", None))
self.autoDownsampleCheck.setText(_translate("Form", "Auto", None))
self.downsampleSpin.setToolTip(_translate("Form", "Downsample data before plotting. (plot every Nth sample)", None))
self.downsampleSpin.setSuffix(_translate("Form", "x", None))
self.fftCheck.setText(_translate("Form", "Power Spectrum (FFT)", None))
self.logXCheck.setText(_translate("Form", "Log X", None))
self.logYCheck.setText(_translate("Form", "Log Y", None))
self.pointsGroup.setTitle(_translate("Form", "Points", None))
self.autoPointsCheck.setText(_translate("Form", "Auto", None))
self.xGridCheck.setText(_translate("Form", "Show X Grid", None))
self.yGridCheck.setText(_translate("Form", "Show Y Grid", None))
self.label.setText(_translate("Form", "Opacity", None))
self.alphaGroup.setTitle(_translate("Form", "Alpha", None))
self.autoAlphaCheck.setText(_translate("Form", "Auto", None))

View File

@ -2,8 +2,8 @@
# Form implementation generated from reading ui file './pyqtgraph/graphicsItems/PlotItem/plotConfigTemplate.ui'
#
# Created: Mon Jul 1 23:21:08 2013
# by: pyside-uic 0.2.13 running on PySide 1.1.2
# Created: Mon Dec 23 10:10:52 2013
# by: pyside-uic 0.2.14 running on PySide 1.1.2
#
# WARNING! All changes made in this file will be lost!

View File

@ -12,16 +12,16 @@ The ROI class is meant to serve as the base for more specific types; see several
of how to build an ROI at the bottom of the file.
"""
from pyqtgraph.Qt import QtCore, QtGui
from ..Qt import QtCore, QtGui
#if not hasattr(QtCore, 'Signal'):
#QtCore.Signal = QtCore.pyqtSignal
import numpy as np
from numpy.linalg import norm
import scipy.ndimage as ndimage
from pyqtgraph.Point import *
from pyqtgraph.SRTTransform import SRTTransform
from ..Point import *
from ..SRTTransform import SRTTransform
from math import cos, sin
import pyqtgraph.functions as fn
from .. import functions as fn
from .GraphicsObject import GraphicsObject
from .UIGraphicsItem import UIGraphicsItem
@ -1203,10 +1203,6 @@ class Handle(UIGraphicsItem):
def getMenu(self):
return self.menu
def getContextMenus(self, event):
return [self.menu]
def raiseContextMenu(self, ev):
menu = self.scene().addParentContextMenus(self, self.getMenu(), ev)

View File

@ -1,10 +1,10 @@
from pyqtgraph.Qt import QtGui, QtCore
from ..Qt import QtGui, QtCore
from .GraphicsObject import *
from .GraphicsWidgetAnchor import *
from .TextItem import TextItem
import numpy as np
import pyqtgraph.functions as fn
import pyqtgraph as pg
from .. import functions as fn
from .. import getConfigOption
__all__ = ['ScaleBar']
@ -19,7 +19,7 @@ class ScaleBar(GraphicsObject, GraphicsWidgetAnchor):
self.setAcceptedMouseButtons(QtCore.Qt.NoButton)
if brush is None:
brush = pg.getConfigOption('foreground')
brush = getConfigOption('foreground')
self.brush = fn.mkBrush(brush)
self.pen = fn.mkPen(pen)
self._width = width

View File

@ -1,14 +1,14 @@
from pyqtgraph.Qt import QtGui, QtCore, USE_PYSIDE
from pyqtgraph.Point import Point
import pyqtgraph.functions as fn
from ..Qt import QtGui, QtCore, USE_PYSIDE
from ..Point import Point
from .. import functions as fn
from .GraphicsItem import GraphicsItem
from .GraphicsObject import GraphicsObject
import numpy as np
import weakref
import pyqtgraph.debug as debug
from pyqtgraph.pgcollections import OrderedDict
import pyqtgraph as pg
#import pyqtgraph as pg
from .. import getConfigOption
from .. import debug as debug
from ..pgcollections import OrderedDict
from .. import debug
__all__ = ['ScatterPlotItem', 'SpotItem']
@ -219,7 +219,7 @@ class ScatterPlotItem(GraphicsObject):
"""
Accepts the same arguments as setData()
"""
prof = debug.Profiler('ScatterPlotItem.__init__', disabled=True)
profiler = debug.Profiler()
GraphicsObject.__init__(self)
self.picture = None # QPicture used for rendering when pxmode==False
@ -233,17 +233,17 @@ class ScatterPlotItem(GraphicsObject):
self.opts = {
'pxMode': True,
'useCache': True, ## If useCache is False, symbols are re-drawn on every paint.
'antialias': pg.getConfigOption('antialias'),
'antialias': getConfigOption('antialias'),
'name': None,
}
self.setPen(200,200,200, update=False)
self.setBrush(100,100,150, update=False)
self.setSymbol('o', update=False)
self.setSize(7, update=False)
prof.mark('1')
profiler()
self.setData(*args, **kargs)
prof.mark('setData')
prof.finish()
profiler('setData')
#self.setCacheMode(self.DeviceCoordinateCache)
@ -282,6 +282,8 @@ class ScatterPlotItem(GraphicsObject):
*antialias* Whether to draw symbols with antialiasing. Note that if pxMode is True, symbols are
always rendered with antialiasing (since the rendered symbols can be cached, this
incurs very little performance cost)
*name* The name of this item. Names are used for automatically
generating LegendItem entries and by some exporters.
====================== ===============================================================================================
"""
oldData = self.data ## this causes cached pixmaps to be preserved while new data is registered.
@ -411,6 +413,9 @@ class ScatterPlotItem(GraphicsObject):
return ints
return interface in ints
def name(self):
return self.opts.get('name', None)
def setPen(self, *args, **kargs):
"""Set the pen(s) used to draw the outline around each spot.
If a list or array is provided, then the pen for each spot will be set separately.
@ -688,7 +693,7 @@ class ScatterPlotItem(GraphicsObject):
GraphicsObject.setExportMode(self, *args, **kwds)
self.invalidate()
@pg.debug.warnOnException ## raising an exception here causes crash
@debug.warnOnException ## raising an exception here causes crash
def paint(self, p, *args):
#p.setPen(fn.mkPen('r'))

View File

@ -1,7 +1,7 @@
from pyqtgraph.Qt import QtCore, QtGui
import pyqtgraph as pg
from ..Qt import QtCore, QtGui
from ..Point import Point
from .UIGraphicsItem import *
import pyqtgraph.functions as fn
from .. import functions as fn
class TextItem(UIGraphicsItem):
"""
@ -27,7 +27,7 @@ class TextItem(UIGraphicsItem):
#*angle* Angle in degrees to rotate text (note that the rotation assigned in this item's
#transformation will be ignored)
self.anchor = pg.Point(anchor)
self.anchor = Point(anchor)
#self.angle = 0
UIGraphicsItem.__init__(self)
self.textItem = QtGui.QGraphicsTextItem()
@ -38,13 +38,13 @@ class TextItem(UIGraphicsItem):
self.setText(text, color)
else:
self.setHtml(html)
self.fill = pg.mkBrush(fill)
self.border = pg.mkPen(border)
self.fill = fn.mkBrush(fill)
self.border = fn.mkPen(border)
self.rotate(angle)
self.setFlag(self.ItemIgnoresTransformations) ## This is required to keep the text unscaled inside the viewport
def setText(self, text, color=(200,200,200)):
color = pg.mkColor(color)
color = fn.mkColor(color)
self.textItem.setDefaultTextColor(color)
self.textItem.setPlainText(text)
self.updateText()
@ -89,7 +89,7 @@ class TextItem(UIGraphicsItem):
#br = self.textItem.mapRectToParent(self.textItem.boundingRect())
self.textItem.setPos(0,0)
br = self.textItem.boundingRect()
apos = self.textItem.mapToParent(pg.Point(br.width()*self.anchor.x(), br.height()*self.anchor.y()))
apos = self.textItem.mapToParent(Point(br.width()*self.anchor.x(), br.height()*self.anchor.y()))
#print br, apos
self.textItem.setPos(-apos.x(), -apos.y())

View File

@ -1,4 +1,4 @@
from pyqtgraph.Qt import QtGui, QtCore, USE_PYSIDE
from ..Qt import QtGui, QtCore, USE_PYSIDE
import weakref
from .GraphicsObject import GraphicsObject
if not USE_PYSIDE:

View File

@ -3,8 +3,8 @@ if __name__ == '__main__':
path = os.path.abspath(os.path.dirname(__file__))
sys.path.insert(0, os.path.join(path, '..', '..'))
from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph.functions as fn
from ..Qt import QtGui, QtCore
from .. import functions as fn
import weakref
from .UIGraphicsItem import UIGraphicsItem
@ -97,17 +97,3 @@ class VTickGroup(UIGraphicsItem):
p.drawPath(self.path)
if __name__ == '__main__':
app = QtGui.QApplication([])
import pyqtgraph as pg
vt = VTickGroup([1,3,4,7,9], [0.8, 1.0])
p = pg.plot()
p.addItem(vt)
if sys.flags.interactive == 0:
app.exec_()

View File

@ -1,15 +1,15 @@
from pyqtgraph.Qt import QtGui, QtCore
from pyqtgraph.python2_3 import sortList
from ...Qt import QtGui, QtCore
from ...python2_3 import sortList
import numpy as np
from pyqtgraph.Point import Point
import pyqtgraph.functions as fn
from ...Point import Point
from ... import functions as fn
from .. ItemGroup import ItemGroup
from .. GraphicsWidget import GraphicsWidget
from pyqtgraph.GraphicsScene import GraphicsScene
import pyqtgraph
from ...GraphicsScene import GraphicsScene
import weakref
from copy import deepcopy
import pyqtgraph.debug as debug
from ... import debug as debug
from ... import getConfigOption
__all__ = ['ViewBox']
@ -113,7 +113,7 @@ class ViewBox(GraphicsWidget):
## a name string indicates that the view *should* link to another, but no view with that name exists yet.
'mouseEnabled': [enableMouse, enableMouse],
'mouseMode': ViewBox.PanMode if pyqtgraph.getConfigOption('leftButtonPan') else ViewBox.RectMode,
'mouseMode': ViewBox.PanMode if getConfigOption('leftButtonPan') else ViewBox.RectMode,
'enableMenu': enableMenu,
'wheelScaleFactor': -1.0 / 8.0,
@ -1067,31 +1067,15 @@ class ViewBox(GraphicsWidget):
self.raiseContextMenu(ev)
def raiseContextMenu(self, ev):
#print "viewbox.raiseContextMenu called."
#menu = self.getMenu(ev)
menu = self.getMenu(ev)
self.scene().addParentContextMenus(self, menu, ev)
#print "2:", [str(a.text()) for a in self.menu.actions()]
pos = ev.screenPos()
#pos2 = ev.scenePos()
#print "3:", [str(a.text()) for a in self.menu.actions()]
#self.sigActionPositionChanged.emit(pos2)
menu.popup(QtCore.QPoint(pos.x(), pos.y()))
#print "4:", [str(a.text()) for a in self.menu.actions()]
menu.popup(ev.screenPos().toPoint())
def getMenu(self, ev):
self._menuCopy = self.menu.copy() ## temporary storage to prevent menu disappearing
return self._menuCopy
return self.menu
def getContextMenus(self, event):
if self.menuEnabled():
return self.menu.subMenus()
else:
return None
#return [self.getMenu(event)]
return self.menu.actions() if self.menuEnabled() else []
def mouseDragEvent(self, ev, axis=None):
## if axis is specified, event will only affect that axis.
@ -1221,7 +1205,7 @@ class ViewBox(GraphicsWidget):
[[xmin, xmax], [ymin, ymax]]
Values may be None if there are no specific bounds for an axis.
"""
prof = debug.Profiler('updateAutoRange', disabled=True)
profiler = debug.Profiler()
if items is None:
items = self.addedItems
@ -1298,7 +1282,7 @@ class ViewBox(GraphicsWidget):
range[0] = [min(bounds.left(), range[0][0]), max(bounds.right(), range[0][1])]
else:
range[0] = [bounds.left(), bounds.right()]
prof.mark('2')
profiler()
#print "range", range
@ -1323,9 +1307,6 @@ class ViewBox(GraphicsWidget):
range[1][0] = min(range[1][0], bounds.top() - px*pxSize)
range[1][1] = max(range[1][1], bounds.bottom() + px*pxSize)
#print "final range", range
prof.finish()
return range
def childrenBoundingRect(self, *args, **kwds):

View File

@ -1,6 +1,6 @@
from pyqtgraph.Qt import QtCore, QtGui, USE_PYSIDE
from pyqtgraph.python2_3 import asUnicode
from pyqtgraph.WidgetGroup import WidgetGroup
from ...Qt import QtCore, QtGui, USE_PYSIDE
from ...python2_3 import asUnicode
from ...WidgetGroup import WidgetGroup
if USE_PYSIDE:
from .axisCtrlTemplate_pyside import Ui_Form as AxisCtrlTemplate
@ -88,22 +88,6 @@ class ViewBoxMenu(QtGui.QMenu):
self.updateState()
def copy(self):
m = QtGui.QMenu()
for sm in self.subMenus():
if isinstance(sm, QtGui.QMenu):
m.addMenu(sm)
else:
m.addAction(sm)
m.setTitle(self.title())
return m
def subMenus(self):
if not self.valid:
self.updateState()
return [self.viewAll] + self.axes + [self.leftMenu]
def setExportMethods(self, methods):
self.exportMethods = methods
self.export.clear()
@ -159,6 +143,10 @@ class ViewBoxMenu(QtGui.QMenu):
self.ctrl[1].invertCheck.setChecked(state['yInverted'])
self.valid = True
def popup(self, *args):
if not self.valid:
self.updateState()
QtGui.QMenu.popup(self, *args)
def autoRange(self):
self.view().autoRange() ## don't let signal call this directly--it'll add an unwanted argument

View File

@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file './graphicsItems/ViewBox/axisCtrlTemplate.ui'
# Form implementation generated from reading ui file './pyqtgraph/graphicsItems/ViewBox/axisCtrlTemplate.ui'
#
# Created: Sun Sep 9 14:41:31 2012
# by: PyQt4 UI code generator 4.9.1
# Created: Mon Dec 23 10:10:51 2013
# by: PyQt4 UI code generator 4.10
#
# WARNING! All changes made in this file will be lost!
@ -12,7 +12,16 @@ from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_Form(object):
def setupUi(self, Form):
@ -69,25 +78,25 @@ class Ui_Form(object):
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
self.label.setText(QtGui.QApplication.translate("Form", "Link Axis:", None, QtGui.QApplication.UnicodeUTF8))
self.linkCombo.setToolTip(QtGui.QApplication.translate("Form", "<html><head/><body><p>Links this axis with another view. When linked, both views will display the same data range.</p></body></html>", None, QtGui.QApplication.UnicodeUTF8))
self.autoPercentSpin.setToolTip(QtGui.QApplication.translate("Form", "<html><head/><body><p>Percent of data to be visible when auto-scaling. It may be useful to decrease this value for data with spiky noise.</p></body></html>", None, QtGui.QApplication.UnicodeUTF8))
self.autoPercentSpin.setSuffix(QtGui.QApplication.translate("Form", "%", None, QtGui.QApplication.UnicodeUTF8))
self.autoRadio.setToolTip(QtGui.QApplication.translate("Form", "<html><head/><body><p>Automatically resize this axis whenever the displayed data is changed.</p></body></html>", None, QtGui.QApplication.UnicodeUTF8))
self.autoRadio.setText(QtGui.QApplication.translate("Form", "Auto", None, QtGui.QApplication.UnicodeUTF8))
self.manualRadio.setToolTip(QtGui.QApplication.translate("Form", "<html><head/><body><p>Set the range for this axis manually. This disables automatic scaling. </p></body></html>", None, QtGui.QApplication.UnicodeUTF8))
self.manualRadio.setText(QtGui.QApplication.translate("Form", "Manual", None, QtGui.QApplication.UnicodeUTF8))
self.minText.setToolTip(QtGui.QApplication.translate("Form", "<html><head/><body><p>Minimum value to display for this axis.</p></body></html>", None, QtGui.QApplication.UnicodeUTF8))
self.minText.setText(QtGui.QApplication.translate("Form", "0", None, QtGui.QApplication.UnicodeUTF8))
self.maxText.setToolTip(QtGui.QApplication.translate("Form", "<html><head/><body><p>Maximum value to display for this axis.</p></body></html>", None, QtGui.QApplication.UnicodeUTF8))
self.maxText.setText(QtGui.QApplication.translate("Form", "0", None, QtGui.QApplication.UnicodeUTF8))
self.invertCheck.setToolTip(QtGui.QApplication.translate("Form", "<html><head/><body><p>Inverts the display of this axis. (+y points downward instead of upward)</p></body></html>", None, QtGui.QApplication.UnicodeUTF8))
self.invertCheck.setText(QtGui.QApplication.translate("Form", "Invert Axis", None, QtGui.QApplication.UnicodeUTF8))
self.mouseCheck.setToolTip(QtGui.QApplication.translate("Form", "<html><head/><body><p>Enables mouse interaction (panning, scaling) for this axis.</p></body></html>", None, QtGui.QApplication.UnicodeUTF8))
self.mouseCheck.setText(QtGui.QApplication.translate("Form", "Mouse Enabled", None, QtGui.QApplication.UnicodeUTF8))
self.visibleOnlyCheck.setToolTip(QtGui.QApplication.translate("Form", "<html><head/><body><p>When checked, the axis will only auto-scale to data that is visible along the orthogonal axis.</p></body></html>", None, QtGui.QApplication.UnicodeUTF8))
self.visibleOnlyCheck.setText(QtGui.QApplication.translate("Form", "Visible Data Only", None, QtGui.QApplication.UnicodeUTF8))
self.autoPanCheck.setToolTip(QtGui.QApplication.translate("Form", "<html><head/><body><p>When checked, the axis will automatically pan to center on the current data, but the scale along this axis will not change.</p></body></html>", None, QtGui.QApplication.UnicodeUTF8))
self.autoPanCheck.setText(QtGui.QApplication.translate("Form", "Auto Pan Only", None, QtGui.QApplication.UnicodeUTF8))
Form.setWindowTitle(_translate("Form", "Form", None))
self.label.setText(_translate("Form", "Link Axis:", None))
self.linkCombo.setToolTip(_translate("Form", "<html><head/><body><p>Links this axis with another view. When linked, both views will display the same data range.</p></body></html>", None))
self.autoPercentSpin.setToolTip(_translate("Form", "<html><head/><body><p>Percent of data to be visible when auto-scaling. It may be useful to decrease this value for data with spiky noise.</p></body></html>", None))
self.autoPercentSpin.setSuffix(_translate("Form", "%", None))
self.autoRadio.setToolTip(_translate("Form", "<html><head/><body><p>Automatically resize this axis whenever the displayed data is changed.</p></body></html>", None))
self.autoRadio.setText(_translate("Form", "Auto", None))
self.manualRadio.setToolTip(_translate("Form", "<html><head/><body><p>Set the range for this axis manually. This disables automatic scaling. </p></body></html>", None))
self.manualRadio.setText(_translate("Form", "Manual", None))
self.minText.setToolTip(_translate("Form", "<html><head/><body><p>Minimum value to display for this axis.</p></body></html>", None))
self.minText.setText(_translate("Form", "0", None))
self.maxText.setToolTip(_translate("Form", "<html><head/><body><p>Maximum value to display for this axis.</p></body></html>", None))
self.maxText.setText(_translate("Form", "0", None))
self.invertCheck.setToolTip(_translate("Form", "<html><head/><body><p>Inverts the display of this axis. (+y points downward instead of upward)</p></body></html>", None))
self.invertCheck.setText(_translate("Form", "Invert Axis", None))
self.mouseCheck.setToolTip(_translate("Form", "<html><head/><body><p>Enables mouse interaction (panning, scaling) for this axis.</p></body></html>", None))
self.mouseCheck.setText(_translate("Form", "Mouse Enabled", None))
self.visibleOnlyCheck.setToolTip(_translate("Form", "<html><head/><body><p>When checked, the axis will only auto-scale to data that is visible along the orthogonal axis.</p></body></html>", None))
self.visibleOnlyCheck.setText(_translate("Form", "Visible Data Only", None))
self.autoPanCheck.setToolTip(_translate("Form", "<html><head/><body><p>When checked, the axis will automatically pan to center on the current data, but the scale along this axis will not change.</p></body></html>", None))
self.autoPanCheck.setText(_translate("Form", "Auto Pan Only", None))

View File

@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file './graphicsItems/ViewBox/axisCtrlTemplate.ui'
# Form implementation generated from reading ui file './pyqtgraph/graphicsItems/ViewBox/axisCtrlTemplate.ui'
#
# Created: Sun Sep 9 14:41:32 2012
# by: pyside-uic 0.2.13 running on PySide 1.1.0
# Created: Mon Dec 23 10:10:51 2013
# by: pyside-uic 0.2.14 running on PySide 1.1.2
#
# WARNING! All changes made in this file will be lost!

View File

@ -12,29 +12,29 @@ Widget used for displaying 2D or 3D data. Features:
- ROI plotting
- Image normalization through a variety of methods
"""
from pyqtgraph.Qt import QtCore, QtGui, USE_PYSIDE
from ..Qt import QtCore, QtGui, USE_PYSIDE
if USE_PYSIDE:
from .ImageViewTemplate_pyside import *
else:
from .ImageViewTemplate_pyqt import *
from pyqtgraph.graphicsItems.ImageItem import *
from pyqtgraph.graphicsItems.ROI import *
from pyqtgraph.graphicsItems.LinearRegionItem import *
from pyqtgraph.graphicsItems.InfiniteLine import *
from pyqtgraph.graphicsItems.ViewBox import *
from ..graphicsItems.ImageItem import *
from ..graphicsItems.ROI import *
from ..graphicsItems.LinearRegionItem import *
from ..graphicsItems.InfiniteLine import *
from ..graphicsItems.ViewBox import *
#from widgets import ROI
import sys
#from numpy import ndarray
import pyqtgraph.ptime as ptime
from .. import ptime as ptime
import numpy as np
import pyqtgraph.debug as debug
from .. import debug as debug
from pyqtgraph.SignalProxy import SignalProxy
from ..SignalProxy import SignalProxy
#try:
#import pyqtgraph.metaarray as metaarray
#from .. import metaarray as metaarray
#HAVE_METAARRAY = True
#except:
#HAVE_METAARRAY = False
@ -190,7 +190,7 @@ class ImageView(QtGui.QWidget):
image data.
================== =======================================================================
"""
prof = debug.Profiler('ImageView.setImage', disabled=True)
profiler = debug.Profiler()
if hasattr(img, 'implements') and img.implements('MetaArray'):
img = img.asarray()
@ -209,7 +209,7 @@ class ImageView(QtGui.QWidget):
else:
self.tVals = np.arange(img.shape[0])
prof.mark('1')
profiler()
if axes is None:
if img.ndim == 2:
@ -234,12 +234,8 @@ class ImageView(QtGui.QWidget):
for x in ['t', 'x', 'y', 'c']:
self.axes[x] = self.axes.get(x, None)
prof.mark('2')
self.imageDisp = None
prof.mark('3')
profiler()
self.currentIndex = 0
self.updateImage(autoHistogramRange=autoHistogramRange)
@ -250,8 +246,8 @@ class ImageView(QtGui.QWidget):
if self.ui.roiBtn.isChecked():
self.roiChanged()
prof.mark('4')
profiler()
if self.axes['t'] is not None:
#self.ui.roiPlot.show()
@ -271,7 +267,7 @@ class ImageView(QtGui.QWidget):
s.setBounds([start, stop])
#else:
#self.ui.roiPlot.hide()
prof.mark('5')
profiler()
self.imageItem.resetTransform()
if scale is not None:
@ -280,14 +276,14 @@ class ImageView(QtGui.QWidget):
self.imageItem.setPos(*pos)
if transform is not None:
self.imageItem.setTransform(transform)
prof.mark('6')
profiler()
if autoRange:
self.autoRange()
self.roiClicked()
prof.mark('7')
prof.finish()
profiler()
def play(self, rate):
"""Begin automatically stepping frames forward at the given rate (in fps).

View File

@ -233,18 +233,18 @@
<customwidget>
<class>PlotWidget</class>
<extends>QWidget</extends>
<header>pyqtgraph.widgets.PlotWidget</header>
<header>..widgets.PlotWidget</header>
<container>1</container>
</customwidget>
<customwidget>
<class>GraphicsView</class>
<extends>QGraphicsView</extends>
<header>pyqtgraph.widgets.GraphicsView</header>
<header>..widgets.GraphicsView</header>
</customwidget>
<customwidget>
<class>HistogramLUTWidget</class>
<extends>QGraphicsView</extends>
<header>pyqtgraph.widgets.HistogramLUTWidget</header>
<header>..widgets.HistogramLUTWidget</header>
</customwidget>
</customwidgets>
<resources/>

View File

@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file './imageview/ImageViewTemplate.ui'
# Form implementation generated from reading ui file './pyqtgraph/imageview/ImageViewTemplate.ui'
#
# Created: Sun Sep 9 14:41:30 2012
# by: PyQt4 UI code generator 4.9.1
# Created: Mon Dec 23 10:10:52 2013
# by: PyQt4 UI code generator 4.10
#
# WARNING! All changes made in this file will be lost!
@ -12,7 +12,16 @@ from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_Form(object):
def setupUi(self, Form):
@ -138,23 +147,23 @@ class Ui_Form(object):
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
self.roiBtn.setText(QtGui.QApplication.translate("Form", "ROI", None, QtGui.QApplication.UnicodeUTF8))
self.normBtn.setText(QtGui.QApplication.translate("Form", "Norm", None, QtGui.QApplication.UnicodeUTF8))
self.normGroup.setTitle(QtGui.QApplication.translate("Form", "Normalization", None, QtGui.QApplication.UnicodeUTF8))
self.normSubtractRadio.setText(QtGui.QApplication.translate("Form", "Subtract", None, QtGui.QApplication.UnicodeUTF8))
self.normDivideRadio.setText(QtGui.QApplication.translate("Form", "Divide", None, QtGui.QApplication.UnicodeUTF8))
self.label_5.setText(QtGui.QApplication.translate("Form", "Operation:", None, QtGui.QApplication.UnicodeUTF8))
self.label_3.setText(QtGui.QApplication.translate("Form", "Mean:", None, QtGui.QApplication.UnicodeUTF8))
self.label_4.setText(QtGui.QApplication.translate("Form", "Blur:", None, QtGui.QApplication.UnicodeUTF8))
self.normROICheck.setText(QtGui.QApplication.translate("Form", "ROI", None, QtGui.QApplication.UnicodeUTF8))
self.label_8.setText(QtGui.QApplication.translate("Form", "X", None, QtGui.QApplication.UnicodeUTF8))
self.label_9.setText(QtGui.QApplication.translate("Form", "Y", None, QtGui.QApplication.UnicodeUTF8))
self.label_10.setText(QtGui.QApplication.translate("Form", "T", None, QtGui.QApplication.UnicodeUTF8))
self.normOffRadio.setText(QtGui.QApplication.translate("Form", "Off", None, QtGui.QApplication.UnicodeUTF8))
self.normTimeRangeCheck.setText(QtGui.QApplication.translate("Form", "Time range", None, QtGui.QApplication.UnicodeUTF8))
self.normFrameCheck.setText(QtGui.QApplication.translate("Form", "Frame", None, QtGui.QApplication.UnicodeUTF8))
Form.setWindowTitle(_translate("Form", "Form", None))
self.roiBtn.setText(_translate("Form", "ROI", None))
self.normBtn.setText(_translate("Form", "Norm", None))
self.normGroup.setTitle(_translate("Form", "Normalization", None))
self.normSubtractRadio.setText(_translate("Form", "Subtract", None))
self.normDivideRadio.setText(_translate("Form", "Divide", None))
self.label_5.setText(_translate("Form", "Operation:", None))
self.label_3.setText(_translate("Form", "Mean:", None))
self.label_4.setText(_translate("Form", "Blur:", None))
self.normROICheck.setText(_translate("Form", "ROI", None))
self.label_8.setText(_translate("Form", "X", None))
self.label_9.setText(_translate("Form", "Y", None))
self.label_10.setText(_translate("Form", "T", None))
self.normOffRadio.setText(_translate("Form", "Off", None))
self.normTimeRangeCheck.setText(_translate("Form", "Time range", None))
self.normFrameCheck.setText(_translate("Form", "Frame", None))
from pyqtgraph.widgets.GraphicsView import GraphicsView
from pyqtgraph.widgets.PlotWidget import PlotWidget
from pyqtgraph.widgets.HistogramLUTWidget import HistogramLUTWidget
from ..widgets.HistogramLUTWidget import HistogramLUTWidget
from ..widgets.GraphicsView import GraphicsView
from ..widgets.PlotWidget import PlotWidget

View File

@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file './imageview/ImageViewTemplate.ui'
# Form implementation generated from reading ui file './pyqtgraph/imageview/ImageViewTemplate.ui'
#
# Created: Sun Sep 9 14:41:31 2012
# by: pyside-uic 0.2.13 running on PySide 1.1.0
# Created: Mon Dec 23 10:10:52 2013
# by: pyside-uic 0.2.14 running on PySide 1.1.2
#
# WARNING! All changes made in this file will be lost!
@ -150,6 +150,6 @@ class Ui_Form(object):
self.normTimeRangeCheck.setText(QtGui.QApplication.translate("Form", "Time range", None, QtGui.QApplication.UnicodeUTF8))
self.normFrameCheck.setText(QtGui.QApplication.translate("Form", "Frame", None, QtGui.QApplication.UnicodeUTF8))
from pyqtgraph.widgets.GraphicsView import GraphicsView
from pyqtgraph.widgets.PlotWidget import PlotWidget
from pyqtgraph.widgets.HistogramLUTWidget import HistogramLUTWidget
from ..widgets.HistogramLUTWidget import HistogramLUTWidget
from ..widgets.GraphicsView import GraphicsView
from ..widgets.PlotWidget import PlotWidget

View File

@ -929,7 +929,7 @@ class MetaArray(object):
if proc == False:
raise Exception('remote read failed')
if proc == None:
import pyqtgraph.multiprocess as mp
from .. import multiprocess as mp
#print "new process"
proc = mp.Process(executable='/usr/bin/python')
proc.setProxyOptions(deferGetattr=True)

View File

@ -63,8 +63,8 @@ class Parallelize(object):
self.showProgress = True
if isinstance(progressDialog, basestring):
progressDialog = {'labelText': progressDialog}
import pyqtgraph as pg
self.progressDlg = pg.ProgressDialog(**progressDialog)
from ..widgets.ProgressDialog import ProgressDialog
self.progressDlg = ProgressDialog(**progressDialog)
if workers is None:
workers = self.suggestedWorkerCount()

Some files were not shown because too many files have changed in this diff Show More