Minor updates and bug fixes:
- fixed handling of foreground colors in AxisItem - fixed rare crash caused in AxisItem - fixed improper propagation of key events from SpinBox - many others
This commit is contained in:
parent
bb48f1cb36
commit
0402d08604
@ -182,7 +182,7 @@ def plot(*args, **kargs):
|
|||||||
#if len(args)+len(kargs) > 0:
|
#if len(args)+len(kargs) > 0:
|
||||||
#w.plot(*args, **kargs)
|
#w.plot(*args, **kargs)
|
||||||
|
|
||||||
pwArgList = ['title', 'label', 'name', 'left', 'right', 'top', 'bottom']
|
pwArgList = ['title', 'labels', 'name', 'left', 'right', 'top', 'bottom']
|
||||||
pwArgs = {}
|
pwArgs = {}
|
||||||
dataArgs = {}
|
dataArgs = {}
|
||||||
for k in kargs:
|
for k in kargs:
|
||||||
|
@ -122,7 +122,7 @@ params = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
## Create tree of Parameter objects
|
## Create tree of Parameter objects
|
||||||
p = Parameter(name='params', type='group', children=params)
|
p = Parameter.create(name='params', type='group', children=params)
|
||||||
|
|
||||||
## If anything changes in the tree, print a message
|
## If anything changes in the tree, print a message
|
||||||
def change(param, changes):
|
def change(param, changes):
|
||||||
|
@ -160,7 +160,10 @@ class Flowchart(Node):
|
|||||||
Node.addTerminal(self, term.name(), io=io, renamable=term.isRenamable(), removable=term.isRemovable(), multiable=term.isMultiable())
|
Node.addTerminal(self, term.name(), io=io, renamable=term.isRenamable(), removable=term.isRemovable(), multiable=term.isMultiable())
|
||||||
|
|
||||||
def internalTerminalRemoved(self, node, term):
|
def internalTerminalRemoved(self, node, term):
|
||||||
|
try:
|
||||||
Node.removeTerminal(self, term.name())
|
Node.removeTerminal(self, term.name())
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
def terminalRenamed(self, term, oldName):
|
def terminalRenamed(self, term, oldName):
|
||||||
newName = term.name()
|
newName = term.name()
|
||||||
|
@ -294,6 +294,8 @@ class Node(QtCore.QObject):
|
|||||||
self.removeTerminal(name)
|
self.removeTerminal(name)
|
||||||
for name, opts in state.items():
|
for name, opts in state.items():
|
||||||
if name in self.terminals:
|
if name in self.terminals:
|
||||||
|
term = self[name]
|
||||||
|
term.setOpts(**opts)
|
||||||
continue
|
continue
|
||||||
try:
|
try:
|
||||||
opts = strDict(opts)
|
opts = strDict(opts)
|
||||||
|
@ -86,6 +86,14 @@ class Terminal:
|
|||||||
#c.inputChanged(self)
|
#c.inputChanged(self)
|
||||||
self.recolor()
|
self.recolor()
|
||||||
|
|
||||||
|
def setOpts(self, **opts):
|
||||||
|
self._renamable = opts.get('renamable', self._renamable)
|
||||||
|
self._removable = opts.get('removable', self._removable)
|
||||||
|
self._multiable = opts.get('multiable', self._multiable)
|
||||||
|
if 'multi' in opts:
|
||||||
|
self.setMultiValue(opts['multi'])
|
||||||
|
|
||||||
|
|
||||||
def connected(self, term):
|
def connected(self, term):
|
||||||
"""Called whenever this terminal has been connected to another. (note--this function is called on both terminals)"""
|
"""Called whenever this terminal has been connected to another. (note--this function is called on both terminals)"""
|
||||||
if self.isInput() and term.isOutput():
|
if self.isInput() and term.isOutput():
|
||||||
|
@ -235,6 +235,9 @@ class EvalNode(Node):
|
|||||||
run = "\noutput=fn(**args)\n"
|
run = "\noutput=fn(**args)\n"
|
||||||
text = fn + "\n".join([" "+l for l in str(self.text.toPlainText()).split('\n')]) + run
|
text = fn + "\n".join([" "+l for l in str(self.text.toPlainText()).split('\n')]) + run
|
||||||
exec(text)
|
exec(text)
|
||||||
|
except:
|
||||||
|
print "Error processing node:", self.name()
|
||||||
|
raise
|
||||||
return output
|
return output
|
||||||
|
|
||||||
def saveState(self):
|
def saveState(self):
|
||||||
@ -282,7 +285,7 @@ class ColumnJoinNode(Node):
|
|||||||
|
|
||||||
def addInput(self):
|
def addInput(self):
|
||||||
#print "ColumnJoinNode.addInput called."
|
#print "ColumnJoinNode.addInput called."
|
||||||
term = Node.addInput(self, 'input', renamable=True, removable=True)
|
term = Node.addInput(self, 'input', renamable=True, removable=True, multiable=True)
|
||||||
#print "Node.addInput returned. term:", term
|
#print "Node.addInput returned. term:", term
|
||||||
item = QtGui.QTreeWidgetItem([term.name()])
|
item = QtGui.QTreeWidgetItem([term.name()])
|
||||||
item.term = term
|
item.term = term
|
||||||
@ -323,6 +326,14 @@ class ColumnJoinNode(Node):
|
|||||||
def restoreState(self, state):
|
def restoreState(self, state):
|
||||||
Node.restoreState(self, state)
|
Node.restoreState(self, state)
|
||||||
inputs = self.inputs()
|
inputs = self.inputs()
|
||||||
|
|
||||||
|
## Node.restoreState should have created all of the terminals we need
|
||||||
|
## However: to maintain support for some older flowchart files, we need
|
||||||
|
## to manually add any terminals that were not taken care of.
|
||||||
|
for name in [n for n in state['order'] if n not in inputs]:
|
||||||
|
Node.addInput(self, name, renamable=True, removable=True, multiable=True)
|
||||||
|
inputs = self.inputs()
|
||||||
|
|
||||||
order = [name for name in state['order'] if name in inputs]
|
order = [name for name in state['order'] if name in inputs]
|
||||||
for name in inputs:
|
for name in inputs:
|
||||||
if name not in order:
|
if name not in order:
|
||||||
|
@ -184,13 +184,16 @@ class HistogramDetrend(CtrlNode):
|
|||||||
nodeName = 'HistogramDetrend'
|
nodeName = 'HistogramDetrend'
|
||||||
uiTemplate = [
|
uiTemplate = [
|
||||||
('windowSize', 'intSpin', {'value': 500, 'min': 10, 'max': 1000000, 'suffix': 'pts'}),
|
('windowSize', 'intSpin', {'value': 500, 'min': 10, 'max': 1000000, 'suffix': 'pts'}),
|
||||||
('numBins', 'intSpin', {'value': 50, 'min': 3, 'max': 1000000})
|
('numBins', 'intSpin', {'value': 50, 'min': 3, 'max': 1000000}),
|
||||||
|
('offsetOnly', 'check', {'checked': False}),
|
||||||
]
|
]
|
||||||
|
|
||||||
def processData(self, data):
|
def processData(self, data):
|
||||||
ws = self.ctrls['windowSize'].value()
|
s = self.stateGroup.state()
|
||||||
bn = self.ctrls['numBins'].value()
|
#ws = self.ctrls['windowSize'].value()
|
||||||
return functions.histogramDetrend(data, window=ws, bins=bn)
|
#bn = self.ctrls['numBins'].value()
|
||||||
|
#offset = self.ctrls['offsetOnly'].checked()
|
||||||
|
return functions.histogramDetrend(data, window=s['windowSize'], bins=s['numBins'], offsetOnly=s['offsetOnly'])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -196,8 +196,10 @@ def adaptiveDetrend(data, x=None, threshold=3.0):
|
|||||||
return d4
|
return d4
|
||||||
|
|
||||||
|
|
||||||
def histogramDetrend(data, window=500, bins=50, threshold=3.0):
|
def histogramDetrend(data, window=500, bins=50, threshold=3.0, offsetOnly=False):
|
||||||
"""Linear detrend. Works by finding the most common value at the beginning and end of a trace, excluding outliers."""
|
"""Linear detrend. Works by finding the most common value at the beginning and end of a trace, excluding outliers.
|
||||||
|
If offsetOnly is True, then only the offset from the beginning of the trace is subtracted.
|
||||||
|
"""
|
||||||
|
|
||||||
d1 = data.view(np.ndarray)
|
d1 = data.view(np.ndarray)
|
||||||
d2 = [d1[:window], d1[-window:]]
|
d2 = [d1[:window], d1[-window:]]
|
||||||
@ -211,6 +213,9 @@ def histogramDetrend(data, window=500, bins=50, threshold=3.0):
|
|||||||
ind = np.argmax(y)
|
ind = np.argmax(y)
|
||||||
v[i] = 0.5 * (x[ind] + x[ind+1])
|
v[i] = 0.5 * (x[ind] + x[ind+1])
|
||||||
|
|
||||||
|
if offsetOnly:
|
||||||
|
d3 = data.view(np.ndarray) - v[0]
|
||||||
|
else:
|
||||||
base = np.linspace(v[0], v[1], len(data))
|
base = np.linspace(v[0], v[1], len(data))
|
||||||
d3 = data.view(np.ndarray) - base
|
d3 = data.view(np.ndarray) - base
|
||||||
|
|
||||||
|
@ -261,7 +261,7 @@ def mkPen(*args, **kargs):
|
|||||||
if isinstance(arg, dict):
|
if isinstance(arg, dict):
|
||||||
return mkPen(**arg)
|
return mkPen(**arg)
|
||||||
if isinstance(arg, QtGui.QPen):
|
if isinstance(arg, QtGui.QPen):
|
||||||
return arg
|
return QtGui.QPen(arg) ## return a copy of this pen
|
||||||
elif arg is None:
|
elif arg is None:
|
||||||
style = QtCore.Qt.NoPen
|
style = QtCore.Qt.NoPen
|
||||||
else:
|
else:
|
||||||
|
@ -56,7 +56,7 @@ class AxisItem(GraphicsWidget):
|
|||||||
self.labelText = ''
|
self.labelText = ''
|
||||||
self.labelUnits = ''
|
self.labelUnits = ''
|
||||||
self.labelUnitPrefix=''
|
self.labelUnitPrefix=''
|
||||||
self.labelStyle = {'color': '#CCC'}
|
self.labelStyle = {}
|
||||||
self.logMode = False
|
self.logMode = False
|
||||||
|
|
||||||
self.textHeight = 18
|
self.textHeight = 18
|
||||||
@ -167,7 +167,7 @@ class AxisItem(GraphicsWidget):
|
|||||||
|
|
||||||
s = asUnicode('%s %s') % (self.labelText, units)
|
s = asUnicode('%s %s') % (self.labelText, units)
|
||||||
|
|
||||||
style = ';'.join(['%s: "%s"' % (k, self.labelStyle[k]) for k in self.labelStyle])
|
style = ';'.join(['%s: %s' % (k, self.labelStyle[k]) for k in self.labelStyle])
|
||||||
|
|
||||||
return asUnicode("<span style='%s'>%s</span>") % (style, s)
|
return asUnicode("<span style='%s'>%s</span>") % (style, s)
|
||||||
|
|
||||||
@ -192,7 +192,7 @@ class AxisItem(GraphicsWidget):
|
|||||||
def pen(self):
|
def pen(self):
|
||||||
if self._pen is None:
|
if self._pen is None:
|
||||||
return fn.mkPen(pg.getConfigOption('foreground'))
|
return fn.mkPen(pg.getConfigOption('foreground'))
|
||||||
return self._pen
|
return pg.mkPen(self._pen)
|
||||||
|
|
||||||
def setPen(self, pen):
|
def setPen(self, pen):
|
||||||
"""
|
"""
|
||||||
@ -202,6 +202,10 @@ class AxisItem(GraphicsWidget):
|
|||||||
"""
|
"""
|
||||||
self._pen = pen
|
self._pen = pen
|
||||||
self.picture = None
|
self.picture = None
|
||||||
|
if pen is None:
|
||||||
|
pen = pg.getConfigOption('foreground')
|
||||||
|
self.labelStyle['color'] = '#' + pg.colorStr(pg.mkPen(pen).color())[:6]
|
||||||
|
self.setLabel()
|
||||||
self.update()
|
self.update()
|
||||||
|
|
||||||
def setScale(self, scale=None):
|
def setScale(self, scale=None):
|
||||||
@ -299,8 +303,8 @@ class AxisItem(GraphicsWidget):
|
|||||||
self.drawPicture(painter)
|
self.drawPicture(painter)
|
||||||
finally:
|
finally:
|
||||||
painter.end()
|
painter.end()
|
||||||
p.setRenderHint(p.Antialiasing, False)
|
#p.setRenderHint(p.Antialiasing, False) ## Sometimes we get a segfault here ???
|
||||||
p.setRenderHint(p.TextAntialiasing, True)
|
#p.setRenderHint(p.TextAntialiasing, True)
|
||||||
self.picture.play(p)
|
self.picture.play(p)
|
||||||
|
|
||||||
|
|
||||||
|
@ -47,6 +47,8 @@ class GradientLegend(UIGraphicsItem):
|
|||||||
UIGraphicsItem.paint(self, p, opt, widget)
|
UIGraphicsItem.paint(self, p, opt, widget)
|
||||||
rect = self.boundingRect() ## Boundaries of visible area in scene coords.
|
rect = self.boundingRect() ## Boundaries of visible area in scene coords.
|
||||||
unit = self.pixelSize() ## Size of one view pixel in scene coords.
|
unit = self.pixelSize() ## Size of one view pixel in scene coords.
|
||||||
|
if unit[0] is None:
|
||||||
|
return
|
||||||
|
|
||||||
## determine max width of all labels
|
## determine max width of all labels
|
||||||
labelWidth = 0
|
labelWidth = 0
|
||||||
|
@ -1017,7 +1017,7 @@ class PlotItem(GraphicsWidget):
|
|||||||
(ie, use 'V' instead of 'mV'; 'm' will be added automatically)
|
(ie, use 'V' instead of 'mV'; 'm' will be added automatically)
|
||||||
============= =================================================================
|
============= =================================================================
|
||||||
"""
|
"""
|
||||||
self.getScale(axis).setLabel(text=text, units=units, **args)
|
self.getAxis(axis).setLabel(text=text, units=units, **args)
|
||||||
|
|
||||||
def showLabel(self, axis, show=True):
|
def showLabel(self, axis, show=True):
|
||||||
"""
|
"""
|
||||||
|
@ -71,7 +71,6 @@ class ScatterPlotItem(GraphicsObject):
|
|||||||
#sigPointClicked = QtCore.Signal(object, object)
|
#sigPointClicked = QtCore.Signal(object, object)
|
||||||
sigClicked = QtCore.Signal(object, object) ## self, points
|
sigClicked = QtCore.Signal(object, object) ## self, points
|
||||||
sigPlotChanged = QtCore.Signal(object)
|
sigPlotChanged = QtCore.Signal(object)
|
||||||
|
|
||||||
def __init__(self, *args, **kargs):
|
def __init__(self, *args, **kargs):
|
||||||
"""
|
"""
|
||||||
Accepts the same arguments as setData()
|
Accepts the same arguments as setData()
|
||||||
@ -231,6 +230,9 @@ class ScatterPlotItem(GraphicsObject):
|
|||||||
self.generateSpotItems()
|
self.generateSpotItems()
|
||||||
self.sigPlotChanged.emit(self)
|
self.sigPlotChanged.emit(self)
|
||||||
|
|
||||||
|
def getData(self):
|
||||||
|
return self.data['x'], self.data['y']
|
||||||
|
|
||||||
|
|
||||||
def setPoints(self, *args, **kargs):
|
def setPoints(self, *args, **kargs):
|
||||||
##Deprecated; use setData
|
##Deprecated; use setData
|
||||||
|
@ -310,6 +310,12 @@ class Parameter(QtCore.QObject):
|
|||||||
"""
|
"""
|
||||||
return not self.opts.get('readonly', False)
|
return not self.opts.get('readonly', False)
|
||||||
|
|
||||||
|
def setWritable(self, writable=True):
|
||||||
|
self.setOpts(readonly=not writable)
|
||||||
|
|
||||||
|
def setReadonly(self, readonly=True):
|
||||||
|
self.setOpts(readonly=readonly)
|
||||||
|
|
||||||
def setOpts(self, **opts):
|
def setOpts(self, **opts):
|
||||||
"""
|
"""
|
||||||
Set any arbitrary options on this parameter.
|
Set any arbitrary options on this parameter.
|
||||||
|
@ -26,6 +26,7 @@ class ParameterItem(QtGui.QTreeWidgetItem):
|
|||||||
param.sigLimitsChanged.connect(self.limitsChanged)
|
param.sigLimitsChanged.connect(self.limitsChanged)
|
||||||
param.sigDefaultChanged.connect(self.defaultChanged)
|
param.sigDefaultChanged.connect(self.defaultChanged)
|
||||||
param.sigOptionsChanged.connect(self.optsChanged)
|
param.sigOptionsChanged.connect(self.optsChanged)
|
||||||
|
param.sigParentChanged.connect(self.parentChanged)
|
||||||
|
|
||||||
|
|
||||||
opts = param.opts
|
opts = param.opts
|
||||||
@ -93,6 +94,10 @@ class ParameterItem(QtGui.QTreeWidgetItem):
|
|||||||
self.takeChild(i)
|
self.takeChild(i)
|
||||||
break
|
break
|
||||||
|
|
||||||
|
def parentChanged(self, param, parent):
|
||||||
|
## called when the parameter's parent has changed.
|
||||||
|
pass
|
||||||
|
|
||||||
def contextMenuEvent(self, ev):
|
def contextMenuEvent(self, ev):
|
||||||
if not self.param.opts.get('removable', False) and not self.param.opts.get('renamable', False):
|
if not self.param.opts.get('removable', False) and not self.param.opts.get('renamable', False):
|
||||||
return
|
return
|
||||||
|
@ -290,23 +290,7 @@ class GroupParameterItem(ParameterItem):
|
|||||||
"""
|
"""
|
||||||
def __init__(self, param, depth):
|
def __init__(self, param, depth):
|
||||||
ParameterItem.__init__(self, param, depth)
|
ParameterItem.__init__(self, param, depth)
|
||||||
if depth == 0:
|
self.updateDepth(depth)
|
||||||
for c in [0,1]:
|
|
||||||
self.setBackground(c, QtGui.QBrush(QtGui.QColor(100,100,100)))
|
|
||||||
self.setForeground(c, QtGui.QBrush(QtGui.QColor(220,220,255)))
|
|
||||||
font = self.font(c)
|
|
||||||
font.setBold(True)
|
|
||||||
font.setPointSize(font.pointSize()+1)
|
|
||||||
self.setFont(c, font)
|
|
||||||
self.setSizeHint(0, QtCore.QSize(0, 25))
|
|
||||||
else:
|
|
||||||
for c in [0,1]:
|
|
||||||
self.setBackground(c, QtGui.QBrush(QtGui.QColor(220,220,220)))
|
|
||||||
font = self.font(c)
|
|
||||||
font.setBold(True)
|
|
||||||
#font.setPointSize(font.pointSize()+1)
|
|
||||||
self.setFont(c, font)
|
|
||||||
self.setSizeHint(0, QtCore.QSize(0, 20))
|
|
||||||
|
|
||||||
self.addItem = None
|
self.addItem = None
|
||||||
if 'addText' in param.opts:
|
if 'addText' in param.opts:
|
||||||
@ -331,6 +315,27 @@ class GroupParameterItem(ParameterItem):
|
|||||||
self.addItem.setFlags(QtCore.Qt.ItemIsEnabled)
|
self.addItem.setFlags(QtCore.Qt.ItemIsEnabled)
|
||||||
ParameterItem.addChild(self, self.addItem)
|
ParameterItem.addChild(self, self.addItem)
|
||||||
|
|
||||||
|
def updateDepth(self, depth):
|
||||||
|
## Change item's appearance based on its depth in the tree
|
||||||
|
## This allows highest-level groups to be displayed more prominently.
|
||||||
|
if depth == 0:
|
||||||
|
for c in [0,1]:
|
||||||
|
self.setBackground(c, QtGui.QBrush(QtGui.QColor(100,100,100)))
|
||||||
|
self.setForeground(c, QtGui.QBrush(QtGui.QColor(220,220,255)))
|
||||||
|
font = self.font(c)
|
||||||
|
font.setBold(True)
|
||||||
|
font.setPointSize(font.pointSize()+1)
|
||||||
|
self.setFont(c, font)
|
||||||
|
self.setSizeHint(0, QtCore.QSize(0, 25))
|
||||||
|
else:
|
||||||
|
for c in [0,1]:
|
||||||
|
self.setBackground(c, QtGui.QBrush(QtGui.QColor(220,220,220)))
|
||||||
|
font = self.font(c)
|
||||||
|
font.setBold(True)
|
||||||
|
#font.setPointSize(font.pointSize()+1)
|
||||||
|
self.setFont(c, font)
|
||||||
|
self.setSizeHint(0, QtCore.QSize(0, 20))
|
||||||
|
|
||||||
def addClicked(self):
|
def addClicked(self):
|
||||||
"""Called when "add new" button is clicked
|
"""Called when "add new" button is clicked
|
||||||
The parameter MUST have an 'addNew' method defined.
|
The parameter MUST have an 'addNew' method defined.
|
||||||
|
@ -127,6 +127,12 @@ class SpinBox(QtGui.QAbstractSpinBox):
|
|||||||
self.editingFinished.connect(self.editingFinishedEvent)
|
self.editingFinished.connect(self.editingFinishedEvent)
|
||||||
self.proxy = SignalProxy(self.sigValueChanging, slot=self.delayedChange)
|
self.proxy = SignalProxy(self.sigValueChanging, slot=self.delayedChange)
|
||||||
|
|
||||||
|
def event(self, ev):
|
||||||
|
ret = QtGui.QAbstractSpinBox.event(self, ev)
|
||||||
|
if ev.type() == QtCore.QEvent.KeyPress and ev.key() == QtCore.Qt.Key_Return:
|
||||||
|
ret = True ## For some reason, spinbox pretends to ignore return key press
|
||||||
|
return ret
|
||||||
|
|
||||||
##lots of config options, just gonna stuff 'em all in here rather than do the get/set crap.
|
##lots of config options, just gonna stuff 'em all in here rather than do the get/set crap.
|
||||||
def setOpts(self, **opts):
|
def setOpts(self, **opts):
|
||||||
"""
|
"""
|
||||||
|
Loading…
Reference in New Issue
Block a user