merged many changes in from acq4:
- added vertical lines / regions for plots - added gradient editor widget - many bugfixes - cleaned up imageview a bit
This commit is contained in:
parent
7efc975400
commit
2ca08c69ce
364
GradientWidget.py
Normal file
364
GradientWidget.py
Normal file
@ -0,0 +1,364 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from PyQt4 import QtGui, QtCore
|
||||||
|
|
||||||
|
|
||||||
|
class TickSlider(QtGui.QGraphicsView):
|
||||||
|
def __init__(self, parent=None, orientation='bottom', allowAdd=True, **kargs):
|
||||||
|
QtGui.QGraphicsView.__init__(self, parent)
|
||||||
|
#self.orientation = orientation
|
||||||
|
self.allowAdd = allowAdd
|
||||||
|
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
||||||
|
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
||||||
|
self.setTransformationAnchor(QtGui.QGraphicsView.NoAnchor)
|
||||||
|
self.setResizeAnchor(QtGui.QGraphicsView.AnchorViewCenter)
|
||||||
|
self.setRenderHints(QtGui.QPainter.Antialiasing | QtGui.QPainter.TextAntialiasing)
|
||||||
|
self.length = 100
|
||||||
|
self.tickSize = 15
|
||||||
|
self.orientations = {
|
||||||
|
'left': (270, 1, -1),
|
||||||
|
'right': (270, 1, 1),
|
||||||
|
'top': (0, 1, -1),
|
||||||
|
'bottom': (0, 1, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.scene = QtGui.QGraphicsScene()
|
||||||
|
self.setScene(self.scene)
|
||||||
|
|
||||||
|
self.ticks = {}
|
||||||
|
self.maxDim = 20
|
||||||
|
self.setOrientation(orientation)
|
||||||
|
self.setFrameStyle(QtGui.QFrame.NoFrame | QtGui.QFrame.Plain)
|
||||||
|
self.setBackgroundRole(QtGui.QPalette.NoRole)
|
||||||
|
self.setMouseTracking(True)
|
||||||
|
|
||||||
|
def keyPressEvent(self, ev):
|
||||||
|
ev.ignore()
|
||||||
|
|
||||||
|
def setMaxDim(self, mx=None):
|
||||||
|
if mx is None:
|
||||||
|
mx = self.maxDim
|
||||||
|
else:
|
||||||
|
self.maxDim = mx
|
||||||
|
|
||||||
|
if self.orientation in ['bottom', 'top']:
|
||||||
|
self.setFixedHeight(mx)
|
||||||
|
self.setMaximumWidth(16777215)
|
||||||
|
else:
|
||||||
|
self.setFixedWidth(mx)
|
||||||
|
self.setMaximumHeight(16777215)
|
||||||
|
|
||||||
|
def setOrientation(self, ort):
|
||||||
|
self.orientation = ort
|
||||||
|
self.resetTransform()
|
||||||
|
self.rotate(self.orientations[ort][0])
|
||||||
|
self.scale(*self.orientations[ort][1:])
|
||||||
|
self.setMaxDim()
|
||||||
|
|
||||||
|
def addTick(self, x, color=None, movable=True):
|
||||||
|
if color is None:
|
||||||
|
color = QtGui.QColor(255,255,255)
|
||||||
|
tick = Tick(self, [x*self.length, 0], color, movable, self.tickSize)
|
||||||
|
self.ticks[tick] = x
|
||||||
|
self.scene.addItem(tick)
|
||||||
|
return tick
|
||||||
|
|
||||||
|
def removeTick(self, tick):
|
||||||
|
del self.ticks[tick]
|
||||||
|
self.scene.removeItem(tick)
|
||||||
|
|
||||||
|
def tickMoved(self, tick, pos):
|
||||||
|
#print "tick changed"
|
||||||
|
## Correct position of tick if it has left bounds.
|
||||||
|
newX = min(max(0, pos.x()), self.length)
|
||||||
|
pos.setX(newX)
|
||||||
|
tick.setPos(pos)
|
||||||
|
self.ticks[tick] = float(newX) / self.length
|
||||||
|
|
||||||
|
def tickClicked(self, tick, ev):
|
||||||
|
if ev.button() == QtCore.Qt.RightButton:
|
||||||
|
self.removeTick(tick)
|
||||||
|
|
||||||
|
def widgetLength(self):
|
||||||
|
if self.orientation in ['bottom', 'top']:
|
||||||
|
return self.width()
|
||||||
|
else:
|
||||||
|
return self.height()
|
||||||
|
|
||||||
|
def resizeEvent(self, ev):
|
||||||
|
wlen = max(40, self.widgetLength())
|
||||||
|
self.setLength(wlen-self.tickSize)
|
||||||
|
bounds = self.scene.itemsBoundingRect()
|
||||||
|
bounds.setLeft(min(-self.tickSize*0.5, bounds.left()))
|
||||||
|
bounds.setRight(max(self.length + self.tickSize, bounds.right()))
|
||||||
|
#bounds.setTop(min(bounds.top(), self.tickSize))
|
||||||
|
#bounds.setBottom(max(0, bounds.bottom()))
|
||||||
|
self.setSceneRect(bounds)
|
||||||
|
self.fitInView(bounds, QtCore.Qt.KeepAspectRatio)
|
||||||
|
|
||||||
|
def setLength(self, newLen):
|
||||||
|
for t, x in self.ticks.items():
|
||||||
|
t.setPos(x * newLen, t.pos().y())
|
||||||
|
self.length = float(newLen)
|
||||||
|
|
||||||
|
def mousePressEvent(self, ev):
|
||||||
|
QtGui.QGraphicsView.mousePressEvent(self, ev)
|
||||||
|
self.ignoreRelease = False
|
||||||
|
if len(self.items(ev.pos())) > 0: ## Let items handle their own clicks
|
||||||
|
self.ignoreRelease = True
|
||||||
|
|
||||||
|
def mouseReleaseEvent(self, ev):
|
||||||
|
QtGui.QGraphicsView.mouseReleaseEvent(self, ev)
|
||||||
|
if self.ignoreRelease:
|
||||||
|
return
|
||||||
|
|
||||||
|
pos = self.mapToScene(ev.pos())
|
||||||
|
if pos.x() < 0 or pos.x() > self.length:
|
||||||
|
return
|
||||||
|
if pos.y() < 0 or pos.y() > self.tickSize:
|
||||||
|
return
|
||||||
|
|
||||||
|
if ev.button() == QtCore.Qt.LeftButton and self.allowAdd:
|
||||||
|
pos.setX(min(max(pos.x(), 0), self.length))
|
||||||
|
self.addTick(pos.x()/self.length)
|
||||||
|
elif ev.button() == QtCore.Qt.RightButton:
|
||||||
|
self.showMenu(ev)
|
||||||
|
|
||||||
|
|
||||||
|
def showMenu(self, ev):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def setTickColor(self, tick, color):
|
||||||
|
tick = self.getTick(tick)
|
||||||
|
tick.color = color
|
||||||
|
tick.setBrush(QtGui.QBrush(QtGui.QColor(tick.color)))
|
||||||
|
|
||||||
|
def setTickValue(self, tick, val):
|
||||||
|
tick = self.getTick(tick)
|
||||||
|
val = min(max(0.0, val), 1.0)
|
||||||
|
x = val * self.length
|
||||||
|
pos = tick.pos()
|
||||||
|
pos.setX(x)
|
||||||
|
tick.setPos(pos)
|
||||||
|
self.ticks[tick] = val
|
||||||
|
|
||||||
|
def tickValue(self, tick):
|
||||||
|
tick = self.getTick(tick)
|
||||||
|
return self.ticks[tick]
|
||||||
|
|
||||||
|
def getTick(self, tick):
|
||||||
|
if type(tick) is int:
|
||||||
|
tick = self.listTicks()[tick][0]
|
||||||
|
return tick
|
||||||
|
|
||||||
|
def mouseMoveEvent(self, ev):
|
||||||
|
QtGui.QGraphicsView.mouseMoveEvent(self, ev)
|
||||||
|
#print ev.pos(), ev.buttons()
|
||||||
|
|
||||||
|
def listTicks(self):
|
||||||
|
ticks = self.ticks.items()
|
||||||
|
ticks.sort(lambda a,b: cmp(a[1], b[1]))
|
||||||
|
return ticks
|
||||||
|
|
||||||
|
|
||||||
|
class GradientWidget(TickSlider):
|
||||||
|
def __init__(self, *args, **kargs):
|
||||||
|
TickSlider.__init__(self, *args, **kargs)
|
||||||
|
self.rectSize = 15
|
||||||
|
self.gradRect = QtGui.QGraphicsRectItem(QtCore.QRectF(0, -self.rectSize, 100, self.rectSize))
|
||||||
|
self.colorMode = 'rgb'
|
||||||
|
|
||||||
|
|
||||||
|
#self.gradient = QtGui.QLinearGradient(QtCore.QPointF(0,0), QtCore.QPointF(100,0))
|
||||||
|
self.scene.addItem(self.gradRect)
|
||||||
|
self.addTick(0, QtGui.QColor(0,0,0), True)
|
||||||
|
self.addTick(1, QtGui.QColor(255,0,0), True)
|
||||||
|
|
||||||
|
self.setMaxDim(self.rectSize + self.tickSize)
|
||||||
|
self.updateGradient()
|
||||||
|
|
||||||
|
#self.btn = QtGui.QPushButton('RGB')
|
||||||
|
#self.btnProxy = self.scene.addWidget(self.btn)
|
||||||
|
#self.btnProxy.setFlag(self.btnProxy.ItemIgnoresTransformations)
|
||||||
|
#self.btnProxy.scale(0.7, 0.7)
|
||||||
|
#self.btnProxy.translate(-self.btnProxy.sceneBoundingRect().width()+self.tickSize/2., 0)
|
||||||
|
#if self.orientation == 'bottom':
|
||||||
|
#self.btnProxy.translate(0, -self.rectSize)
|
||||||
|
|
||||||
|
def setColorMode(self, cm):
|
||||||
|
if cm not in ['rgb', 'hsv']:
|
||||||
|
raise Exception("Unknown color mode %s" % str(cm))
|
||||||
|
self.colorMode = cm
|
||||||
|
self.updateGradient()
|
||||||
|
|
||||||
|
def updateGradient(self):
|
||||||
|
self.gradient = self.getGradient()
|
||||||
|
self.gradRect.setBrush(QtGui.QBrush(self.gradient))
|
||||||
|
self.emit(QtCore.SIGNAL('gradientChanged'), self)
|
||||||
|
|
||||||
|
def setLength(self, newLen):
|
||||||
|
TickSlider.setLength(self, newLen)
|
||||||
|
self.gradRect.setRect(0, -self.rectSize, newLen, self.rectSize)
|
||||||
|
self.updateGradient()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def tickClicked(self, tick, ev):
|
||||||
|
if ev.button() == QtCore.Qt.LeftButton:
|
||||||
|
if not tick.colorChangeAllowed:
|
||||||
|
return
|
||||||
|
color = QtGui.QColorDialog.getColor(tick.color, None, "Select Color", QtGui.QColorDialog.ShowAlphaChannel)
|
||||||
|
if color.isValid():
|
||||||
|
self.setTickColor(tick, color)
|
||||||
|
self.updateGradient()
|
||||||
|
elif ev.button() == QtCore.Qt.RightButton:
|
||||||
|
if not tick.removeAllowed:
|
||||||
|
return
|
||||||
|
if len(self.ticks) > 2:
|
||||||
|
self.removeTick(tick)
|
||||||
|
self.updateGradient()
|
||||||
|
|
||||||
|
def tickMoved(self, tick, pos):
|
||||||
|
TickSlider.tickMoved(self, tick, pos)
|
||||||
|
self.updateGradient()
|
||||||
|
|
||||||
|
|
||||||
|
def getGradient(self):
|
||||||
|
g = QtGui.QLinearGradient(QtCore.QPointF(0,0), QtCore.QPointF(self.length,0))
|
||||||
|
if self.colorMode == 'rgb':
|
||||||
|
ticks = self.listTicks()
|
||||||
|
g.setStops([(x, QtGui.QColor(t.color)) for t,x in ticks])
|
||||||
|
elif self.colorMode == 'hsv': ## HSV mode is approximated for display by interpolating 10 points between each stop
|
||||||
|
ticks = self.listTicks()
|
||||||
|
stops = []
|
||||||
|
stops.append((ticks[0][1], ticks[0][0].color))
|
||||||
|
for i in range(1,len(ticks)):
|
||||||
|
x1 = ticks[i-1][1]
|
||||||
|
x2 = ticks[i][1]
|
||||||
|
dx = (x2-x1) / 10.
|
||||||
|
for j in range(1,10):
|
||||||
|
x = x1 + dx*j
|
||||||
|
stops.append((x, self.getColor(x)))
|
||||||
|
stops.append((x2, self.getColor(x2)))
|
||||||
|
g.setStops(stops)
|
||||||
|
return g
|
||||||
|
|
||||||
|
def getColor(self, x):
|
||||||
|
ticks = self.listTicks()
|
||||||
|
if x <= ticks[0][1]:
|
||||||
|
return QtGui.QColor(ticks[0][0].color) # always copy colors before handing them out
|
||||||
|
if x >= ticks[-1][1]:
|
||||||
|
return QtGui.QColor(ticks[-1][0].color)
|
||||||
|
|
||||||
|
x2 = ticks[0][1]
|
||||||
|
for i in range(1,len(ticks)):
|
||||||
|
x1 = x2
|
||||||
|
x2 = ticks[i][1]
|
||||||
|
if x1 <= x and x2 >= x:
|
||||||
|
break
|
||||||
|
|
||||||
|
dx = (x2-x1)
|
||||||
|
if dx == 0:
|
||||||
|
f = 0.
|
||||||
|
else:
|
||||||
|
f = (x-x1) / dx
|
||||||
|
c1 = ticks[i-1][0].color
|
||||||
|
c2 = ticks[i][0].color
|
||||||
|
if self.colorMode == 'rgb':
|
||||||
|
r = c1.red() * (1.-f) + c2.red() * f
|
||||||
|
g = c1.green() * (1.-f) + c2.green() * f
|
||||||
|
b = c1.blue() * (1.-f) + c2.blue() * f
|
||||||
|
return QtGui.QColor(r, g, b)
|
||||||
|
elif self.colorMode == 'hsv':
|
||||||
|
h1,s1,v1,_ = c1.getHsv()
|
||||||
|
h2,s2,v2,_ = c2.getHsv()
|
||||||
|
h = h1 * (1.-f) + h2 * f
|
||||||
|
s = s1 * (1.-f) + s2 * f
|
||||||
|
v = v1 * (1.-f) + v2 * f
|
||||||
|
c = QtGui.QColor()
|
||||||
|
c.setHsv(h,s,v)
|
||||||
|
return c
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def mouseReleaseEvent(self, ev):
|
||||||
|
TickSlider.mouseReleaseEvent(self, ev)
|
||||||
|
self.updateGradient()
|
||||||
|
|
||||||
|
def addTick(self, x, color=None, movable=True):
|
||||||
|
if color is None:
|
||||||
|
color = self.getColor(x)
|
||||||
|
t = TickSlider.addTick(self, x, color=color, movable=movable)
|
||||||
|
t.colorChangeAllowed = True
|
||||||
|
t.removeAllowed = True
|
||||||
|
return t
|
||||||
|
|
||||||
|
|
||||||
|
class GammaWidget(TickSlider):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Tick(QtGui.QGraphicsPolygonItem):
|
||||||
|
def __init__(self, view, pos, color, movable=True, scale=10):
|
||||||
|
#QObjectWorkaround.__init__(self)
|
||||||
|
self.movable = movable
|
||||||
|
self.view = view
|
||||||
|
self.scale = scale
|
||||||
|
self.color = color
|
||||||
|
#self.endTick = endTick
|
||||||
|
self.pg = QtGui.QPolygonF([QtCore.QPointF(0,0), QtCore.QPointF(-scale/3**0.5,scale), QtCore.QPointF(scale/3**0.5,scale)])
|
||||||
|
QtGui.QGraphicsPolygonItem.__init__(self, self.pg)
|
||||||
|
self.setPos(pos[0], pos[1])
|
||||||
|
self.setFlags(QtGui.QGraphicsItem.ItemIsMovable | QtGui.QGraphicsItem.ItemIsSelectable)
|
||||||
|
self.setBrush(QtGui.QBrush(QtGui.QColor(self.color)))
|
||||||
|
if self.movable:
|
||||||
|
self.setZValue(1)
|
||||||
|
else:
|
||||||
|
self.setZValue(0)
|
||||||
|
|
||||||
|
#def x(self):
|
||||||
|
#return self.pos().x()/100.
|
||||||
|
|
||||||
|
def mouseMoveEvent(self, ev):
|
||||||
|
#print self, "move", ev.scenePos()
|
||||||
|
if not self.movable:
|
||||||
|
return
|
||||||
|
if not ev.buttons() & QtCore.Qt.LeftButton:
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
newPos = ev.scenePos() + self.mouseOffset
|
||||||
|
newPos.setY(self.pos().y())
|
||||||
|
#newPos.setX(min(max(newPos.x(), 0), 100))
|
||||||
|
self.setPos(newPos)
|
||||||
|
self.view.tickMoved(self, newPos)
|
||||||
|
self.movedSincePress = True
|
||||||
|
#self.emit(QtCore.SIGNAL('tickChanged'), self)
|
||||||
|
ev.accept()
|
||||||
|
|
||||||
|
def mousePressEvent(self, ev):
|
||||||
|
self.movedSincePress = False
|
||||||
|
if ev.button() == QtCore.Qt.LeftButton:
|
||||||
|
ev.accept()
|
||||||
|
self.mouseOffset = self.pos() - ev.scenePos()
|
||||||
|
self.pressPos = ev.scenePos()
|
||||||
|
elif ev.button() == QtCore.Qt.RightButton:
|
||||||
|
ev.accept()
|
||||||
|
#if self.endTick:
|
||||||
|
#return
|
||||||
|
#self.view.tickChanged(self, delete=True)
|
||||||
|
|
||||||
|
def mouseReleaseEvent(self, ev):
|
||||||
|
#print self, "release", ev.scenePos()
|
||||||
|
if not self.movedSincePress:
|
||||||
|
self.view.tickClicked(self, ev)
|
||||||
|
|
||||||
|
#if ev.button() == QtCore.Qt.LeftButton and ev.scenePos() == self.pressPos:
|
||||||
|
#color = QtGui.QColorDialog.getColor(self.color, None, "Select Color", QtGui.QColorDialog.ShowAlphaChannel)
|
||||||
|
#if color.isValid():
|
||||||
|
#self.color = color
|
||||||
|
#self.setBrush(QtGui.QBrush(QtGui.QColor(self.color)))
|
||||||
|
##self.emit(QtCore.SIGNAL('tickChanged'), self)
|
||||||
|
#self.view.tickChanged(self)
|
||||||
|
|
||||||
|
|
||||||
|
|
26
GradientWidgetTest.py
Normal file
26
GradientWidgetTest.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from GradientWidget import *
|
||||||
|
from PyQt4 import QtGui
|
||||||
|
|
||||||
|
app = QtGui.QApplication([])
|
||||||
|
w = QtGui.QMainWindow()
|
||||||
|
w.show()
|
||||||
|
w.resize(400,400)
|
||||||
|
cw = QtGui.QWidget()
|
||||||
|
w.setCentralWidget(cw)
|
||||||
|
|
||||||
|
l = QtGui.QGridLayout()
|
||||||
|
l.setSpacing(0)
|
||||||
|
cw.setLayout(l)
|
||||||
|
|
||||||
|
w1 = GradientWidget(orientation='top')
|
||||||
|
w2 = GradientWidget(orientation='right', allowAdd=False)
|
||||||
|
w2.setTickColor(1, QtGui.QColor(255,255,255))
|
||||||
|
w3 = GradientWidget(orientation='bottom')
|
||||||
|
w4 = TickSlider(orientation='left')
|
||||||
|
|
||||||
|
l.addWidget(w1, 0, 1)
|
||||||
|
l.addWidget(w2, 1, 2)
|
||||||
|
l.addWidget(w3, 2, 1)
|
||||||
|
l.addWidget(w4, 1, 0)
|
@ -10,11 +10,11 @@ from PyQt4 import QtCore, QtGui, QtOpenGL, QtSvg
|
|||||||
#import time
|
#import time
|
||||||
from Point import *
|
from Point import *
|
||||||
#from vector import *
|
#from vector import *
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
class GraphicsView(QtGui.QGraphicsView):
|
class GraphicsView(QtGui.QGraphicsView):
|
||||||
def __init__(self, *args):
|
def __init__(self, parent=None, useOpenGL=True):
|
||||||
"""Re-implementation of QGraphicsView that removes scrollbars and allows unambiguous control of the
|
"""Re-implementation of QGraphicsView that removes scrollbars and allows unambiguous control of the
|
||||||
viewed coordinate range. Also automatically creates a QGraphicsScene and a central QGraphicsWidget
|
viewed coordinate range. Also automatically creates a QGraphicsScene and a central QGraphicsWidget
|
||||||
that is automatically scaled to the full view geometry.
|
that is automatically scaled to the full view geometry.
|
||||||
@ -26,8 +26,9 @@ class GraphicsView(QtGui.QGraphicsView):
|
|||||||
The view can be panned using the middle mouse button and scaled using the right mouse button if
|
The view can be panned using the middle mouse button and scaled using the right mouse button if
|
||||||
enabled via enableMouse()."""
|
enabled via enableMouse()."""
|
||||||
|
|
||||||
QtGui.QGraphicsView.__init__(self, *args)
|
QtGui.QGraphicsView.__init__(self, parent)
|
||||||
self.setViewport(QtOpenGL.QGLWidget())
|
self.useOpenGL(useOpenGL)
|
||||||
|
|
||||||
palette = QtGui.QPalette()
|
palette = QtGui.QPalette()
|
||||||
brush = QtGui.QBrush(QtGui.QColor(0,0,0))
|
brush = QtGui.QBrush(QtGui.QColor(0,0,0))
|
||||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||||
@ -49,6 +50,7 @@ class GraphicsView(QtGui.QGraphicsView):
|
|||||||
#self.setResizeAnchor(QtGui.QGraphicsView.NoAnchor)
|
#self.setResizeAnchor(QtGui.QGraphicsView.NoAnchor)
|
||||||
self.setViewportUpdateMode(QtGui.QGraphicsView.SmartViewportUpdate)
|
self.setViewportUpdateMode(QtGui.QGraphicsView.SmartViewportUpdate)
|
||||||
self.setSceneRect(QtCore.QRectF(-1e10, -1e10, 2e10, 2e10))
|
self.setSceneRect(QtCore.QRectF(-1e10, -1e10, 2e10, 2e10))
|
||||||
|
#self.setSceneRect(1, 1, 0, 0) ## Set an empty (but non-zero) scene rect so that the view doesn't try to automatically update for us.
|
||||||
#self.setInteractive(False)
|
#self.setInteractive(False)
|
||||||
self.lockedViewports = []
|
self.lockedViewports = []
|
||||||
self.lastMousePos = None
|
self.lastMousePos = None
|
||||||
@ -68,6 +70,18 @@ class GraphicsView(QtGui.QGraphicsView):
|
|||||||
self.scaleCenter = False ## should scaling center around view center (True) or mouse click (False)
|
self.scaleCenter = False ## should scaling center around view center (True) or mouse click (False)
|
||||||
self.clickAccepted = False
|
self.clickAccepted = False
|
||||||
|
|
||||||
|
def useOpenGL(self, b=True):
|
||||||
|
if b:
|
||||||
|
v = QtOpenGL.QGLWidget()
|
||||||
|
else:
|
||||||
|
v = QtGui.QWidget()
|
||||||
|
|
||||||
|
#v.setStyleSheet("background-color: #000000;")
|
||||||
|
self.setViewport(v)
|
||||||
|
|
||||||
|
def keyPressEvent(self, ev):
|
||||||
|
ev.ignore()
|
||||||
|
|
||||||
def setCentralItem(self, item):
|
def setCentralItem(self, item):
|
||||||
if self.centralWidget is not None:
|
if self.centralWidget is not None:
|
||||||
self.scene().removeItem(self.centralWidget)
|
self.scene().removeItem(self.centralWidget)
|
||||||
@ -77,6 +91,9 @@ class GraphicsView(QtGui.QGraphicsView):
|
|||||||
def addItem(self, *args):
|
def addItem(self, *args):
|
||||||
return self.scene().addItem(*args)
|
return self.scene().addItem(*args)
|
||||||
|
|
||||||
|
def removeItem(self, *args):
|
||||||
|
return self.scene().removeItem(*args)
|
||||||
|
|
||||||
def enableMouse(self, b=True):
|
def enableMouse(self, b=True):
|
||||||
self.mouseEnabled = b
|
self.mouseEnabled = b
|
||||||
self.autoPixelRange = (not b)
|
self.autoPixelRange = (not b)
|
||||||
@ -128,6 +145,8 @@ class GraphicsView(QtGui.QGraphicsView):
|
|||||||
v.setXRange(self.range, padding=0)
|
v.setXRange(self.range, padding=0)
|
||||||
|
|
||||||
def visibleRange(self):
|
def visibleRange(self):
|
||||||
|
"""Return the boundaries of the view in scene coordinates"""
|
||||||
|
## easier to just return self.range ?
|
||||||
r = QtCore.QRectF(self.rect())
|
r = QtCore.QRectF(self.rect())
|
||||||
return self.viewportTransform().inverted()[0].mapRect(r)
|
return self.viewportTransform().inverted()[0].mapRect(r)
|
||||||
|
|
||||||
@ -347,6 +366,16 @@ class GraphicsView(QtGui.QGraphicsView):
|
|||||||
self.setRenderHints(rh)
|
self.setRenderHints(rh)
|
||||||
self.png.save(fileName)
|
self.png.save(fileName)
|
||||||
|
|
||||||
|
def writePs(self, fileName=None):
|
||||||
|
if fileName is None:
|
||||||
|
fileName = str(QtGui.QFileDialog.getSaveFileName())
|
||||||
|
printer = QtGui.QPrinter(QtGui.QPrinter.HighResolution)
|
||||||
|
printer.setOutputFileName(fileName)
|
||||||
|
painter = QtGui.QPainter(printer)
|
||||||
|
self.render(painter)
|
||||||
|
painter.end()
|
||||||
|
|
||||||
|
|
||||||
#def getFreehandLine(self):
|
#def getFreehandLine(self):
|
||||||
|
|
||||||
## Wait for click
|
## Wait for click
|
||||||
|
342
ImageView.py
342
ImageView.py
@ -17,6 +17,11 @@ from ImageViewTemplate import *
|
|||||||
from graphicsItems import *
|
from graphicsItems import *
|
||||||
from widgets import ROI
|
from widgets import ROI
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
|
import sys
|
||||||
|
from numpy import ndarray
|
||||||
|
import ptime
|
||||||
|
|
||||||
|
from SignalProxy import proxyConnect
|
||||||
|
|
||||||
class PlotROI(ROI):
|
class PlotROI(ROI):
|
||||||
def __init__(self, size):
|
def __init__(self, size):
|
||||||
@ -35,12 +40,25 @@ class ImageView(QtGui.QWidget):
|
|||||||
self.ui = Ui_Form()
|
self.ui = Ui_Form()
|
||||||
self.ui.setupUi(self)
|
self.ui.setupUi(self)
|
||||||
self.scene = self.ui.graphicsView.sceneObj
|
self.scene = self.ui.graphicsView.sceneObj
|
||||||
|
|
||||||
|
self.ignoreTimeLine = False
|
||||||
|
|
||||||
|
if 'linux' in sys.platform.lower(): ## Stupid GL bug in linux.
|
||||||
|
self.ui.graphicsView.setViewport(QtGui.QWidget())
|
||||||
|
|
||||||
self.ui.graphicsView.enableMouse(True)
|
self.ui.graphicsView.enableMouse(True)
|
||||||
self.ui.graphicsView.autoPixelRange = False
|
self.ui.graphicsView.autoPixelRange = False
|
||||||
self.ui.graphicsView.setAspectLocked(True)
|
self.ui.graphicsView.setAspectLocked(True)
|
||||||
self.ui.graphicsView.invertY()
|
self.ui.graphicsView.invertY()
|
||||||
self.ui.graphicsView.enableMouse()
|
self.ui.graphicsView.enableMouse()
|
||||||
|
|
||||||
|
self. ticks = [t[0] for t in self.ui.gradientWidget.listTicks()]
|
||||||
|
self.ticks[0].colorChangeAllowed = False
|
||||||
|
self.ticks[1].colorChangeAllowed = False
|
||||||
|
self.ui.gradientWidget.allowAdd = False
|
||||||
|
self.ui.gradientWidget.setTickColor(self.ticks[1], QtGui.QColor(255,255,255))
|
||||||
|
self.ui.gradientWidget.setOrientation('right')
|
||||||
|
|
||||||
self.imageItem = ImageItem()
|
self.imageItem = ImageItem()
|
||||||
self.scene.addItem(self.imageItem)
|
self.scene.addItem(self.imageItem)
|
||||||
self.currentIndex = 0
|
self.currentIndex = 0
|
||||||
@ -51,26 +69,46 @@ class ImageView(QtGui.QWidget):
|
|||||||
self.roi.setZValue(20)
|
self.roi.setZValue(20)
|
||||||
self.scene.addItem(self.roi)
|
self.scene.addItem(self.roi)
|
||||||
self.roi.hide()
|
self.roi.hide()
|
||||||
self.ui.roiPlot.hide()
|
self.normRoi = PlotROI(10)
|
||||||
|
self.normRoi.setPen(QtGui.QPen(QtGui.QColor(255,255,0)))
|
||||||
|
self.normRoi.setZValue(20)
|
||||||
|
self.scene.addItem(self.normRoi)
|
||||||
|
self.normRoi.hide()
|
||||||
|
#self.ui.roiPlot.hide()
|
||||||
self.roiCurve = self.ui.roiPlot.plot()
|
self.roiCurve = self.ui.roiPlot.plot()
|
||||||
self.roiTimeLine = InfiniteLine(self.ui.roiPlot, 0)
|
self.timeLine = InfiniteLine(self.ui.roiPlot, 0, movable=True)
|
||||||
self.roiTimeLine.setPen(QtGui.QPen(QtGui.QColor(255, 255, 0, 200)))
|
self.timeLine.setPen(QtGui.QPen(QtGui.QColor(255, 255, 0, 200)))
|
||||||
self.ui.roiPlot.addItem(self.roiTimeLine)
|
self.timeLine.setZValue(1)
|
||||||
|
self.ui.roiPlot.addItem(self.timeLine)
|
||||||
|
self.ui.splitter.setSizes([self.height()-35, 35])
|
||||||
|
self.ui.roiPlot.showScale('left', False)
|
||||||
|
|
||||||
self.normLines = []
|
self.keysPressed = {}
|
||||||
for i in [0,1]:
|
self.playTimer = QtCore.QTimer()
|
||||||
l = InfiniteLine(self.ui.roiPlot, 0)
|
self.playRate = 0
|
||||||
l.setPen(QtGui.QPen(QtGui.QColor(0, 100, 200, 200)))
|
self.lastPlayTime = 0
|
||||||
self.ui.roiPlot.addItem(l)
|
|
||||||
self.normLines.append(l)
|
|
||||||
l.hide()
|
|
||||||
|
|
||||||
for fn in ['addItem']:
|
#self.normLines = []
|
||||||
|
#for i in [0,1]:
|
||||||
|
#l = InfiniteLine(self.ui.roiPlot, 0)
|
||||||
|
#l.setPen(QtGui.QPen(QtGui.QColor(0, 100, 200, 200)))
|
||||||
|
#self.ui.roiPlot.addItem(l)
|
||||||
|
#self.normLines.append(l)
|
||||||
|
#l.hide()
|
||||||
|
self.normRgn = LinearRegionItem(self.ui.roiPlot, 'vertical')
|
||||||
|
self.normRgn.setZValue(0)
|
||||||
|
self.ui.roiPlot.addItem(self.normRgn)
|
||||||
|
self.normRgn.hide()
|
||||||
|
|
||||||
|
## wrap functions from graphics view
|
||||||
|
for fn in ['addItem', 'removeItem']:
|
||||||
setattr(self, fn, getattr(self.ui.graphicsView, fn))
|
setattr(self, fn, getattr(self.ui.graphicsView, fn))
|
||||||
|
|
||||||
QtCore.QObject.connect(self.ui.timeSlider, QtCore.SIGNAL('valueChanged(int)'), self.timeChanged)
|
#QtCore.QObject.connect(self.ui.timeSlider, QtCore.SIGNAL('valueChanged(int)'), self.timeChanged)
|
||||||
QtCore.QObject.connect(self.ui.whiteSlider, QtCore.SIGNAL('valueChanged(int)'), self.updateImage)
|
self.timeLine.connect(QtCore.SIGNAL('positionChanged'), self.timeLineChanged)
|
||||||
QtCore.QObject.connect(self.ui.blackSlider, QtCore.SIGNAL('valueChanged(int)'), self.updateImage)
|
#QtCore.QObject.connect(self.ui.whiteSlider, QtCore.SIGNAL('valueChanged(int)'), self.updateImage)
|
||||||
|
#QtCore.QObject.connect(self.ui.blackSlider, QtCore.SIGNAL('valueChanged(int)'), self.updateImage)
|
||||||
|
QtCore.QObject.connect(self.ui.gradientWidget, QtCore.SIGNAL('gradientChanged'), self.updateImage)
|
||||||
QtCore.QObject.connect(self.ui.roiBtn, QtCore.SIGNAL('clicked()'), self.roiClicked)
|
QtCore.QObject.connect(self.ui.roiBtn, QtCore.SIGNAL('clicked()'), self.roiClicked)
|
||||||
self.roi.connect(QtCore.SIGNAL('regionChanged'), self.roiChanged)
|
self.roi.connect(QtCore.SIGNAL('regionChanged'), self.roiChanged)
|
||||||
QtCore.QObject.connect(self.ui.normBtn, QtCore.SIGNAL('toggled(bool)'), self.normToggled)
|
QtCore.QObject.connect(self.ui.normBtn, QtCore.SIGNAL('toggled(bool)'), self.normToggled)
|
||||||
@ -80,37 +118,177 @@ class ImageView(QtGui.QWidget):
|
|||||||
QtCore.QObject.connect(self.ui.normROICheck, QtCore.SIGNAL('clicked()'), self.updateNorm)
|
QtCore.QObject.connect(self.ui.normROICheck, QtCore.SIGNAL('clicked()'), self.updateNorm)
|
||||||
QtCore.QObject.connect(self.ui.normFrameCheck, QtCore.SIGNAL('clicked()'), self.updateNorm)
|
QtCore.QObject.connect(self.ui.normFrameCheck, QtCore.SIGNAL('clicked()'), self.updateNorm)
|
||||||
QtCore.QObject.connect(self.ui.normTimeRangeCheck, QtCore.SIGNAL('clicked()'), self.updateNorm)
|
QtCore.QObject.connect(self.ui.normTimeRangeCheck, QtCore.SIGNAL('clicked()'), self.updateNorm)
|
||||||
QtCore.QObject.connect(self.ui.normStartSlider, QtCore.SIGNAL('valueChanged(int)'), self.updateNorm)
|
QtCore.QObject.connect(self.playTimer, QtCore.SIGNAL('timeout()'), self.timeout)
|
||||||
QtCore.QObject.connect(self.ui.normStopSlider, QtCore.SIGNAL('valueChanged(int)'), self.updateNorm)
|
|
||||||
|
##QtCore.QObject.connect(self.ui.normStartSlider, QtCore.SIGNAL('valueChanged(int)'), self.updateNorm)
|
||||||
|
#QtCore.QObject.connect(self.ui.normStopSlider, QtCore.SIGNAL('valueChanged(int)'), self.updateNorm)
|
||||||
|
self.normProxy = proxyConnect(self.normRgn, QtCore.SIGNAL('regionChanged'), self.updateNorm)
|
||||||
|
self.normRoi.connect(QtCore.SIGNAL('regionChangeFinished'), self.updateNorm)
|
||||||
|
|
||||||
self.ui.roiPlot.registerPlot(self.name + '_ROI')
|
self.ui.roiPlot.registerPlot(self.name + '_ROI')
|
||||||
|
|
||||||
def updateNorm(self):
|
self.noRepeatKeys = [QtCore.Qt.Key_Right, QtCore.Qt.Key_Left, QtCore.Qt.Key_Up, QtCore.Qt.Key_Down, QtCore.Qt.Key_PageUp, QtCore.Qt.Key_PageDown]
|
||||||
for l, sl in zip(self.normLines, [self.ui.normStartSlider, self.ui.normStopSlider]):
|
|
||||||
if self.ui.normTimeRangeCheck.isChecked():
|
#def __dtor__(self):
|
||||||
l.show()
|
##print "Called ImageView sip destructor"
|
||||||
|
#self.quit()
|
||||||
|
#QtGui.QWidget.__dtor__(self)
|
||||||
|
|
||||||
|
def quit(self):
|
||||||
|
self.scene.clear()
|
||||||
|
del self.image
|
||||||
|
del self.imageDisp
|
||||||
|
|
||||||
|
|
||||||
|
def keyPressEvent(self, ev):
|
||||||
|
if ev.key() == QtCore.Qt.Key_Space:
|
||||||
|
if self.playRate == 0:
|
||||||
|
fps = (self.getProcessedImage().shape[0]-1) / (self.tVals[-1] - self.tVals[0])
|
||||||
|
self.play(fps)
|
||||||
|
#print fps
|
||||||
else:
|
else:
|
||||||
l.hide()
|
self.play(0)
|
||||||
|
ev.accept()
|
||||||
|
elif ev.key() == QtCore.Qt.Key_Home:
|
||||||
|
self.setCurrentIndex(0)
|
||||||
|
self.play(0)
|
||||||
|
ev.accept()
|
||||||
|
elif ev.key() == QtCore.Qt.Key_End:
|
||||||
|
self.setCurrentIndex(self.getProcessedImage().shape[0]-1)
|
||||||
|
self.play(0)
|
||||||
|
ev.accept()
|
||||||
|
elif ev.key() in self.noRepeatKeys:
|
||||||
|
ev.accept()
|
||||||
|
if ev.isAutoRepeat():
|
||||||
|
return
|
||||||
|
self.keysPressed[ev.key()] = 1
|
||||||
|
self.evalKeyState()
|
||||||
|
else:
|
||||||
|
QtGui.QWidget.keyPressEvent(self, ev)
|
||||||
|
|
||||||
i, t = self.timeIndex(sl)
|
def keyReleaseEvent(self, ev):
|
||||||
l.setPos(t)
|
if ev.key() in [QtCore.Qt.Key_Space, QtCore.Qt.Key_Home, QtCore.Qt.Key_End]:
|
||||||
|
ev.accept()
|
||||||
|
elif ev.key() in self.noRepeatKeys:
|
||||||
|
ev.accept()
|
||||||
|
if ev.isAutoRepeat():
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
del self.keysPressed[ev.key()]
|
||||||
|
except:
|
||||||
|
self.keysPressed = {}
|
||||||
|
self.evalKeyState()
|
||||||
|
else:
|
||||||
|
QtGui.QWidget.keyReleaseEvent(self, ev)
|
||||||
|
|
||||||
|
|
||||||
|
def evalKeyState(self):
|
||||||
|
if len(self.keysPressed) == 1:
|
||||||
|
key = self.keysPressed.keys()[0]
|
||||||
|
if key == QtCore.Qt.Key_Right:
|
||||||
|
self.play(20)
|
||||||
|
self.lastPlayTime = ptime.time() + 0.2 ## 2ms wait before start
|
||||||
|
self.jumpFrames(1)
|
||||||
|
elif key == QtCore.Qt.Key_Left:
|
||||||
|
self.play(-20)
|
||||||
|
self.lastPlayTime = ptime.time() + 0.2
|
||||||
|
self.jumpFrames(-1)
|
||||||
|
elif key == QtCore.Qt.Key_Up:
|
||||||
|
self.play(-100)
|
||||||
|
elif key == QtCore.Qt.Key_Down:
|
||||||
|
self.play(100)
|
||||||
|
elif key == QtCore.Qt.Key_PageUp:
|
||||||
|
self.play(-1000)
|
||||||
|
elif key == QtCore.Qt.Key_PageDown:
|
||||||
|
self.play(1000)
|
||||||
|
else:
|
||||||
|
self.play(0)
|
||||||
|
|
||||||
|
def play(self, rate):
|
||||||
|
#print "play:", rate
|
||||||
|
self.playRate = rate
|
||||||
|
if rate == 0:
|
||||||
|
self.playTimer.stop()
|
||||||
|
return
|
||||||
|
|
||||||
|
self.lastPlayTime = ptime.time()
|
||||||
|
if not self.playTimer.isActive():
|
||||||
|
self.playTimer.start(16)
|
||||||
|
|
||||||
|
|
||||||
|
def timeout(self):
|
||||||
|
now = ptime.time()
|
||||||
|
dt = now - self.lastPlayTime
|
||||||
|
if dt < 0:
|
||||||
|
return
|
||||||
|
n = int(self.playRate * dt)
|
||||||
|
#print n, dt
|
||||||
|
if n != 0:
|
||||||
|
#print n, dt, self.lastPlayTime
|
||||||
|
self.lastPlayTime += (float(n)/self.playRate)
|
||||||
|
if self.currentIndex+n > self.image.shape[0]:
|
||||||
|
self.play(0)
|
||||||
|
self.jumpFrames(n)
|
||||||
|
|
||||||
|
def setCurrentIndex(self, ind):
|
||||||
|
self.currentIndex = clip(ind, 0, self.getProcessedImage().shape[0]-1)
|
||||||
|
self.updateImage()
|
||||||
|
self.ignoreTimeLine = True
|
||||||
|
self.timeLine.setValue(self.tVals[self.currentIndex])
|
||||||
|
self.ignoreTimeLine = False
|
||||||
|
|
||||||
|
def jumpFrames(self, n):
|
||||||
|
"""If this is a video, move ahead n frames"""
|
||||||
|
if self.axes['t'] is not None:
|
||||||
|
self.setCurrentIndex(self.currentIndex + n)
|
||||||
|
|
||||||
|
def updateNorm(self):
|
||||||
|
#for l, sl in zip(self.normLines, [self.ui.normStartSlider, self.ui.normStopSlider]):
|
||||||
|
#if self.ui.normTimeRangeCheck.isChecked():
|
||||||
|
#l.show()
|
||||||
|
#else:
|
||||||
|
#l.hide()
|
||||||
|
|
||||||
|
#i, t = self.timeIndex(sl)
|
||||||
|
#l.setPos(t)
|
||||||
|
|
||||||
|
if self.ui.normTimeRangeCheck.isChecked():
|
||||||
|
#print "show!"
|
||||||
|
self.normRgn.show()
|
||||||
|
else:
|
||||||
|
self.normRgn.hide()
|
||||||
|
|
||||||
|
if self.ui.normROICheck.isChecked():
|
||||||
|
#print "show!"
|
||||||
|
self.normRoi.show()
|
||||||
|
else:
|
||||||
|
self.normRoi.hide()
|
||||||
|
|
||||||
self.imageDisp = None
|
self.imageDisp = None
|
||||||
self.updateImage()
|
self.updateImage()
|
||||||
self.roiChanged()
|
self.roiChanged()
|
||||||
|
|
||||||
def normToggled(self, b):
|
def normToggled(self, b):
|
||||||
self.ui.normGroup.setVisible(b)
|
self.ui.normGroup.setVisible(b)
|
||||||
|
self.normRoi.setVisible(b and self.ui.normROICheck.isChecked())
|
||||||
|
self.normRgn.setVisible(b and self.ui.normTimeRangeCheck.isChecked())
|
||||||
|
|
||||||
def roiClicked(self):
|
def roiClicked(self):
|
||||||
if self.ui.roiBtn.isChecked():
|
if self.ui.roiBtn.isChecked():
|
||||||
self.roi.show()
|
self.roi.show()
|
||||||
self.ui.roiPlot.show()
|
#self.ui.roiPlot.show()
|
||||||
|
self.ui.roiPlot.setMouseEnabled(True, True)
|
||||||
|
self.ui.splitter.setSizes([self.height()*0.6, self.height()*0.4])
|
||||||
|
self.roiCurve.show()
|
||||||
self.roiChanged()
|
self.roiChanged()
|
||||||
|
self.ui.roiPlot.showScale('left', True)
|
||||||
else:
|
else:
|
||||||
self.roi.hide()
|
self.roi.hide()
|
||||||
self.ui.roiPlot.hide()
|
self.ui.roiPlot.setMouseEnabled(False, False)
|
||||||
|
self.ui.roiPlot.setXRange(self.tVals.min(), self.tVals.max())
|
||||||
|
self.ui.splitter.setSizes([self.height()-35, 35])
|
||||||
|
self.roiCurve.hide()
|
||||||
|
self.ui.roiPlot.showScale('left', False)
|
||||||
|
|
||||||
def roiChanged(self):
|
def roiChanged(self):
|
||||||
if self.image is None:
|
if self.image is None:
|
||||||
@ -130,20 +308,36 @@ class ImageView(QtGui.QWidget):
|
|||||||
self.roiCurve.setData(y=data, x=self.tVals)
|
self.roiCurve.setData(y=data, x=self.tVals)
|
||||||
#self.ui.roiPlot.replot()
|
#self.ui.roiPlot.replot()
|
||||||
|
|
||||||
def setImage(self, img, autoRange=True, autoLevels=True, levels=None):
|
def setImage(self, img, autoRange=True, autoLevels=True, levels=None, axes=None, xvals=None):
|
||||||
|
"""Set the image to be displayed in the widget.
|
||||||
|
Options are:
|
||||||
|
img: ndarray; the image to be displayed.
|
||||||
|
autoRange: bool; whether to scale/pan the view to fit the image.
|
||||||
|
autoLevels: bool; whether to update the white/black levels to fit the image.
|
||||||
|
levels: (min, max); the white and black level values to use.
|
||||||
|
axes: {'t':0, 'x':1, 'y':2, 'c':3}; Dictionary indicating the interpretation for each axis.
|
||||||
|
This is only needed to override the default guess.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not isinstance(img, ndarray):
|
||||||
|
raise Exception("Image must be specified as ndarray.")
|
||||||
self.image = img
|
self.image = img
|
||||||
if hasattr(img, 'xvals'):
|
|
||||||
|
if xvals is not None:
|
||||||
|
self.tVals = xvals
|
||||||
|
elif hasattr(img, 'xvals'):
|
||||||
self.tVals = img.xvals(0)
|
self.tVals = img.xvals(0)
|
||||||
else:
|
else:
|
||||||
self.tVals = arange(img.shape[0])
|
self.tVals = arange(img.shape[0])
|
||||||
self.ui.timeSlider.setValue(0)
|
#self.ui.timeSlider.setValue(0)
|
||||||
#self.ui.normStartSlider.setValue(0)
|
#self.ui.normStartSlider.setValue(0)
|
||||||
#self.ui.timeSlider.setMaximum(img.shape[0]-1)
|
#self.ui.timeSlider.setMaximum(img.shape[0]-1)
|
||||||
|
|
||||||
|
if axes is None:
|
||||||
if img.ndim == 2:
|
if img.ndim == 2:
|
||||||
self.axes = {'t': None, 'x': 0, 'y': 1, 'c': None}
|
self.axes = {'t': None, 'x': 0, 'y': 1, 'c': None}
|
||||||
elif img.ndim == 3:
|
elif img.ndim == 3:
|
||||||
if img.shape[2] <= 3:
|
if img.shape[2] <= 4:
|
||||||
self.axes = {'t': None, 'x': 0, 'y': 1, 'c': 2}
|
self.axes = {'t': None, 'x': 0, 'y': 1, 'c': 2}
|
||||||
else:
|
else:
|
||||||
self.axes = {'t': 0, 'x': 1, 'y': 2, 'c': None}
|
self.axes = {'t': 0, 'x': 1, 'y': 2, 'c': None}
|
||||||
@ -163,11 +357,36 @@ class ImageView(QtGui.QWidget):
|
|||||||
if self.ui.roiBtn.isChecked():
|
if self.ui.roiBtn.isChecked():
|
||||||
self.roiChanged()
|
self.roiChanged()
|
||||||
|
|
||||||
|
|
||||||
|
if self.axes['t'] is not None:
|
||||||
|
#self.ui.roiPlot.show()
|
||||||
|
self.ui.roiPlot.setXRange(self.tVals.min(), self.tVals.max())
|
||||||
|
#self.ui.roiPlot.setMouseEnabled(False, False)
|
||||||
|
if len(self.tVals) > 1:
|
||||||
|
start = self.tVals.min()
|
||||||
|
stop = self.tVals.max() + abs(self.tVals[-1] - self.tVals[0]) * 0.02
|
||||||
|
elif len(self.tVals) == 1:
|
||||||
|
start = self.tVals[0] - 0.5
|
||||||
|
stop = self.tVals[0] + 0.5
|
||||||
|
else:
|
||||||
|
start = 0
|
||||||
|
stop = 1
|
||||||
|
for s in [self.timeLine, self.normRgn]:
|
||||||
|
s.setBounds([start, stop])
|
||||||
|
#else:
|
||||||
|
#self.ui.roiPlot.hide()
|
||||||
|
|
||||||
|
self.roiClicked()
|
||||||
|
|
||||||
|
|
||||||
def autoLevels(self):
|
def autoLevels(self):
|
||||||
image = self.getProcessedImage()
|
image = self.getProcessedImage()
|
||||||
|
|
||||||
self.ui.whiteSlider.setValue(self.ui.whiteSlider.maximum())
|
#self.ui.whiteSlider.setValue(self.ui.whiteSlider.maximum())
|
||||||
self.ui.blackSlider.setValue(0)
|
#self.ui.blackSlider.setValue(0)
|
||||||
|
|
||||||
|
self.ui.gradientWidget.setTickValue(self.ticks[0], 0.0)
|
||||||
|
self.ui.gradientWidget.setTickValue(self.ticks[1], 1.0)
|
||||||
self.imageItem.setLevels(white=self.whiteLevel(), black=self.blackLevel())
|
self.imageItem.setLevels(white=self.whiteLevel(), black=self.blackLevel())
|
||||||
|
|
||||||
def autoRange(self):
|
def autoRange(self):
|
||||||
@ -189,7 +408,7 @@ class ImageView(QtGui.QWidget):
|
|||||||
return image
|
return image
|
||||||
|
|
||||||
div = self.ui.normDivideRadio.isChecked()
|
div = self.ui.normDivideRadio.isChecked()
|
||||||
norm = image.copy()
|
norm = image.view(ndarray).copy()
|
||||||
#if div:
|
#if div:
|
||||||
#norm = ones(image.shape)
|
#norm = ones(image.shape)
|
||||||
#else:
|
#else:
|
||||||
@ -198,8 +417,8 @@ class ImageView(QtGui.QWidget):
|
|||||||
norm = norm.astype(float32)
|
norm = norm.astype(float32)
|
||||||
|
|
||||||
if self.ui.normTimeRangeCheck.isChecked() and image.ndim == 3:
|
if self.ui.normTimeRangeCheck.isChecked() and image.ndim == 3:
|
||||||
(sind, start) = self.timeIndex(self.ui.normStartSlider)
|
(sind, start) = self.timeIndex(self.normRgn.lines[0])
|
||||||
(eind, end) = self.timeIndex(self.ui.normStopSlider)
|
(eind, end) = self.timeIndex(self.normRgn.lines[1])
|
||||||
#print start, end, sind, eind
|
#print start, end, sind, eind
|
||||||
n = image[sind:eind+1].mean(axis=0)
|
n = image[sind:eind+1].mean(axis=0)
|
||||||
n.shape = (1,) + n.shape
|
n.shape = (1,) + n.shape
|
||||||
@ -216,17 +435,27 @@ class ImageView(QtGui.QWidget):
|
|||||||
else:
|
else:
|
||||||
norm -= n
|
norm -= n
|
||||||
|
|
||||||
|
if self.ui.normROICheck.isChecked() and image.ndim == 3:
|
||||||
|
n = self.normRoi.getArrayRegion(norm, self.imageItem, (1, 2)).mean(axis=1).mean(axis=1)
|
||||||
|
n = n[:,newaxis,newaxis]
|
||||||
|
#print start, end, sind, eind
|
||||||
|
if div:
|
||||||
|
norm /= n
|
||||||
|
else:
|
||||||
|
norm -= n
|
||||||
|
|
||||||
return norm
|
return norm
|
||||||
|
|
||||||
|
def timeLineChanged(self):
|
||||||
|
#(ind, time) = self.timeIndex(self.ui.timeSlider)
|
||||||
def timeChanged(self):
|
if self.ignoreTimeLine:
|
||||||
(ind, time) = self.timeIndex(self.ui.timeSlider)
|
return
|
||||||
|
self.play(0)
|
||||||
|
(ind, time) = self.timeIndex(self.timeLine)
|
||||||
if ind != self.currentIndex:
|
if ind != self.currentIndex:
|
||||||
self.currentIndex = ind
|
self.currentIndex = ind
|
||||||
self.updateImage()
|
self.updateImage()
|
||||||
self.roiTimeLine.setPos(time)
|
#self.timeLine.setPos(time)
|
||||||
#self.ui.roiPlot.replot()
|
|
||||||
self.emit(QtCore.SIGNAL('timeChanged'), ind, time)
|
self.emit(QtCore.SIGNAL('timeChanged'), ind, time)
|
||||||
|
|
||||||
def updateImage(self):
|
def updateImage(self):
|
||||||
@ -237,29 +466,38 @@ class ImageView(QtGui.QWidget):
|
|||||||
image = self.getProcessedImage()
|
image = self.getProcessedImage()
|
||||||
#print "update:", image.ndim, image.max(), image.min(), self.blackLevel(), self.whiteLevel()
|
#print "update:", image.ndim, image.max(), image.min(), self.blackLevel(), self.whiteLevel()
|
||||||
if self.axes['t'] is None:
|
if self.axes['t'] is None:
|
||||||
self.ui.timeSlider.hide()
|
#self.ui.timeSlider.hide()
|
||||||
self.imageItem.updateImage(image, white=self.whiteLevel(), black=self.blackLevel())
|
self.imageItem.updateImage(image, white=self.whiteLevel(), black=self.blackLevel())
|
||||||
|
self.ui.roiPlot.hide()
|
||||||
|
self.ui.roiBtn.hide()
|
||||||
else:
|
else:
|
||||||
self.ui.timeSlider.show()
|
self.ui.roiBtn.show()
|
||||||
|
self.ui.roiPlot.show()
|
||||||
|
#self.ui.timeSlider.show()
|
||||||
self.imageItem.updateImage(image[self.currentIndex], white=self.whiteLevel(), black=self.blackLevel())
|
self.imageItem.updateImage(image[self.currentIndex], white=self.whiteLevel(), black=self.blackLevel())
|
||||||
|
|
||||||
|
|
||||||
def timeIndex(self, slider):
|
def timeIndex(self, slider):
|
||||||
"""Return the time and frame index indicated by a slider"""
|
"""Return the time and frame index indicated by a slider"""
|
||||||
if self.image is None:
|
if self.image is None:
|
||||||
return (0,0)
|
return (0,0)
|
||||||
v = slider.value()
|
#v = slider.value()
|
||||||
vmax = slider.maximum()
|
#vmax = slider.maximum()
|
||||||
f = float(v) / vmax
|
#f = float(v) / vmax
|
||||||
t = 0.0
|
|
||||||
|
t = slider.value()
|
||||||
|
|
||||||
|
#t = 0.0
|
||||||
#xv = self.image.xvals('Time')
|
#xv = self.image.xvals('Time')
|
||||||
xv = self.tVals
|
xv = self.tVals
|
||||||
if xv is None:
|
if xv is None:
|
||||||
ind = int(f * self.image.shape[0])
|
ind = int(t)
|
||||||
|
#ind = int(f * self.image.shape[0])
|
||||||
else:
|
else:
|
||||||
if len(xv) < 2:
|
if len(xv) < 2:
|
||||||
return (0,0)
|
return (0,0)
|
||||||
totTime = xv[-1] + (xv[-1]-xv[-2])
|
totTime = xv[-1] + (xv[-1]-xv[-2])
|
||||||
t = f * totTime
|
#t = f * totTime
|
||||||
inds = argwhere(xv < t)
|
inds = argwhere(xv < t)
|
||||||
if len(inds) < 1:
|
if len(inds) < 1:
|
||||||
return (0,t)
|
return (0,t)
|
||||||
@ -268,8 +506,10 @@ class ImageView(QtGui.QWidget):
|
|||||||
return ind, t
|
return ind, t
|
||||||
|
|
||||||
def whiteLevel(self):
|
def whiteLevel(self):
|
||||||
return self.levelMin + (self.levelMax-self.levelMin) * self.ui.whiteSlider.value() / self.ui.whiteSlider.maximum()
|
return self.levelMin + (self.levelMax-self.levelMin) * self.ui.gradientWidget.tickValue(self.ticks[1])
|
||||||
|
#return self.levelMin + (self.levelMax-self.levelMin) * self.ui.whiteSlider.value() / self.ui.whiteSlider.maximum()
|
||||||
|
|
||||||
def blackLevel(self):
|
def blackLevel(self):
|
||||||
return self.levelMin + ((self.levelMax-self.levelMin) / self.ui.blackSlider.maximum()) * self.ui.blackSlider.value()
|
return self.levelMin + (self.levelMax-self.levelMin) * self.ui.gradientWidget.tickValue(self.ticks[0])
|
||||||
|
#return self.levelMin + ((self.levelMax-self.levelMin) / self.ui.blackSlider.maximum()) * self.ui.blackSlider.value()
|
||||||
|
|
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
# Form implementation generated from reading ui file 'ImageViewTemplate.ui'
|
# Form implementation generated from reading ui file 'ImageViewTemplate.ui'
|
||||||
#
|
#
|
||||||
# Created: Mon Mar 29 22:40:48 2010
|
# Created: Sat Jul 17 13:05:44 2010
|
||||||
# by: PyQt4 UI code generator 4.6
|
# by: PyQt4 UI code generator 4.5.4
|
||||||
#
|
#
|
||||||
# WARNING! All changes made in this file will be lost!
|
# WARNING! All changes made in this file will be lost!
|
||||||
|
|
||||||
@ -12,7 +12,7 @@ from PyQt4 import QtCore, QtGui
|
|||||||
class Ui_Form(object):
|
class Ui_Form(object):
|
||||||
def setupUi(self, Form):
|
def setupUi(self, Form):
|
||||||
Form.setObjectName("Form")
|
Form.setObjectName("Form")
|
||||||
Form.resize(757, 495)
|
Form.resize(726, 588)
|
||||||
self.verticalLayout = QtGui.QVBoxLayout(Form)
|
self.verticalLayout = QtGui.QVBoxLayout(Form)
|
||||||
self.verticalLayout.setSpacing(0)
|
self.verticalLayout.setSpacing(0)
|
||||||
self.verticalLayout.setMargin(0)
|
self.verticalLayout.setMargin(0)
|
||||||
@ -23,52 +23,45 @@ class Ui_Form(object):
|
|||||||
self.layoutWidget = QtGui.QWidget(self.splitter)
|
self.layoutWidget = QtGui.QWidget(self.splitter)
|
||||||
self.layoutWidget.setObjectName("layoutWidget")
|
self.layoutWidget.setObjectName("layoutWidget")
|
||||||
self.gridLayout = QtGui.QGridLayout(self.layoutWidget)
|
self.gridLayout = QtGui.QGridLayout(self.layoutWidget)
|
||||||
|
self.gridLayout.setMargin(0)
|
||||||
self.gridLayout.setSpacing(0)
|
self.gridLayout.setSpacing(0)
|
||||||
self.gridLayout.setObjectName("gridLayout")
|
self.gridLayout.setObjectName("gridLayout")
|
||||||
self.graphicsView = GraphicsView(self.layoutWidget)
|
self.graphicsView = GraphicsView(self.layoutWidget)
|
||||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
|
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
|
||||||
sizePolicy.setHorizontalStretch(0)
|
sizePolicy.setHorizontalStretch(10)
|
||||||
sizePolicy.setVerticalStretch(0)
|
sizePolicy.setVerticalStretch(10)
|
||||||
sizePolicy.setHeightForWidth(self.graphicsView.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.graphicsView.sizePolicy().hasHeightForWidth())
|
||||||
self.graphicsView.setSizePolicy(sizePolicy)
|
self.graphicsView.setSizePolicy(sizePolicy)
|
||||||
self.graphicsView.setObjectName("graphicsView")
|
self.graphicsView.setObjectName("graphicsView")
|
||||||
self.gridLayout.addWidget(self.graphicsView, 0, 0, 3, 1)
|
self.gridLayout.addWidget(self.graphicsView, 1, 0, 3, 1)
|
||||||
self.blackSlider = QtGui.QSlider(self.layoutWidget)
|
|
||||||
self.blackSlider.setMaximum(4096)
|
|
||||||
self.blackSlider.setOrientation(QtCore.Qt.Vertical)
|
|
||||||
self.blackSlider.setInvertedAppearance(False)
|
|
||||||
self.blackSlider.setInvertedControls(False)
|
|
||||||
self.blackSlider.setTickPosition(QtGui.QSlider.TicksBelow)
|
|
||||||
self.blackSlider.setTickInterval(410)
|
|
||||||
self.blackSlider.setObjectName("blackSlider")
|
|
||||||
self.gridLayout.addWidget(self.blackSlider, 0, 1, 1, 1)
|
|
||||||
self.whiteSlider = QtGui.QSlider(self.layoutWidget)
|
|
||||||
self.whiteSlider.setMaximum(4096)
|
|
||||||
self.whiteSlider.setProperty("value", 4096)
|
|
||||||
self.whiteSlider.setOrientation(QtCore.Qt.Vertical)
|
|
||||||
self.whiteSlider.setObjectName("whiteSlider")
|
|
||||||
self.gridLayout.addWidget(self.whiteSlider, 0, 2, 1, 2)
|
|
||||||
self.label = QtGui.QLabel(self.layoutWidget)
|
|
||||||
self.label.setObjectName("label")
|
|
||||||
self.gridLayout.addWidget(self.label, 1, 1, 1, 1)
|
|
||||||
self.label_2 = QtGui.QLabel(self.layoutWidget)
|
|
||||||
self.label_2.setObjectName("label_2")
|
|
||||||
self.gridLayout.addWidget(self.label_2, 1, 2, 1, 1)
|
|
||||||
self.roiBtn = QtGui.QPushButton(self.layoutWidget)
|
self.roiBtn = QtGui.QPushButton(self.layoutWidget)
|
||||||
self.roiBtn.setMaximumSize(QtCore.QSize(40, 16777215))
|
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(1)
|
||||||
|
sizePolicy.setHeightForWidth(self.roiBtn.sizePolicy().hasHeightForWidth())
|
||||||
|
self.roiBtn.setSizePolicy(sizePolicy)
|
||||||
|
self.roiBtn.setMaximumSize(QtCore.QSize(30, 16777215))
|
||||||
self.roiBtn.setCheckable(True)
|
self.roiBtn.setCheckable(True)
|
||||||
self.roiBtn.setObjectName("roiBtn")
|
self.roiBtn.setObjectName("roiBtn")
|
||||||
self.gridLayout.addWidget(self.roiBtn, 2, 1, 1, 3)
|
self.gridLayout.addWidget(self.roiBtn, 3, 3, 1, 1)
|
||||||
self.timeSlider = QtGui.QSlider(self.layoutWidget)
|
self.gradientWidget = GradientWidget(self.layoutWidget)
|
||||||
self.timeSlider.setMaximum(65535)
|
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Expanding)
|
||||||
self.timeSlider.setOrientation(QtCore.Qt.Horizontal)
|
sizePolicy.setHorizontalStretch(0)
|
||||||
self.timeSlider.setObjectName("timeSlider")
|
sizePolicy.setVerticalStretch(100)
|
||||||
self.gridLayout.addWidget(self.timeSlider, 4, 0, 1, 1)
|
sizePolicy.setHeightForWidth(self.gradientWidget.sizePolicy().hasHeightForWidth())
|
||||||
|
self.gradientWidget.setSizePolicy(sizePolicy)
|
||||||
|
self.gradientWidget.setObjectName("gradientWidget")
|
||||||
|
self.gridLayout.addWidget(self.gradientWidget, 1, 3, 1, 1)
|
||||||
self.normBtn = QtGui.QPushButton(self.layoutWidget)
|
self.normBtn = QtGui.QPushButton(self.layoutWidget)
|
||||||
self.normBtn.setMaximumSize(QtCore.QSize(50, 16777215))
|
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(1)
|
||||||
|
sizePolicy.setHeightForWidth(self.normBtn.sizePolicy().hasHeightForWidth())
|
||||||
|
self.normBtn.setSizePolicy(sizePolicy)
|
||||||
|
self.normBtn.setMaximumSize(QtCore.QSize(30, 16777215))
|
||||||
self.normBtn.setCheckable(True)
|
self.normBtn.setCheckable(True)
|
||||||
self.normBtn.setObjectName("normBtn")
|
self.normBtn.setObjectName("normBtn")
|
||||||
self.gridLayout.addWidget(self.normBtn, 4, 1, 1, 2)
|
self.gridLayout.addWidget(self.normBtn, 2, 3, 1, 1)
|
||||||
self.normGroup = QtGui.QGroupBox(self.layoutWidget)
|
self.normGroup = QtGui.QGroupBox(self.layoutWidget)
|
||||||
self.normGroup.setObjectName("normGroup")
|
self.normGroup.setObjectName("normGroup")
|
||||||
self.gridLayout_2 = QtGui.QGridLayout(self.normGroup)
|
self.gridLayout_2 = QtGui.QGridLayout(self.normGroup)
|
||||||
@ -102,44 +95,28 @@ class Ui_Form(object):
|
|||||||
font.setBold(True)
|
font.setBold(True)
|
||||||
self.label_4.setFont(font)
|
self.label_4.setFont(font)
|
||||||
self.label_4.setObjectName("label_4")
|
self.label_4.setObjectName("label_4")
|
||||||
self.gridLayout_2.addWidget(self.label_4, 4, 0, 1, 1)
|
self.gridLayout_2.addWidget(self.label_4, 2, 0, 1, 1)
|
||||||
self.normROICheck = QtGui.QCheckBox(self.normGroup)
|
self.normROICheck = QtGui.QCheckBox(self.normGroup)
|
||||||
self.normROICheck.setObjectName("normROICheck")
|
self.normROICheck.setObjectName("normROICheck")
|
||||||
self.gridLayout_2.addWidget(self.normROICheck, 1, 1, 1, 1)
|
self.gridLayout_2.addWidget(self.normROICheck, 1, 1, 1, 1)
|
||||||
self.normStartSlider = QtGui.QSlider(self.normGroup)
|
|
||||||
self.normStartSlider.setMaximum(65535)
|
|
||||||
self.normStartSlider.setOrientation(QtCore.Qt.Horizontal)
|
|
||||||
self.normStartSlider.setObjectName("normStartSlider")
|
|
||||||
self.gridLayout_2.addWidget(self.normStartSlider, 2, 0, 1, 6)
|
|
||||||
self.normStopSlider = QtGui.QSlider(self.normGroup)
|
|
||||||
self.normStopSlider.setMaximum(65535)
|
|
||||||
self.normStopSlider.setOrientation(QtCore.Qt.Horizontal)
|
|
||||||
self.normStopSlider.setObjectName("normStopSlider")
|
|
||||||
self.gridLayout_2.addWidget(self.normStopSlider, 3, 0, 1, 6)
|
|
||||||
self.normXBlurSpin = QtGui.QDoubleSpinBox(self.normGroup)
|
self.normXBlurSpin = QtGui.QDoubleSpinBox(self.normGroup)
|
||||||
self.normXBlurSpin.setObjectName("normXBlurSpin")
|
self.normXBlurSpin.setObjectName("normXBlurSpin")
|
||||||
self.gridLayout_2.addWidget(self.normXBlurSpin, 4, 2, 1, 1)
|
self.gridLayout_2.addWidget(self.normXBlurSpin, 2, 2, 1, 1)
|
||||||
self.label_8 = QtGui.QLabel(self.normGroup)
|
self.label_8 = QtGui.QLabel(self.normGroup)
|
||||||
self.label_8.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
self.label_8.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||||
self.label_8.setObjectName("label_8")
|
self.label_8.setObjectName("label_8")
|
||||||
self.gridLayout_2.addWidget(self.label_8, 4, 1, 1, 1)
|
self.gridLayout_2.addWidget(self.label_8, 2, 1, 1, 1)
|
||||||
self.label_9 = QtGui.QLabel(self.normGroup)
|
self.label_9 = QtGui.QLabel(self.normGroup)
|
||||||
self.label_9.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
self.label_9.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||||
self.label_9.setObjectName("label_9")
|
self.label_9.setObjectName("label_9")
|
||||||
self.gridLayout_2.addWidget(self.label_9, 4, 3, 1, 1)
|
self.gridLayout_2.addWidget(self.label_9, 2, 3, 1, 1)
|
||||||
self.normYBlurSpin = QtGui.QDoubleSpinBox(self.normGroup)
|
self.normYBlurSpin = QtGui.QDoubleSpinBox(self.normGroup)
|
||||||
self.normYBlurSpin.setObjectName("normYBlurSpin")
|
self.normYBlurSpin.setObjectName("normYBlurSpin")
|
||||||
self.gridLayout_2.addWidget(self.normYBlurSpin, 4, 4, 1, 1)
|
self.gridLayout_2.addWidget(self.normYBlurSpin, 2, 4, 1, 1)
|
||||||
self.label_10 = QtGui.QLabel(self.normGroup)
|
self.label_10 = QtGui.QLabel(self.normGroup)
|
||||||
self.label_10.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
self.label_10.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||||
self.label_10.setObjectName("label_10")
|
self.label_10.setObjectName("label_10")
|
||||||
self.gridLayout_2.addWidget(self.label_10, 4, 5, 1, 1)
|
self.gridLayout_2.addWidget(self.label_10, 2, 5, 1, 1)
|
||||||
self.normStopLabel = QtGui.QLabel(self.normGroup)
|
|
||||||
self.normStopLabel.setObjectName("normStopLabel")
|
|
||||||
self.gridLayout_2.addWidget(self.normStopLabel, 3, 6, 1, 1)
|
|
||||||
self.normStartLabel = QtGui.QLabel(self.normGroup)
|
|
||||||
self.normStartLabel.setObjectName("normStartLabel")
|
|
||||||
self.gridLayout_2.addWidget(self.normStartLabel, 2, 6, 1, 1)
|
|
||||||
self.normOffRadio = QtGui.QRadioButton(self.normGroup)
|
self.normOffRadio = QtGui.QRadioButton(self.normGroup)
|
||||||
self.normOffRadio.setChecked(True)
|
self.normOffRadio.setChecked(True)
|
||||||
self.normOffRadio.setObjectName("normOffRadio")
|
self.normOffRadio.setObjectName("normOffRadio")
|
||||||
@ -152,9 +129,14 @@ class Ui_Form(object):
|
|||||||
self.gridLayout_2.addWidget(self.normFrameCheck, 1, 2, 1, 1)
|
self.gridLayout_2.addWidget(self.normFrameCheck, 1, 2, 1, 1)
|
||||||
self.normTBlurSpin = QtGui.QDoubleSpinBox(self.normGroup)
|
self.normTBlurSpin = QtGui.QDoubleSpinBox(self.normGroup)
|
||||||
self.normTBlurSpin.setObjectName("normTBlurSpin")
|
self.normTBlurSpin.setObjectName("normTBlurSpin")
|
||||||
self.gridLayout_2.addWidget(self.normTBlurSpin, 4, 6, 1, 1)
|
self.gridLayout_2.addWidget(self.normTBlurSpin, 2, 6, 1, 1)
|
||||||
self.gridLayout.addWidget(self.normGroup, 5, 0, 1, 4)
|
self.gridLayout.addWidget(self.normGroup, 0, 0, 1, 4)
|
||||||
self.roiPlot = PlotWidget(self.splitter)
|
self.roiPlot = PlotWidget(self.splitter)
|
||||||
|
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.roiPlot.sizePolicy().hasHeightForWidth())
|
||||||
|
self.roiPlot.setSizePolicy(sizePolicy)
|
||||||
self.roiPlot.setMinimumSize(QtCore.QSize(0, 40))
|
self.roiPlot.setMinimumSize(QtCore.QSize(0, 40))
|
||||||
self.roiPlot.setObjectName("roiPlot")
|
self.roiPlot.setObjectName("roiPlot")
|
||||||
self.verticalLayout.addWidget(self.splitter)
|
self.verticalLayout.addWidget(self.splitter)
|
||||||
@ -164,10 +146,8 @@ class Ui_Form(object):
|
|||||||
|
|
||||||
def retranslateUi(self, Form):
|
def retranslateUi(self, Form):
|
||||||
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
|
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.label.setText(QtGui.QApplication.translate("Form", "B", None, QtGui.QApplication.UnicodeUTF8))
|
self.roiBtn.setText(QtGui.QApplication.translate("Form", "R", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.label_2.setText(QtGui.QApplication.translate("Form", "W", None, QtGui.QApplication.UnicodeUTF8))
|
self.normBtn.setText(QtGui.QApplication.translate("Form", "N", 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.normGroup.setTitle(QtGui.QApplication.translate("Form", "Normalization", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.normSubtractRadio.setText(QtGui.QApplication.translate("Form", "Subtract", 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.normDivideRadio.setText(QtGui.QApplication.translate("Form", "Divide", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
@ -178,11 +158,10 @@ class Ui_Form(object):
|
|||||||
self.label_8.setText(QtGui.QApplication.translate("Form", "X", 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_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.label_10.setText(QtGui.QApplication.translate("Form", "T", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.normStopLabel.setText(QtGui.QApplication.translate("Form", "Stop", None, QtGui.QApplication.UnicodeUTF8))
|
|
||||||
self.normStartLabel.setText(QtGui.QApplication.translate("Form", "Start", None, QtGui.QApplication.UnicodeUTF8))
|
|
||||||
self.normOffRadio.setText(QtGui.QApplication.translate("Form", "Off", 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.normTimeRangeCheck.setText(QtGui.QApplication.translate("Form", "Time range", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.normFrameCheck.setText(QtGui.QApplication.translate("Form", "Frame", None, QtGui.QApplication.UnicodeUTF8))
|
self.normFrameCheck.setText(QtGui.QApplication.translate("Form", "Frame", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
|
||||||
from GraphicsView import GraphicsView
|
from GraphicsView import GraphicsView
|
||||||
|
from pyqtgraph.GradientWidget import GradientWidget
|
||||||
from PlotWidget import PlotWidget
|
from PlotWidget import PlotWidget
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>757</width>
|
<width>726</width>
|
||||||
<height>495</height>
|
<height>588</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
@ -27,113 +27,77 @@
|
|||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="layoutWidget">
|
<widget class="QWidget" name="layoutWidget">
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<property name="margin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="0" column="0" rowspan="3">
|
<item row="1" column="0" rowspan="3">
|
||||||
<widget class="GraphicsView" name="graphicsView" native="true">
|
<widget class="GraphicsView" name="graphicsView" native="true">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>10</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>10</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<zorder>normGroup</zorder>
|
|
||||||
<zorder>normGroup</zorder>
|
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="3" column="3">
|
||||||
<widget class="QSlider" name="blackSlider">
|
|
||||||
<property name="maximum">
|
|
||||||
<number>4096</number>
|
|
||||||
</property>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="invertedAppearance">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="invertedControls">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="tickPosition">
|
|
||||||
<enum>QSlider::TicksBelow</enum>
|
|
||||||
</property>
|
|
||||||
<property name="tickInterval">
|
|
||||||
<number>410</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="2" colspan="2">
|
|
||||||
<widget class="QSlider" name="whiteSlider">
|
|
||||||
<property name="maximum">
|
|
||||||
<number>4096</number>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<number>4096</number>
|
|
||||||
</property>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QLabel" name="label">
|
|
||||||
<property name="text">
|
|
||||||
<string>B</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="2">
|
|
||||||
<widget class="QLabel" name="label_2">
|
|
||||||
<property name="text">
|
|
||||||
<string>W</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1" colspan="3">
|
|
||||||
<widget class="QPushButton" name="roiBtn">
|
<widget class="QPushButton" name="roiBtn">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>1</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<property name="maximumSize">
|
<property name="maximumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>40</width>
|
<width>30</width>
|
||||||
<height>16777215</height>
|
<height>16777215</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>ROI</string>
|
<string>R</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="0">
|
<item row="1" column="3">
|
||||||
<widget class="QSlider" name="timeSlider">
|
<widget class="GradientWidget" name="gradientWidget" native="true">
|
||||||
<property name="maximum">
|
<property name="sizePolicy">
|
||||||
<number>65535</number>
|
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||||
</property>
|
<horstretch>0</horstretch>
|
||||||
<property name="orientation">
|
<verstretch>100</verstretch>
|
||||||
<enum>Qt::Horizontal</enum>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="1" colspan="2">
|
<item row="2" column="3">
|
||||||
<widget class="QPushButton" name="normBtn">
|
<widget class="QPushButton" name="normBtn">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>1</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<property name="maximumSize">
|
<property name="maximumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>50</width>
|
<width>30</width>
|
||||||
<height>16777215</height>
|
<height>16777215</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Norm</string>
|
<string>N</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="0" colspan="4">
|
<item row="0" column="0" colspan="4">
|
||||||
<widget class="QGroupBox" name="normGroup">
|
<widget class="QGroupBox" name="normGroup">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Normalization</string>
|
<string>Normalization</string>
|
||||||
@ -188,7 +152,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="0">
|
<item row="2" column="0">
|
||||||
<widget class="QLabel" name="label_4">
|
<widget class="QLabel" name="label_4">
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
@ -208,30 +172,10 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0" colspan="6">
|
<item row="2" column="2">
|
||||||
<widget class="QSlider" name="normStartSlider">
|
|
||||||
<property name="maximum">
|
|
||||||
<number>65535</number>
|
|
||||||
</property>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0" colspan="6">
|
|
||||||
<widget class="QSlider" name="normStopSlider">
|
|
||||||
<property name="maximum">
|
|
||||||
<number>65535</number>
|
|
||||||
</property>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="2">
|
|
||||||
<widget class="QDoubleSpinBox" name="normXBlurSpin"/>
|
<widget class="QDoubleSpinBox" name="normXBlurSpin"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="QLabel" name="label_8">
|
<widget class="QLabel" name="label_8">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>X</string>
|
<string>X</string>
|
||||||
@ -241,7 +185,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="3">
|
<item row="2" column="3">
|
||||||
<widget class="QLabel" name="label_9">
|
<widget class="QLabel" name="label_9">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Y</string>
|
<string>Y</string>
|
||||||
@ -251,10 +195,10 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="4">
|
<item row="2" column="4">
|
||||||
<widget class="QDoubleSpinBox" name="normYBlurSpin"/>
|
<widget class="QDoubleSpinBox" name="normYBlurSpin"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="5">
|
<item row="2" column="5">
|
||||||
<widget class="QLabel" name="label_10">
|
<widget class="QLabel" name="label_10">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>T</string>
|
<string>T</string>
|
||||||
@ -264,20 +208,6 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="6">
|
|
||||||
<widget class="QLabel" name="normStopLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Stop</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="6">
|
|
||||||
<widget class="QLabel" name="normStartLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Start</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="3">
|
<item row="0" column="3">
|
||||||
<widget class="QRadioButton" name="normOffRadio">
|
<widget class="QRadioButton" name="normOffRadio">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@ -302,7 +232,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="6">
|
<item row="2" column="6">
|
||||||
<widget class="QDoubleSpinBox" name="normTBlurSpin"/>
|
<widget class="QDoubleSpinBox" name="normTBlurSpin"/>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
@ -311,6 +241,12 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="PlotWidget" name="roiPlot" native="true">
|
<widget class="PlotWidget" name="roiPlot" native="true">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>0</width>
|
<width>0</width>
|
||||||
@ -323,6 +259,12 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>GradientWidget</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>pyqtgraph.GradientWidget</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>GraphicsView</class>
|
<class>GraphicsView</class>
|
||||||
<extends>QWidget</extends>
|
<extends>QWidget</extends>
|
||||||
|
22
ObjectWorkaround.py
Normal file
22
ObjectWorkaround.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from PyQt4 import QtGui, QtCore
|
||||||
|
|
||||||
|
class QObjectWorkaround:
|
||||||
|
def __init__(self):
|
||||||
|
self._qObj_ = QtCore.QObject()
|
||||||
|
def connect(self, *args):
|
||||||
|
if args[0] is self:
|
||||||
|
return QtCore.QObject.connect(self._qObj_, *args[1:])
|
||||||
|
else:
|
||||||
|
return QtCore.QObject.connect(self._qObj_, *args)
|
||||||
|
def disconnect(self, *args):
|
||||||
|
return QtCore.QObject.disconnect(self._qObj_, *args)
|
||||||
|
def emit(self, *args):
|
||||||
|
return QtCore.QObject.emit(self._qObj_, *args)
|
||||||
|
def blockSignals(self, b):
|
||||||
|
return self._qObj_.blockSignals(b)
|
||||||
|
|
||||||
|
class QGraphicsObject(QtGui.QGraphicsItem, QObjectWorkaround):
|
||||||
|
def __init__(self, *args):
|
||||||
|
QtGui.QGraphicsItem.__init__(self, *args)
|
||||||
|
QObjectWorkaround.__init__(self)
|
157
PlotItem.py
157
PlotItem.py
@ -20,6 +20,8 @@ This class is very heavily featured:
|
|||||||
from graphicsItems import *
|
from graphicsItems import *
|
||||||
from plotConfigTemplate import *
|
from plotConfigTemplate import *
|
||||||
from PyQt4 import QtGui, QtCore, QtSvg
|
from PyQt4 import QtGui, QtCore, QtSvg
|
||||||
|
#from ObjectWorkaround import *
|
||||||
|
#tryWorkaround(QtCore, QtGui)
|
||||||
import weakref
|
import weakref
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -42,7 +44,7 @@ class PlotItem(QtGui.QGraphicsWidget):
|
|||||||
lastFileDir = None
|
lastFileDir = None
|
||||||
managers = {}
|
managers = {}
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None, name=None):
|
||||||
QtGui.QGraphicsWidget.__init__(self, parent)
|
QtGui.QGraphicsWidget.__init__(self, parent)
|
||||||
|
|
||||||
## Set up control buttons
|
## Set up control buttons
|
||||||
@ -56,6 +58,7 @@ class PlotItem(QtGui.QGraphicsWidget):
|
|||||||
for b in [self.ctrlBtn, self.autoBtn]:
|
for b in [self.ctrlBtn, self.autoBtn]:
|
||||||
proxy = QtGui.QGraphicsProxyWidget(self)
|
proxy = QtGui.QGraphicsProxyWidget(self)
|
||||||
proxy.setWidget(b)
|
proxy.setWidget(b)
|
||||||
|
proxy.setAcceptHoverEvents(False)
|
||||||
b.setStyleSheet("background-color: #000000; color: #888; font-size: 6pt")
|
b.setStyleSheet("background-color: #000000; color: #888; font-size: 6pt")
|
||||||
QtCore.QObject.connect(self.ctrlBtn, QtCore.SIGNAL('clicked()'), self.ctrlBtnClicked)
|
QtCore.QObject.connect(self.ctrlBtn, QtCore.SIGNAL('clicked()'), self.ctrlBtnClicked)
|
||||||
QtCore.QObject.connect(self.autoBtn, QtCore.SIGNAL('clicked()'), self.enableAutoScale)
|
QtCore.QObject.connect(self.autoBtn, QtCore.SIGNAL('clicked()'), self.enableAutoScale)
|
||||||
@ -124,7 +127,7 @@ class PlotItem(QtGui.QGraphicsWidget):
|
|||||||
|
|
||||||
|
|
||||||
## Wrap a few methods from viewBox
|
## Wrap a few methods from viewBox
|
||||||
for m in ['setXRange', 'setYRange', 'setRange', 'autoRange', 'viewRect']:
|
for m in ['setXRange', 'setYRange', 'setRange', 'autoRange', 'viewRect', 'setMouseEnabled']:
|
||||||
setattr(self, m, getattr(self.vb, m))
|
setattr(self, m, getattr(self.vb, m))
|
||||||
|
|
||||||
self.items = []
|
self.items = []
|
||||||
@ -178,9 +181,13 @@ class PlotItem(QtGui.QGraphicsWidget):
|
|||||||
QtCore.QObject.connect(c.alphaSlider, QtCore.SIGNAL('valueChanged(int)'), self.updateAlpha)
|
QtCore.QObject.connect(c.alphaSlider, QtCore.SIGNAL('valueChanged(int)'), self.updateAlpha)
|
||||||
QtCore.QObject.connect(c.autoAlphaCheck, QtCore.SIGNAL('toggled(bool)'), self.updateAlpha)
|
QtCore.QObject.connect(c.autoAlphaCheck, QtCore.SIGNAL('toggled(bool)'), self.updateAlpha)
|
||||||
|
|
||||||
|
QtCore.QObject.connect(c.gridGroup, QtCore.SIGNAL('toggled(bool)'), self.updateGrid)
|
||||||
|
QtCore.QObject.connect(c.gridAlphaSlider, QtCore.SIGNAL('valueChanged(int)'), self.updateGrid)
|
||||||
|
|
||||||
QtCore.QObject.connect(c.powerSpectrumGroup, QtCore.SIGNAL('toggled(bool)'), self.updateSpectrumMode)
|
QtCore.QObject.connect(c.powerSpectrumGroup, QtCore.SIGNAL('toggled(bool)'), self.updateSpectrumMode)
|
||||||
QtCore.QObject.connect(c.saveSvgBtn, QtCore.SIGNAL('clicked()'), self.saveSvgClicked)
|
QtCore.QObject.connect(c.saveSvgBtn, QtCore.SIGNAL('clicked()'), self.saveSvgClicked)
|
||||||
QtCore.QObject.connect(c.saveImgBtn, QtCore.SIGNAL('clicked()'), self.saveImgClicked)
|
QtCore.QObject.connect(c.saveImgBtn, QtCore.SIGNAL('clicked()'), self.saveImgClicked)
|
||||||
|
QtCore.QObject.connect(c.saveCsvBtn, QtCore.SIGNAL('clicked()'), self.saveCsvClicked)
|
||||||
|
|
||||||
#QtCore.QObject.connect(c.gridGroup, QtCore.SIGNAL('toggled(bool)'), self.updateGrid)
|
#QtCore.QObject.connect(c.gridGroup, QtCore.SIGNAL('toggled(bool)'), self.updateGrid)
|
||||||
#QtCore.QObject.connect(c.gridAlphaSlider, QtCore.SIGNAL('valueChanged(int)'), self.updateGrid)
|
#QtCore.QObject.connect(c.gridAlphaSlider, QtCore.SIGNAL('valueChanged(int)'), self.updateGrid)
|
||||||
@ -216,6 +223,10 @@ class PlotItem(QtGui.QGraphicsWidget):
|
|||||||
self.showScale('left', True)
|
self.showScale('left', True)
|
||||||
self.showScale('bottom', True)
|
self.showScale('bottom', True)
|
||||||
|
|
||||||
|
if name is not None:
|
||||||
|
self.registerPlot(name)
|
||||||
|
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
if self.manager is not None:
|
if self.manager is not None:
|
||||||
self.manager.removeWidget(self.name)
|
self.manager.removeWidget(self.name)
|
||||||
@ -251,6 +262,13 @@ class PlotItem(QtGui.QGraphicsWidget):
|
|||||||
print " error during update. Referrers are:", refs
|
print " error during update. Referrers are:", refs
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
def updateGrid(self, *args):
|
||||||
|
g = self.ctrl.gridGroup.isChecked()
|
||||||
|
if g:
|
||||||
|
g = self.ctrl.gridAlphaSlider.value()
|
||||||
|
for k in self.scales:
|
||||||
|
self.scales[k]['item'].setGrid(g)
|
||||||
|
|
||||||
def viewGeometry(self):
|
def viewGeometry(self):
|
||||||
"""return the screen geometry of the viewbox"""
|
"""return the screen geometry of the viewbox"""
|
||||||
v = self.scene().views()[0]
|
v = self.scene().views()[0]
|
||||||
@ -261,6 +279,8 @@ class PlotItem(QtGui.QGraphicsWidget):
|
|||||||
return wr
|
return wr
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def viewChanged(self, *args):
|
def viewChanged(self, *args):
|
||||||
self.emit(QtCore.SIGNAL('viewChanged'), *args)
|
self.emit(QtCore.SIGNAL('viewChanged'), *args)
|
||||||
|
|
||||||
@ -273,23 +293,31 @@ class PlotItem(QtGui.QGraphicsWidget):
|
|||||||
def yLinkComboChanged(self):
|
def yLinkComboChanged(self):
|
||||||
self.setYLink(str(self.ctrl.yLinkCombo.currentText()))
|
self.setYLink(str(self.ctrl.yLinkCombo.currentText()))
|
||||||
|
|
||||||
def setXLink(self, plotName=None):
|
def setXLink(self, plot=None):
|
||||||
|
"""Link this plot's X axis to another plot (pass either the PlotItem/PlotWidget or the registered name of the plot)"""
|
||||||
|
if isinstance(plot, basestring):
|
||||||
if self.manager is None:
|
if self.manager is None:
|
||||||
return
|
return
|
||||||
if self.xLinkPlot is not None:
|
if self.xLinkPlot is not None:
|
||||||
self.manager.unlinkX(self, self.xLinkPlot)
|
self.manager.unlinkX(self, self.xLinkPlot)
|
||||||
plot = self.manager.getWidget(plotName)
|
plot = self.manager.getWidget(plot)
|
||||||
|
if not isinstance(plot, PlotItem) and hasattr(plot, 'getPlotItem'):
|
||||||
|
plot = plot.getPlotItem()
|
||||||
self.xLinkPlot = plot
|
self.xLinkPlot = plot
|
||||||
if plot is not None:
|
if plot is not None:
|
||||||
self.setManualXScale()
|
self.setManualXScale()
|
||||||
self.manager.linkX(self, plot)
|
self.manager.linkX(self, plot)
|
||||||
|
|
||||||
def setYLink(self, plotName=None):
|
def setYLink(self, plot=None):
|
||||||
|
"""Link this plot's Y axis to another plot (pass either the PlotItem/PlotWidget or the registered name of the plot)"""
|
||||||
|
if isinstance(plot, basestring):
|
||||||
if self.manager is None:
|
if self.manager is None:
|
||||||
return
|
return
|
||||||
if self.yLinkPlot is not None:
|
if self.yLinkPlot is not None:
|
||||||
self.manager.unlinkY(self, self.yLinkPlot)
|
self.manager.unlinkY(self, self.yLinkPlot)
|
||||||
plot = self.manager.getWidget(plotName)
|
plot = self.manager.getWidget(plot)
|
||||||
|
if not isinstance(plot, PlotItem) and hasattr(plot, 'getPlotItem'):
|
||||||
|
plot = plot.getPlotItem()
|
||||||
self.yLinkPlot = plot
|
self.yLinkPlot = plot
|
||||||
if plot is not None:
|
if plot is not None:
|
||||||
self.setManualYScale()
|
self.setManualYScale()
|
||||||
@ -339,6 +367,8 @@ class PlotItem(QtGui.QGraphicsWidget):
|
|||||||
self.recomputeAverages()
|
self.recomputeAverages()
|
||||||
|
|
||||||
def recomputeAverages(self):
|
def recomputeAverages(self):
|
||||||
|
if not self.ctrl.averageGroup.isChecked():
|
||||||
|
return
|
||||||
for k in self.avgCurves:
|
for k in self.avgCurves:
|
||||||
self.removeItem(self.avgCurves[k][1])
|
self.removeItem(self.avgCurves[k][1])
|
||||||
#Qwt.QwtPlotCurve.detach(self.avgCurves[k][1])
|
#Qwt.QwtPlotCurve.detach(self.avgCurves[k][1])
|
||||||
@ -406,6 +436,8 @@ class PlotItem(QtGui.QGraphicsWidget):
|
|||||||
self.vb.setMouseEnabled(*state)
|
self.vb.setMouseEnabled(*state)
|
||||||
|
|
||||||
def xRangeChanged(self, _, range):
|
def xRangeChanged(self, _, range):
|
||||||
|
if any(isnan(range)) or any(isinf(range)):
|
||||||
|
raise Exception("yRange invalid: %s. Signal came from %s" % (str(range), str(self.sender())))
|
||||||
self.ctrl.xMinText.setText('%0.5g' % range[0])
|
self.ctrl.xMinText.setText('%0.5g' % range[0])
|
||||||
self.ctrl.xMaxText.setText('%0.5g' % range[1])
|
self.ctrl.xMaxText.setText('%0.5g' % range[1])
|
||||||
|
|
||||||
@ -423,6 +455,8 @@ class PlotItem(QtGui.QGraphicsWidget):
|
|||||||
self.emit(QtCore.SIGNAL('xRangeChanged'), self, range)
|
self.emit(QtCore.SIGNAL('xRangeChanged'), self, range)
|
||||||
|
|
||||||
def yRangeChanged(self, _, range):
|
def yRangeChanged(self, _, range):
|
||||||
|
if any(isnan(range)) or any(isinf(range)):
|
||||||
|
raise Exception("yRange invalid: %s. Signal came from %s" % (str(range), str(self.sender())))
|
||||||
self.ctrl.yMinText.setText('%0.5g' % range[0])
|
self.ctrl.yMinText.setText('%0.5g' % range[0])
|
||||||
self.ctrl.yMaxText.setText('%0.5g' % range[1])
|
self.ctrl.yMaxText.setText('%0.5g' % range[1])
|
||||||
|
|
||||||
@ -511,18 +545,25 @@ class PlotItem(QtGui.QGraphicsWidget):
|
|||||||
if not item in self.items:
|
if not item in self.items:
|
||||||
return
|
return
|
||||||
self.items.remove(item)
|
self.items.remove(item)
|
||||||
|
if item.scene() is not None:
|
||||||
self.vb.removeItem(item)
|
self.vb.removeItem(item)
|
||||||
if item in self.curves:
|
if item in self.curves:
|
||||||
self.curves.remove(item)
|
self.curves.remove(item)
|
||||||
self.updateDecimation()
|
self.updateDecimation()
|
||||||
self.updateParamList()
|
self.updateParamList()
|
||||||
QtCore.QObject.connect(item, QtCore.SIGNAL('plotChanged'), self.plotChanged)
|
item.connect(QtCore.SIGNAL('plotChanged'), self.plotChanged)
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
for i in self.items[:]:
|
for i in self.items[:]:
|
||||||
self.removeItem(i)
|
self.removeItem(i)
|
||||||
self.avgCurves = {}
|
self.avgCurves = {}
|
||||||
|
|
||||||
|
def clearPlots(self):
|
||||||
|
for i in self.curves[:]:
|
||||||
|
self.removeItem(i)
|
||||||
|
self.avgCurves = {}
|
||||||
|
|
||||||
|
|
||||||
def plot(self, data=None, x=None, clear=False, params=None, pen=None):
|
def plot(self, data=None, x=None, clear=False, params=None, pen=None):
|
||||||
if clear:
|
if clear:
|
||||||
self.clear()
|
self.clear()
|
||||||
@ -549,6 +590,8 @@ class PlotItem(QtGui.QGraphicsWidget):
|
|||||||
return curve
|
return curve
|
||||||
|
|
||||||
def addCurve(self, c, params=None):
|
def addCurve(self, c, params=None):
|
||||||
|
if params is None:
|
||||||
|
params = {}
|
||||||
c.setMeta(params)
|
c.setMeta(params)
|
||||||
self.curves.append(c)
|
self.curves.append(c)
|
||||||
#Qwt.QwtPlotCurve.attach(c, self)
|
#Qwt.QwtPlotCurve.attach(c, self)
|
||||||
@ -569,7 +612,7 @@ class PlotItem(QtGui.QGraphicsWidget):
|
|||||||
if self.ctrl.averageGroup.isChecked():
|
if self.ctrl.averageGroup.isChecked():
|
||||||
self.addAvgCurve(c)
|
self.addAvgCurve(c)
|
||||||
|
|
||||||
QtCore.QObject.connect(c, QtCore.SIGNAL('plotChanged'), self.plotChanged)
|
c.connect(QtCore.SIGNAL('plotChanged'), self.plotChanged)
|
||||||
self.plotChanged()
|
self.plotChanged()
|
||||||
|
|
||||||
def plotChanged(self, curve=None):
|
def plotChanged(self, curve=None):
|
||||||
@ -587,7 +630,7 @@ class PlotItem(QtGui.QGraphicsWidget):
|
|||||||
mn = cmn
|
mn = cmn
|
||||||
if mx is None or cmx > mx:
|
if mx is None or cmx > mx:
|
||||||
mx = cmx
|
mx = cmx
|
||||||
if mn is None or mx is None:
|
if mn is None or mx is None or any(isnan([mn, mx])) or any(isinf([mn, mx])):
|
||||||
continue
|
continue
|
||||||
if mn == mx:
|
if mn == mx:
|
||||||
mn -= 1
|
mn -= 1
|
||||||
@ -632,24 +675,58 @@ class PlotItem(QtGui.QGraphicsWidget):
|
|||||||
if fileName is None:
|
if fileName is None:
|
||||||
fileName = QtGui.QFileDialog.getSaveFileName()
|
fileName = QtGui.QFileDialog.getSaveFileName()
|
||||||
fileName = str(fileName)
|
fileName = str(fileName)
|
||||||
|
PlotItem.lastFileDir = os.path.dirname(fileName)
|
||||||
|
|
||||||
self.svg = QtSvg.QSvgGenerator()
|
self.svg = QtSvg.QSvgGenerator()
|
||||||
self.svg.setFileName(fileName)
|
self.svg.setFileName(fileName)
|
||||||
res = 120.
|
res = 120.
|
||||||
self.svg.setResolution(res)
|
#bounds = self.mapRectToScene(self.boundingRect())
|
||||||
self.svg.setSize(QtCore.QSize(self.size().width(), self.size().height()))
|
view = self.scene().views()[0]
|
||||||
painter = QtGui.QPainter(self.svg)
|
bounds = view.viewport().rect()
|
||||||
#self.scene().render(painter, QtCore.QRectF(), self.mapRectToScene(self.boundingRect()))
|
bounds = QtCore.QRectF(0, 0, bounds.width(), bounds.height())
|
||||||
items = self.scene().items()
|
|
||||||
self.scene().views()[0].drawItems(painter, len(items), items)
|
|
||||||
|
|
||||||
|
self.svg.setResolution(res)
|
||||||
|
#self.svg.setSize(QtCore.QSize(self.size().width(), self.size().height()))
|
||||||
|
self.svg.setViewBox(bounds)
|
||||||
|
|
||||||
|
self.svg.setSize(QtCore.QSize(bounds.width(), bounds.height()))
|
||||||
|
|
||||||
|
painter = QtGui.QPainter(self.svg)
|
||||||
|
#self.scene().render(painter, QtCore.QRectF(), view.mapToScene(bounds).boundingRect())
|
||||||
|
|
||||||
|
#items = self.scene().items()
|
||||||
|
#self.scene().views()[0].drawItems(painter, len(items), items)
|
||||||
|
|
||||||
|
#print view, type(view)
|
||||||
|
view.render(painter, bounds)
|
||||||
|
|
||||||
|
painter.end()
|
||||||
|
|
||||||
|
## Workaround to set pen widths correctly
|
||||||
|
import re
|
||||||
|
data = open(fileName).readlines()
|
||||||
|
for i in range(len(data)):
|
||||||
|
line = data[i]
|
||||||
|
m = re.match(r'(<g .*)stroke-width="1"(.*transform="matrix\(([^\)]+)\)".*)', line)
|
||||||
|
if m is not None:
|
||||||
|
#print "Matched group:", line
|
||||||
|
g = m.groups()
|
||||||
|
matrix = map(float, g[2].split(','))
|
||||||
|
#print "matrix:", matrix
|
||||||
|
scale = max(abs(matrix[0]), abs(matrix[3]))
|
||||||
|
if scale == 0 or scale == 1.0:
|
||||||
|
continue
|
||||||
|
data[i] = g[0] + ' stroke-width="%0.2g" ' % (1.0/scale) + g[1] + '\n'
|
||||||
|
#print "old line:", line
|
||||||
|
#print "new line:", data[i]
|
||||||
|
open(fileName, 'w').write(''.join(data))
|
||||||
|
|
||||||
|
|
||||||
def writeImage(self, fileName=None):
|
def writeImage(self, fileName=None):
|
||||||
if fileName is None:
|
if fileName is None:
|
||||||
fileName = QtGui.QFileDialog.getSaveFileName()
|
fileName = QtGui.QFileDialog.getSaveFileName()
|
||||||
fileName = str(fileName)
|
fileName = str(fileName)
|
||||||
|
PlotItem.lastFileDir = os.path.dirname(fileName)
|
||||||
self.png = QtGui.QImage(int(self.size().width()), int(self.size().height()), QtGui.QImage.Format_ARGB32)
|
self.png = QtGui.QImage(int(self.size().width()), int(self.size().height()), QtGui.QImage.Format_ARGB32)
|
||||||
painter = QtGui.QPainter(self.png)
|
painter = QtGui.QPainter(self.png)
|
||||||
painter.setRenderHints(painter.Antialiasing | painter.TextAntialiasing)
|
painter.setRenderHints(painter.Antialiasing | painter.TextAntialiasing)
|
||||||
@ -657,6 +734,29 @@ class PlotItem(QtGui.QGraphicsWidget):
|
|||||||
painter.end()
|
painter.end()
|
||||||
self.png.save(fileName)
|
self.png.save(fileName)
|
||||||
|
|
||||||
|
def writeCsv(self, fileName=None):
|
||||||
|
if fileName is None:
|
||||||
|
fileName = QtGui.QFileDialog.getSaveFileName()
|
||||||
|
fileName = str(fileName)
|
||||||
|
PlotItem.lastFileDir = os.path.dirname(fileName)
|
||||||
|
|
||||||
|
fd = open(fileName, 'w')
|
||||||
|
data = [c.getData() for c in self.curves]
|
||||||
|
i = 0
|
||||||
|
while True:
|
||||||
|
done = True
|
||||||
|
for d in data:
|
||||||
|
if i < len(d[0]):
|
||||||
|
fd.write('%g,%g,'%(d[0][i], d[1][i]))
|
||||||
|
done = False
|
||||||
|
else:
|
||||||
|
fd.write(' , ,')
|
||||||
|
fd.write('\n')
|
||||||
|
if done:
|
||||||
|
break
|
||||||
|
i += 1
|
||||||
|
fd.close()
|
||||||
|
|
||||||
|
|
||||||
def saveState(self):
|
def saveState(self):
|
||||||
if not HAVE_WIDGETGROUP:
|
if not HAVE_WIDGETGROUP:
|
||||||
@ -672,8 +772,18 @@ class PlotItem(QtGui.QGraphicsWidget):
|
|||||||
raise Exception("State save/restore requires WidgetGroup class.")
|
raise Exception("State save/restore requires WidgetGroup class.")
|
||||||
if 'paramList' in state:
|
if 'paramList' in state:
|
||||||
self.paramList = state['paramList'].copy()
|
self.paramList = state['paramList'].copy()
|
||||||
|
|
||||||
self.stateGroup.setState(state)
|
self.stateGroup.setState(state)
|
||||||
|
self.updateSpectrumMode()
|
||||||
|
self.updateDownsampling()
|
||||||
|
self.updateAlpha()
|
||||||
|
self.updateDecimation()
|
||||||
|
|
||||||
|
self.stateGroup.setState(state)
|
||||||
|
self.updateXScale()
|
||||||
|
self.updateYScale()
|
||||||
self.updateParamList()
|
self.updateParamList()
|
||||||
|
|
||||||
#print "\nRESTORE %s:\n" % str(self.name), state
|
#print "\nRESTORE %s:\n" % str(self.name), state
|
||||||
#print "Restoring state. averageGroup.isChecked(): %s state: %s" % (str(self.ctrl.averageGroup.isChecked()), str(state['averageGroup']))
|
#print "Restoring state. averageGroup.isChecked(): %s state: %s" % (str(self.ctrl.averageGroup.isChecked()), str(state['averageGroup']))
|
||||||
#avg = self.ctrl.averageGroup.isChecked()
|
#avg = self.ctrl.averageGroup.isChecked()
|
||||||
@ -787,7 +897,6 @@ class PlotItem(QtGui.QGraphicsWidget):
|
|||||||
self.mouseScreenPos = ev.screenPos()
|
self.mouseScreenPos = ev.screenPos()
|
||||||
|
|
||||||
def ctrlBtnClicked(self):
|
def ctrlBtnClicked(self):
|
||||||
#print self.mousePos
|
|
||||||
self.ctrlMenu.popup(self.mouseScreenPos)
|
self.ctrlMenu.popup(self.mouseScreenPos)
|
||||||
|
|
||||||
#def _checkLabelKey(self, key):
|
#def _checkLabelKey(self, key):
|
||||||
@ -923,6 +1032,8 @@ class PlotItem(QtGui.QGraphicsWidget):
|
|||||||
#self.fileDialog.setDirectory(PlotItem.lastFileDir)
|
#self.fileDialog.setDirectory(PlotItem.lastFileDir)
|
||||||
self.fileDialog.setFileMode(QtGui.QFileDialog.AnyFile)
|
self.fileDialog.setFileMode(QtGui.QFileDialog.AnyFile)
|
||||||
self.fileDialog.setAcceptMode(QtGui.QFileDialog.AcceptSave)
|
self.fileDialog.setAcceptMode(QtGui.QFileDialog.AcceptSave)
|
||||||
|
if PlotItem.lastFileDir is not None:
|
||||||
|
self.fileDialog.setDirectory(PlotItem.lastFileDir)
|
||||||
self.fileDialog.show()
|
self.fileDialog.show()
|
||||||
QtCore.QObject.connect(self.fileDialog, QtCore.SIGNAL('fileSelected(const QString)'), self.writeSvg)
|
QtCore.QObject.connect(self.fileDialog, QtCore.SIGNAL('fileSelected(const QString)'), self.writeSvg)
|
||||||
|
|
||||||
@ -934,11 +1045,23 @@ class PlotItem(QtGui.QGraphicsWidget):
|
|||||||
self.fileDialog = QtGui.QFileDialog()
|
self.fileDialog = QtGui.QFileDialog()
|
||||||
#if PlotItem.lastFileDir is not None:
|
#if PlotItem.lastFileDir is not None:
|
||||||
#self.fileDialog.setDirectory(PlotItem.lastFileDir)
|
#self.fileDialog.setDirectory(PlotItem.lastFileDir)
|
||||||
|
if PlotItem.lastFileDir is not None:
|
||||||
|
self.fileDialog.setDirectory(PlotItem.lastFileDir)
|
||||||
self.fileDialog.setFileMode(QtGui.QFileDialog.AnyFile)
|
self.fileDialog.setFileMode(QtGui.QFileDialog.AnyFile)
|
||||||
self.fileDialog.setAcceptMode(QtGui.QFileDialog.AcceptSave)
|
self.fileDialog.setAcceptMode(QtGui.QFileDialog.AcceptSave)
|
||||||
self.fileDialog.show()
|
self.fileDialog.show()
|
||||||
QtCore.QObject.connect(self.fileDialog, QtCore.SIGNAL('fileSelected(const QString)'), self.writeImage)
|
QtCore.QObject.connect(self.fileDialog, QtCore.SIGNAL('fileSelected(const QString)'), self.writeImage)
|
||||||
|
|
||||||
|
def saveCsvClicked(self):
|
||||||
|
self.fileDialog = QtGui.QFileDialog()
|
||||||
|
#if PlotItem.lastFileDir is not None:
|
||||||
|
#self.fileDialog.setDirectory(PlotItem.lastFileDir)
|
||||||
|
if PlotItem.lastFileDir is not None:
|
||||||
|
self.fileDialog.setDirectory(PlotItem.lastFileDir)
|
||||||
|
self.fileDialog.setFileMode(QtGui.QFileDialog.AnyFile)
|
||||||
|
self.fileDialog.setAcceptMode(QtGui.QFileDialog.AcceptSave)
|
||||||
|
self.fileDialog.show()
|
||||||
|
QtCore.QObject.connect(self.fileDialog, QtCore.SIGNAL('fileSelected(const QString)'), self.writeCsv)
|
||||||
#def imgFileSelected(self, fileName):
|
#def imgFileSelected(self, fileName):
|
||||||
##PlotWidget.lastFileDir = os.path.split(fileName)[0]
|
##PlotWidget.lastFileDir = os.path.split(fileName)[0]
|
||||||
#self.writeImage(str(fileName))
|
#self.writeImage(str(fileName))
|
||||||
|
@ -11,17 +11,26 @@ import exceptions
|
|||||||
|
|
||||||
class PlotWidget(GraphicsView):
|
class PlotWidget(GraphicsView):
|
||||||
"""Widget implementing a graphicsView with a single PlotItem inside."""
|
"""Widget implementing a graphicsView with a single PlotItem inside."""
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None, **kargs):
|
||||||
GraphicsView.__init__(self, parent)
|
GraphicsView.__init__(self, parent)
|
||||||
self.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
|
self.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
|
||||||
self.enableMouse(False)
|
self.enableMouse(False)
|
||||||
self.plotItem = PlotItem()
|
self.plotItem = PlotItem(**kargs)
|
||||||
self.setCentralItem(self.plotItem)
|
self.setCentralItem(self.plotItem)
|
||||||
## Explicitly wrap methods from plotItem
|
## Explicitly wrap methods from plotItem
|
||||||
for m in ['addItem', 'autoRange', 'clear']:
|
for m in ['addItem', 'removeItem', 'autoRange', 'clear', 'setXRange', 'setYRange']:
|
||||||
setattr(self, m, getattr(self.plotItem, m))
|
setattr(self, m, getattr(self.plotItem, m))
|
||||||
QtCore.QObject.connect(self.plotItem, QtCore.SIGNAL('viewChanged'), self.viewChanged)
|
QtCore.QObject.connect(self.plotItem, QtCore.SIGNAL('viewChanged'), self.viewChanged)
|
||||||
|
|
||||||
|
#def __dtor__(self):
|
||||||
|
##print "Called plotWidget sip destructor"
|
||||||
|
#self.quit()
|
||||||
|
|
||||||
|
|
||||||
|
def quit(self):
|
||||||
|
self.plotItem.clear()
|
||||||
|
self.scene().clear()
|
||||||
|
|
||||||
def __getattr__(self, attr): ## implicitly wrap methods from plotItem
|
def __getattr__(self, attr): ## implicitly wrap methods from plotItem
|
||||||
if hasattr(self.plotItem, attr):
|
if hasattr(self.plotItem, attr):
|
||||||
m = getattr(self.plotItem, attr)
|
m = getattr(self.plotItem, attr)
|
||||||
@ -41,3 +50,5 @@ class PlotWidget(GraphicsView):
|
|||||||
def restoreState(self, state):
|
def restoreState(self, state):
|
||||||
return self.plotItem.restoreState(state)
|
return self.plotItem.restoreState(state)
|
||||||
|
|
||||||
|
def getPlotItem(self):
|
||||||
|
return self.plotItem
|
@ -4,7 +4,7 @@ import sys, os
|
|||||||
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..'))
|
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..'))
|
||||||
|
|
||||||
from pyqtgraph.ImageView import *
|
from pyqtgraph.ImageView import *
|
||||||
from numpy import random
|
from numpy import random, linspace
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
from scipy.ndimage import *
|
from scipy.ndimage import *
|
||||||
|
|
||||||
@ -17,14 +17,27 @@ win.setCentralWidget(imv)
|
|||||||
win.show()
|
win.show()
|
||||||
|
|
||||||
## Create random 3D data set
|
## Create random 3D data set
|
||||||
img = gaussian_filter(random.random((200, 200)), (5, 5)) * 5
|
img = gaussian_filter(random.normal(size=(200, 200)), (5, 5)) * 20 + 100
|
||||||
data = random.random((100, 200, 200))
|
img = img[newaxis,:,:]
|
||||||
data += img
|
decay = exp(-linspace(0,0.3,100))[:,newaxis,newaxis]
|
||||||
for i in range(data.shape[0]):
|
data = random.normal(size=(100, 200, 200))
|
||||||
data[i] += exp(-(2.*i)/data.shape[0])
|
data += img * decay
|
||||||
data += 10
|
|
||||||
|
#for i in range(data.shape[0]):
|
||||||
|
#data[i] += 10*exp(-(2.*i)/data.shape[0])
|
||||||
|
data += 2
|
||||||
|
|
||||||
|
## Add time-varying signal
|
||||||
|
sig = zeros(data.shape[0])
|
||||||
|
sig[30:] += exp(-linspace(1,10, 70))
|
||||||
|
sig[40:] += exp(-linspace(1,10, 60))
|
||||||
|
sig[70:] += exp(-linspace(1,10, 30))
|
||||||
|
|
||||||
|
sig = sig[:,newaxis,newaxis] * 3
|
||||||
|
data[:,50:60,50:60] += sig
|
||||||
|
|
||||||
|
|
||||||
## Display the data
|
## Display the data
|
||||||
imv.setImage(data)
|
imv.setImage(data, xvals=linspace(1., 3., data.shape[0]))
|
||||||
|
|
||||||
app.exec_()
|
app.exec_()
|
||||||
|
@ -34,18 +34,26 @@ rect = QtGui.QGraphicsRectItem(QtCore.QRectF(0, 0, 1, 1))
|
|||||||
rect.setPen(QtGui.QPen(QtGui.QColor(100, 200, 100)))
|
rect.setPen(QtGui.QPen(QtGui.QColor(100, 200, 100)))
|
||||||
pw.addItem(rect)
|
pw.addItem(rect)
|
||||||
|
|
||||||
pen = QtGui.QPen(QtGui.QBrush(QtGui.QColor(255, 255, 255, 10)), 5)
|
#pen = QtGui.QPen(QtGui.QBrush(QtGui.QColor(255, 255, 255, 50)), 5)
|
||||||
pen.setCosmetic(True)
|
#pen.setCosmetic(True)
|
||||||
#pen.setJoinStyle(QtCore.Qt.MiterJoin)
|
#pen.setJoinStyle(QtCore.Qt.MiterJoin)
|
||||||
p1.setShadowPen(pen)
|
#p1.setShadowPen(pen)
|
||||||
p1.setPen(QtGui.QPen(QtGui.QColor(255, 255, 255, 50)))
|
p1.setPen(QtGui.QPen(QtGui.QColor(255, 255, 255)))
|
||||||
|
|
||||||
#l1 = QtGui.QGraphicsLineItem(0, 2, 2, 3)
|
#l1 = QtGui.QGraphicsLineItem(0, 2, 2, 3)
|
||||||
#l1.setPen(QtGui.QPen(QtGui.QColor(255,0,0)))
|
#l1.setPen(QtGui.QPen(QtGui.QColor(255,0,0)))
|
||||||
l2 = InfiniteLine(pw, 1.5, 0)
|
|
||||||
|
#l2 = InfiniteLine(pw2, 1.5, 90, movable=True)
|
||||||
|
#
|
||||||
|
#lr1 = LinearRegionItem(pw2, 'vertical', [1.1, 1.3])
|
||||||
|
#pw2.addItem(lr1)
|
||||||
|
#lr2 = LinearRegionItem(pw2, 'horizontal', [50, 100])
|
||||||
|
#pw2.addItem(lr2)
|
||||||
|
|
||||||
|
|
||||||
#l3 = InfiniteLine(pw, [1.5, 1.5], 45)
|
#l3 = InfiniteLine(pw, [1.5, 1.5], 45)
|
||||||
#pw.addItem(l1)
|
#pw.addItem(l1)
|
||||||
pw.addItem(l2)
|
#pw2.addItem(l2)
|
||||||
#pw.addItem(l3)
|
#pw.addItem(l3)
|
||||||
|
|
||||||
pw3.plot(array([100000]*100))
|
pw3.plot(array([100000]*100))
|
||||||
@ -72,12 +80,14 @@ updateData()
|
|||||||
pw.autoRange()
|
pw.autoRange()
|
||||||
|
|
||||||
t = QtCore.QTimer()
|
t = QtCore.QTimer()
|
||||||
|
|
||||||
QtCore.QObject.connect(t, QtCore.SIGNAL('timeout()'), updateData)
|
QtCore.QObject.connect(t, QtCore.SIGNAL('timeout()'), updateData)
|
||||||
t.start(50)
|
t.start(50)
|
||||||
|
|
||||||
|
|
||||||
for i in range(0, 5):
|
for i in range(0, 5):
|
||||||
for j in range(0, 3):
|
for j in range(0, 3):
|
||||||
yd, xd = rand(10000)
|
yd, xd = rand(10000)
|
||||||
pw2.plot(yd*(j+1), xd, params={'iter': i, 'val': j})
|
pw2.plot(yd*(j+1), xd, params={'iter': i, 'val': j})
|
||||||
|
|
||||||
app.exec_()
|
#app.exec_()
|
||||||
|
@ -19,7 +19,7 @@ class Win(QtGui.QMainWindow):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
w = Win()
|
w = Win()
|
||||||
v = GraphicsView()
|
v = GraphicsView(useOpenGL=False)
|
||||||
v.invertY(True)
|
v.invertY(True)
|
||||||
v.setAspectLocked(True)
|
v.setAspectLocked(True)
|
||||||
v.enableMouse(True)
|
v.enableMouse(True)
|
||||||
@ -72,6 +72,9 @@ elroi = EllipseROI([110, 10], [30, 20])
|
|||||||
s.addItem(elroi)
|
s.addItem(elroi)
|
||||||
croi = CircleROI([110, 50], [20, 20])
|
croi = CircleROI([110, 50], [20, 20])
|
||||||
s.addItem(croi)
|
s.addItem(croi)
|
||||||
|
troi = PolygonROI([[0,0], [1,0], [0,1]])
|
||||||
|
s.addItem(troi)
|
||||||
|
|
||||||
|
|
||||||
def updateImg(roi):
|
def updateImg(roi):
|
||||||
global im1, im2, im3, im4, arr
|
global im1, im2, im3, im4, arr
|
||||||
@ -80,11 +83,11 @@ def updateImg(roi):
|
|||||||
arr2 = roi.getArrayRegion(arr, img=im2)
|
arr2 = roi.getArrayRegion(arr, img=im2)
|
||||||
im4.updateImage(arr2, autoRange=True)
|
im4.updateImage(arr2, autoRange=True)
|
||||||
|
|
||||||
roi.connect(QtCore.SIGNAL('regionChanged'), lambda: updateImg(roi))
|
roi.connect(roi, QtCore.SIGNAL('regionChanged'), lambda: updateImg(roi))
|
||||||
roi2.connect(QtCore.SIGNAL('regionChanged'), lambda: updateImg(roi2))
|
roi2.connect(roi2, QtCore.SIGNAL('regionChanged'), lambda: updateImg(roi2))
|
||||||
croi.connect(QtCore.SIGNAL('regionChanged'), lambda: updateImg(croi))
|
croi.connect(croi, QtCore.SIGNAL('regionChanged'), lambda: updateImg(croi))
|
||||||
elroi.connect(QtCore.SIGNAL('regionChanged'), lambda: updateImg(elroi))
|
elroi.connect(elroi, QtCore.SIGNAL('regionChanged'), lambda: updateImg(elroi))
|
||||||
mlroi.connect(QtCore.SIGNAL('regionChanged'), lambda: updateImg(mlroi))
|
mlroi.connect(mlroi, QtCore.SIGNAL('regionChanged'), lambda: updateImg(mlroi))
|
||||||
|
|
||||||
|
|
||||||
v.setRange(QtCore.QRect(-2, -2, 220, 220))
|
v.setRange(QtCore.QRect(-2, -2, 220, 220))
|
||||||
|
@ -30,7 +30,30 @@ vb = ViewBox()
|
|||||||
p1 = PlotCurveItem()
|
p1 = PlotCurveItem()
|
||||||
vb.addItem(p1)
|
vb.addItem(p1)
|
||||||
vl.addWidget(gv)
|
vl.addWidget(gv)
|
||||||
rect = QtGui.QGraphicsRectItem(QtCore.QRectF(0, 0, 1, 1))
|
|
||||||
|
class movableRect(QtGui.QGraphicsRectItem):
|
||||||
|
def __init__(self, *args):
|
||||||
|
QtGui.QGraphicsRectItem.__init__(self, *args)
|
||||||
|
self.setAcceptHoverEvents(True)
|
||||||
|
def hoverEnterEvent(self, ev):
|
||||||
|
self.savedPen = self.pen()
|
||||||
|
self.setPen(QtGui.QPen(QtGui.QColor(255, 255, 255)))
|
||||||
|
ev.ignore()
|
||||||
|
def hoverLeaveEvent(self, ev):
|
||||||
|
self.setPen(self.savedPen)
|
||||||
|
ev.ignore()
|
||||||
|
def mousePressEvent(self, ev):
|
||||||
|
if ev.button() == QtCore.Qt.LeftButton:
|
||||||
|
ev.accept()
|
||||||
|
self.pressDelta = self.mapToParent(ev.pos()) - self.pos()
|
||||||
|
else:
|
||||||
|
ev.ignore()
|
||||||
|
def mouseMoveEvent(self, ev):
|
||||||
|
self.setPos(self.mapToParent(ev.pos()) - self.pressDelta)
|
||||||
|
|
||||||
|
|
||||||
|
#rect = QtGui.QGraphicsRectItem(QtCore.QRectF(0, 0, 1, 1))
|
||||||
|
rect = movableRect(QtCore.QRectF(0, 0, 1, 1))
|
||||||
rect.setPen(QtGui.QPen(QtGui.QColor(100, 200, 100)))
|
rect.setPen(QtGui.QPen(QtGui.QColor(100, 200, 100)))
|
||||||
vb.addItem(rect)
|
vb.addItem(rect)
|
||||||
|
|
||||||
@ -67,4 +90,4 @@ t = QtCore.QTimer()
|
|||||||
QtCore.QObject.connect(t, QtCore.SIGNAL('timeout()'), updateData)
|
QtCore.QObject.connect(t, QtCore.SIGNAL('timeout()'), updateData)
|
||||||
t.start(50)
|
t.start(50)
|
||||||
|
|
||||||
app.exec_()
|
#app.exec_()
|
||||||
|
803
graphicsItems.py
803
graphicsItems.py
File diff suppressed because it is too large
Load Diff
@ -8,13 +8,16 @@ Distributed under MIT/X11 license. See license.txt for more infomation.
|
|||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
from PlotWidget import *
|
from PlotWidget import *
|
||||||
from ImageView import *
|
from ImageView import *
|
||||||
|
QAPP = None
|
||||||
class PlotWindow(QtGui.QMainWindow):
|
class PlotWindow(QtGui.QMainWindow):
|
||||||
def __init__(self, title=None):
|
def __init__(self, title=None):
|
||||||
|
if QtGui.QApplication.instance() is None:
|
||||||
|
global QAPP
|
||||||
|
QAPP = QtGui.QApplication([])
|
||||||
QtGui.QMainWindow.__init__(self)
|
QtGui.QMainWindow.__init__(self)
|
||||||
self.cw = PlotWidget()
|
self.cw = PlotWidget()
|
||||||
self.setCentralWidget(self.cw)
|
self.setCentralWidget(self.cw)
|
||||||
for m in ['plot', 'autoRange', 'addItem', 'setLabel', 'clear']:
|
for m in ['plot', 'autoRange', 'addItem', 'removeItem', 'setLabel', 'clear']:
|
||||||
setattr(self, m, getattr(self.cw, m))
|
setattr(self, m, getattr(self.cw, m))
|
||||||
if title is not None:
|
if title is not None:
|
||||||
self.setWindowTitle(title)
|
self.setWindowTitle(title)
|
||||||
@ -22,10 +25,13 @@ class PlotWindow(QtGui.QMainWindow):
|
|||||||
|
|
||||||
class ImageWindow(QtGui.QMainWindow):
|
class ImageWindow(QtGui.QMainWindow):
|
||||||
def __init__(self, title=None):
|
def __init__(self, title=None):
|
||||||
|
if QtGui.QApplication.instance() is None:
|
||||||
|
global QAPP
|
||||||
|
QAPP = QtGui.QApplication([])
|
||||||
QtGui.QMainWindow.__init__(self)
|
QtGui.QMainWindow.__init__(self)
|
||||||
self.cw = ImageView()
|
self.cw = ImageView()
|
||||||
self.setCentralWidget(self.cw)
|
self.setCentralWidget(self.cw)
|
||||||
for m in ['setImage', 'autoRange', 'addItem']:
|
for m in ['setImage', 'autoRange', 'addItem', 'removeItem', 'blackLevel', 'whiteLevel', 'imageItem']:
|
||||||
setattr(self, m, getattr(self.cw, m))
|
setattr(self, m, getattr(self.cw, m))
|
||||||
if title is not None:
|
if title is not None:
|
||||||
self.setWindowTitle(title)
|
self.setWindowTitle(title)
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
# Form implementation generated from reading ui file 'plotConfigTemplate.ui'
|
# Form implementation generated from reading ui file 'plotConfigTemplate.ui'
|
||||||
#
|
#
|
||||||
# Created: Mon Mar 29 22:40:47 2010
|
# Created: Sat Jul 17 00:28:43 2010
|
||||||
# by: PyQt4 UI code generator 4.6
|
# by: PyQt4 UI code generator 4.7.2
|
||||||
#
|
#
|
||||||
# WARNING! All changes made in this file will be lost!
|
# WARNING! All changes made in this file will be lost!
|
||||||
|
|
||||||
@ -12,7 +12,7 @@ from PyQt4 import QtCore, QtGui
|
|||||||
class Ui_Form(object):
|
class Ui_Form(object):
|
||||||
def setupUi(self, Form):
|
def setupUi(self, Form):
|
||||||
Form.setObjectName("Form")
|
Form.setObjectName("Form")
|
||||||
Form.resize(210, 340)
|
Form.resize(250, 340)
|
||||||
Form.setMaximumSize(QtCore.QSize(250, 350))
|
Form.setMaximumSize(QtCore.QSize(250, 350))
|
||||||
self.gridLayout_3 = QtGui.QGridLayout(Form)
|
self.gridLayout_3 = QtGui.QGridLayout(Form)
|
||||||
self.gridLayout_3.setMargin(0)
|
self.gridLayout_3.setMargin(0)
|
||||||
@ -187,6 +187,7 @@ class Ui_Form(object):
|
|||||||
self.verticalLayout_3.addWidget(self.alphaGroup)
|
self.verticalLayout_3.addWidget(self.alphaGroup)
|
||||||
self.gridGroup = QtGui.QGroupBox(self.tab_3)
|
self.gridGroup = QtGui.QGroupBox(self.tab_3)
|
||||||
self.gridGroup.setCheckable(True)
|
self.gridGroup.setCheckable(True)
|
||||||
|
self.gridGroup.setChecked(False)
|
||||||
self.gridGroup.setObjectName("gridGroup")
|
self.gridGroup.setObjectName("gridGroup")
|
||||||
self.verticalLayout_4 = QtGui.QVBoxLayout(self.gridGroup)
|
self.verticalLayout_4 = QtGui.QVBoxLayout(self.gridGroup)
|
||||||
self.verticalLayout_4.setObjectName("verticalLayout_4")
|
self.verticalLayout_4.setObjectName("verticalLayout_4")
|
||||||
@ -227,6 +228,9 @@ class Ui_Form(object):
|
|||||||
self.saveMaBtn = QtGui.QPushButton(self.tab_4)
|
self.saveMaBtn = QtGui.QPushButton(self.tab_4)
|
||||||
self.saveMaBtn.setObjectName("saveMaBtn")
|
self.saveMaBtn.setObjectName("saveMaBtn")
|
||||||
self.gridLayout_6.addWidget(self.saveMaBtn, 2, 0, 1, 1)
|
self.gridLayout_6.addWidget(self.saveMaBtn, 2, 0, 1, 1)
|
||||||
|
self.saveCsvBtn = QtGui.QPushButton(self.tab_4)
|
||||||
|
self.saveCsvBtn.setObjectName("saveCsvBtn")
|
||||||
|
self.gridLayout_6.addWidget(self.saveCsvBtn, 3, 0, 1, 1)
|
||||||
self.gridLayout_7.addLayout(self.gridLayout_6, 0, 1, 1, 1)
|
self.gridLayout_7.addLayout(self.gridLayout_6, 0, 1, 1, 1)
|
||||||
spacerItem2 = QtGui.QSpacerItem(59, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
spacerItem2 = QtGui.QSpacerItem(59, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
||||||
self.gridLayout_7.addItem(spacerItem2, 0, 2, 1, 1)
|
self.gridLayout_7.addItem(spacerItem2, 0, 2, 1, 1)
|
||||||
@ -281,5 +285,6 @@ class Ui_Form(object):
|
|||||||
self.saveSvgBtn.setText(QtGui.QApplication.translate("Form", "SVG", None, QtGui.QApplication.UnicodeUTF8))
|
self.saveSvgBtn.setText(QtGui.QApplication.translate("Form", "SVG", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.saveImgBtn.setText(QtGui.QApplication.translate("Form", "Image", None, QtGui.QApplication.UnicodeUTF8))
|
self.saveImgBtn.setText(QtGui.QApplication.translate("Form", "Image", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.saveMaBtn.setText(QtGui.QApplication.translate("Form", "MetaArray", None, QtGui.QApplication.UnicodeUTF8))
|
self.saveMaBtn.setText(QtGui.QApplication.translate("Form", "MetaArray", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.saveCsvBtn.setText(QtGui.QApplication.translate("Form", "CSV", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_4), QtGui.QApplication.translate("Form", "Save", None, QtGui.QApplication.UnicodeUTF8))
|
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_4), QtGui.QApplication.translate("Form", "Save", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>210</width>
|
<width>250</width>
|
||||||
<height>340</height>
|
<height>340</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
@ -35,7 +35,7 @@
|
|||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>1</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="tab">
|
<widget class="QWidget" name="tab">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
@ -419,6 +419,9 @@
|
|||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QSlider" name="gridAlphaSlider">
|
<widget class="QSlider" name="gridAlphaSlider">
|
||||||
@ -514,6 +517,13 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QPushButton" name="saveCsvBtn">
|
||||||
|
<property name="text">
|
||||||
|
<string>CSV</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="2">
|
<item row="0" column="2">
|
||||||
|
100
widgets.py
100
widgets.py
@ -10,25 +10,26 @@ of array data from ImageItems.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui, QtOpenGL, QtSvg
|
from PyQt4 import QtCore, QtGui, QtOpenGL, QtSvg
|
||||||
from numpy import array, arccos, dot, pi, zeros, vstack, ubyte, fromfunction, ceil, floor
|
from numpy import array, arccos, dot, pi, zeros, vstack, ubyte, fromfunction, ceil, floor, arctan2
|
||||||
from numpy.linalg import norm
|
from numpy.linalg import norm
|
||||||
import scipy.ndimage as ndimage
|
import scipy.ndimage as ndimage
|
||||||
from Point import *
|
from Point import *
|
||||||
from math import cos, sin
|
from math import cos, sin
|
||||||
|
from ObjectWorkaround import *
|
||||||
|
|
||||||
def rectStr(r):
|
def rectStr(r):
|
||||||
return "[%f, %f] + [%f, %f]" % (r.x(), r.y(), r.width(), r.height())
|
return "[%f, %f] + [%f, %f]" % (r.x(), r.y(), r.width(), r.height())
|
||||||
|
|
||||||
## Multiple inheritance not allowed in PyQt. Retarded workaround:
|
# Multiple inheritance not allowed in PyQt. Retarded workaround:
|
||||||
class QObjectWorkaround:
|
#class QObjectWorkaround:
|
||||||
def __init__(self):
|
#def __init__(self):
|
||||||
self._qObj_ = QtCore.QObject()
|
#self._qObj_ = QtCore.QObject()
|
||||||
def __getattr__(self, attr):
|
#def __getattr__(self, attr):
|
||||||
if attr == '_qObj_':
|
#if attr == '_qObj_':
|
||||||
raise Exception("QObjectWorkaround not initialized!")
|
#raise Exception("QObjectWorkaround not initialized!")
|
||||||
return getattr(self._qObj_, attr)
|
#return getattr(self._qObj_, attr)
|
||||||
def connect(self, *args):
|
#def connect(self, *args):
|
||||||
return QtCore.QObject.connect(self._qObj_, *args)
|
#return QtCore.QObject.connect(self._qObj_, *args)
|
||||||
|
|
||||||
|
|
||||||
class ROI(QtGui.QGraphicsItem, QObjectWorkaround):
|
class ROI(QtGui.QGraphicsItem, QObjectWorkaround):
|
||||||
@ -46,10 +47,10 @@ class ROI(QtGui.QGraphicsItem, QObjectWorkaround):
|
|||||||
self.state = {'pos': pos, 'size': size, 'angle': angle}
|
self.state = {'pos': pos, 'size': size, 'angle': angle}
|
||||||
self.lastState = None
|
self.lastState = None
|
||||||
self.setPos(pos)
|
self.setPos(pos)
|
||||||
self.rotate(-angle)
|
self.rotate(-angle * 180. / pi)
|
||||||
self.setZValue(10)
|
self.setZValue(10)
|
||||||
|
|
||||||
self.handleSize = 4
|
self.handleSize = 5
|
||||||
self.invertible = invertible
|
self.invertible = invertible
|
||||||
self.maxBounds = maxBounds
|
self.maxBounds = maxBounds
|
||||||
|
|
||||||
@ -93,6 +94,10 @@ class ROI(QtGui.QGraphicsItem, QObjectWorkaround):
|
|||||||
pos = Point(pos)
|
pos = Point(pos)
|
||||||
return self.addHandle({'type': 't', 'pos': pos, 'item': item})
|
return self.addHandle({'type': 't', 'pos': pos, 'item': item})
|
||||||
|
|
||||||
|
def addFreeHandle(self, pos, axes=None, item=None):
|
||||||
|
pos = Point(pos)
|
||||||
|
return self.addHandle({'type': 'f', 'pos': pos, 'item': item})
|
||||||
|
|
||||||
def addScaleHandle(self, pos, center, axes=None, item=None):
|
def addScaleHandle(self, pos, center, axes=None, item=None):
|
||||||
pos = Point(pos)
|
pos = Point(pos)
|
||||||
center = Point(center)
|
center = Point(center)
|
||||||
@ -238,6 +243,9 @@ class ROI(QtGui.QGraphicsItem, QObjectWorkaround):
|
|||||||
snap = Point(self.snapSize, self.snapSize)
|
snap = Point(self.snapSize, self.snapSize)
|
||||||
self.translate(p1-p0, snap=snap, update=False)
|
self.translate(p1-p0, snap=snap, update=False)
|
||||||
|
|
||||||
|
elif h['type'] == 'f':
|
||||||
|
h['item'].setPos(self.mapFromScene(pos))
|
||||||
|
|
||||||
elif h['type'] == 's':
|
elif h['type'] == 's':
|
||||||
#c = h['center']
|
#c = h['center']
|
||||||
#cs = c * self.state['size']
|
#cs = c * self.state['size']
|
||||||
@ -439,11 +447,14 @@ class ROI(QtGui.QGraphicsItem, QObjectWorkaround):
|
|||||||
return QtCore.QRectF(0, 0, self.state['size'][0], self.state['size'][1])
|
return QtCore.QRectF(0, 0, self.state['size'][0], self.state['size'][1])
|
||||||
|
|
||||||
def paint(self, p, opt, widget):
|
def paint(self, p, opt, widget):
|
||||||
|
p.save()
|
||||||
r = self.boundingRect()
|
r = self.boundingRect()
|
||||||
p.setRenderHint(QtGui.QPainter.Antialiasing)
|
p.setRenderHint(QtGui.QPainter.Antialiasing)
|
||||||
p.setPen(self.pen)
|
p.setPen(self.pen)
|
||||||
p.drawRect(r)
|
p.translate(r.left(), r.top())
|
||||||
|
p.scale(r.width(), r.height())
|
||||||
|
p.drawRect(0, 0, 1, 1)
|
||||||
|
p.restore()
|
||||||
|
|
||||||
def getArraySlice(self, data, img, axes=(0,1), returnSlice=True):
|
def getArraySlice(self, data, img, axes=(0,1), returnSlice=True):
|
||||||
"""Return a tuple of slice objects that can be used to slice the region from data covered by this ROI.
|
"""Return a tuple of slice objects that can be used to slice the region from data covered by this ROI.
|
||||||
@ -602,15 +613,21 @@ class Handle(QtGui.QGraphicsItem):
|
|||||||
#print " create item with parent", parent
|
#print " create item with parent", parent
|
||||||
self.bounds = QtCore.QRectF(-1e-10, -1e-10, 2e-10, 2e-10)
|
self.bounds = QtCore.QRectF(-1e-10, -1e-10, 2e-10, 2e-10)
|
||||||
QtGui.QGraphicsItem.__init__(self, parent)
|
QtGui.QGraphicsItem.__init__(self, parent)
|
||||||
|
self.setFlag(self.ItemIgnoresTransformations)
|
||||||
self.setZValue(11)
|
self.setZValue(11)
|
||||||
self.roi = []
|
self.roi = []
|
||||||
self.radius = radius
|
self.radius = radius
|
||||||
self.typ = typ
|
self.typ = typ
|
||||||
self.prepareGeometryChange()
|
self.prepareGeometryChange()
|
||||||
self.pen = pen
|
self.pen = pen
|
||||||
|
self.pen.setWidth(0)
|
||||||
|
self.pen.setCosmetic(True)
|
||||||
if typ == 't':
|
if typ == 't':
|
||||||
self.sides = 4
|
self.sides = 4
|
||||||
self.startAng = pi/4
|
self.startAng = pi/4
|
||||||
|
elif typ == 'f':
|
||||||
|
self.sides = 4
|
||||||
|
self.startAng = pi/4
|
||||||
elif typ == 's':
|
elif typ == 's':
|
||||||
self.sides = 4
|
self.sides = 4
|
||||||
self.startAng = 0
|
self.startAng = 0
|
||||||
@ -660,20 +677,24 @@ class Handle(QtGui.QGraphicsItem):
|
|||||||
r[0].movePoint(r[1], pos, modifiers)
|
r[0].movePoint(r[1], pos, modifiers)
|
||||||
|
|
||||||
def paint(self, p, opt, widget):
|
def paint(self, p, opt, widget):
|
||||||
m = p.transform()
|
## determine rotation of transform
|
||||||
mi = m.inverted()[0]
|
m = self.sceneTransform()
|
||||||
|
#mi = m.inverted()[0]
|
||||||
|
v = m.map(QtCore.QPointF(1, 0)) - m.map(QtCore.QPointF(0, 0))
|
||||||
|
va = arctan2(v.y(), v.x())
|
||||||
|
|
||||||
## Determine length of unit vector in painter's coords
|
## Determine length of unit vector in painter's coords
|
||||||
size = mi.map(Point(self.radius, self.radius)) - mi.map(Point(0, 0))
|
#size = mi.map(Point(self.radius, self.radius)) - mi.map(Point(0, 0))
|
||||||
size = (size.x()*size.x() + size.y() * size.y()) ** 0.5
|
#size = (size.x()*size.x() + size.y() * size.y()) ** 0.5
|
||||||
|
size = self.radius
|
||||||
|
|
||||||
bounds = QtCore.QRectF(-size, -size, size*2, size*2)
|
bounds = QtCore.QRectF(-size, -size, size*2, size*2)
|
||||||
if bounds != self.bounds:
|
if bounds != self.bounds:
|
||||||
self.bounds = bounds
|
self.bounds = bounds
|
||||||
self.prepareGeometryChange()
|
self.prepareGeometryChange()
|
||||||
p.setRenderHint(QtGui.QPainter.Antialiasing)
|
p.setRenderHints(p.Antialiasing, True)
|
||||||
p.setPen(self.pen)
|
p.setPen(self.pen)
|
||||||
ang = self.startAng
|
ang = self.startAng + va
|
||||||
dt = 2*pi / self.sides
|
dt = 2*pi / self.sides
|
||||||
for i in range(0, self.sides):
|
for i in range(0, self.sides):
|
||||||
x1 = size * cos(ang)
|
x1 = size * cos(ang)
|
||||||
@ -757,9 +778,9 @@ class MultiLineROI(QtGui.QGraphicsItem, QObjectWorkaround):
|
|||||||
for l in self.lines:
|
for l in self.lines:
|
||||||
l.translatable = False
|
l.translatable = False
|
||||||
#self.addToGroup(l)
|
#self.addToGroup(l)
|
||||||
l.connect(QtCore.SIGNAL('regionChanged'), self.roiChangedEvent)
|
l.connect(l, QtCore.SIGNAL('regionChanged'), self.roiChangedEvent)
|
||||||
l.connect(QtCore.SIGNAL('regionChangeStarted'), self.roiChangeStartedEvent)
|
l.connect(l, QtCore.SIGNAL('regionChangeStarted'), self.roiChangeStartedEvent)
|
||||||
l.connect(QtCore.SIGNAL('regionChangeFinished'), self.roiChangeFinishedEvent)
|
l.connect(l, QtCore.SIGNAL('regionChangeFinished'), self.roiChangeFinishedEvent)
|
||||||
|
|
||||||
def paint(self, *args):
|
def paint(self, *args):
|
||||||
pass
|
pass
|
||||||
@ -835,3 +856,34 @@ class CircleROI(EllipseROI):
|
|||||||
#self.addTranslateHandle([0.5, 0.5])
|
#self.addTranslateHandle([0.5, 0.5])
|
||||||
self.addScaleHandle([0.5*2.**-0.5 + 0.5, 0.5*2.**-0.5 + 0.5], [0.5, 0.5])
|
self.addScaleHandle([0.5*2.**-0.5 + 0.5, 0.5*2.**-0.5 + 0.5], [0.5, 0.5])
|
||||||
|
|
||||||
|
class PolygonROI(ROI):
|
||||||
|
def __init__(self, positions):
|
||||||
|
ROI.__init__(self, [0,0], [100,100])
|
||||||
|
for p in positions:
|
||||||
|
self.addFreeHandle(p)
|
||||||
|
|
||||||
|
def movePoint(self, *args, **kargs):
|
||||||
|
ROI.movePoint(self, *args, **kargs)
|
||||||
|
self.prepareGeometryChange()
|
||||||
|
|
||||||
|
def paint(self, p, *args):
|
||||||
|
p.setRenderHint(QtGui.QPainter.Antialiasing)
|
||||||
|
p.setPen(self.pen)
|
||||||
|
for i in range(len(self.handles)):
|
||||||
|
h1 = self.handles[i]['item'].pos()
|
||||||
|
h2 = self.handles[i-1]['item'].pos()
|
||||||
|
p.drawLine(h1, h2)
|
||||||
|
|
||||||
|
def boundingRect(self):
|
||||||
|
r = QtCore.QRectF()
|
||||||
|
for h in self.handles:
|
||||||
|
r |= self.mapFromItem(h['item'], h['item'].boundingRect()).boundingRect()
|
||||||
|
return r
|
||||||
|
|
||||||
|
def shape(self):
|
||||||
|
p = QtGui.QPainterPath()
|
||||||
|
p.moveTo(self.handles[0]['item'].pos())
|
||||||
|
for i in range(len(self.handles)):
|
||||||
|
p.lineTo(self.handles[i]['item'].pos())
|
||||||
|
return p
|
||||||
|
|
Loading…
Reference in New Issue
Block a user