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:
|
||||
#w.plot(*args, **kargs)
|
||||
|
||||
pwArgList = ['title', 'label', 'name', 'left', 'right', 'top', 'bottom']
|
||||
pwArgList = ['title', 'labels', 'name', 'left', 'right', 'top', 'bottom']
|
||||
pwArgs = {}
|
||||
dataArgs = {}
|
||||
for k in kargs:
|
||||
|
@ -122,7 +122,7 @@ params = [
|
||||
]
|
||||
|
||||
## 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
|
||||
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())
|
||||
|
||||
def internalTerminalRemoved(self, node, term):
|
||||
Node.removeTerminal(self, term.name())
|
||||
try:
|
||||
Node.removeTerminal(self, term.name())
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
def terminalRenamed(self, term, oldName):
|
||||
newName = term.name()
|
||||
|
@ -294,6 +294,8 @@ class Node(QtCore.QObject):
|
||||
self.removeTerminal(name)
|
||||
for name, opts in state.items():
|
||||
if name in self.terminals:
|
||||
term = self[name]
|
||||
term.setOpts(**opts)
|
||||
continue
|
||||
try:
|
||||
opts = strDict(opts)
|
||||
|
@ -85,6 +85,14 @@ class Terminal:
|
||||
#if c.isInput():
|
||||
#c.inputChanged(self)
|
||||
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):
|
||||
"""Called whenever this terminal has been connected to another. (note--this function is called on both terminals)"""
|
||||
|
@ -235,6 +235,9 @@ class EvalNode(Node):
|
||||
run = "\noutput=fn(**args)\n"
|
||||
text = fn + "\n".join([" "+l for l in str(self.text.toPlainText()).split('\n')]) + run
|
||||
exec(text)
|
||||
except:
|
||||
print "Error processing node:", self.name()
|
||||
raise
|
||||
return output
|
||||
|
||||
def saveState(self):
|
||||
@ -282,7 +285,7 @@ class ColumnJoinNode(Node):
|
||||
|
||||
def addInput(self):
|
||||
#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
|
||||
item = QtGui.QTreeWidgetItem([term.name()])
|
||||
item.term = term
|
||||
@ -323,6 +326,14 @@ class ColumnJoinNode(Node):
|
||||
def restoreState(self, state):
|
||||
Node.restoreState(self, state)
|
||||
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]
|
||||
for name in inputs:
|
||||
if name not in order:
|
||||
@ -343,4 +354,4 @@ class ColumnJoinNode(Node):
|
||||
item.setText(0, term.name())
|
||||
self.update()
|
||||
|
||||
|
||||
|
||||
|
@ -184,13 +184,16 @@ class HistogramDetrend(CtrlNode):
|
||||
nodeName = 'HistogramDetrend'
|
||||
uiTemplate = [
|
||||
('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):
|
||||
ws = self.ctrls['windowSize'].value()
|
||||
bn = self.ctrls['numBins'].value()
|
||||
return functions.histogramDetrend(data, window=ws, bins=bn)
|
||||
s = self.stateGroup.state()
|
||||
#ws = self.ctrls['windowSize'].value()
|
||||
#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
|
||||
|
||||
|
||||
def histogramDetrend(data, window=500, bins=50, threshold=3.0):
|
||||
"""Linear detrend. Works by finding the most common value at the beginning and end of a trace, excluding outliers."""
|
||||
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.
|
||||
If offsetOnly is True, then only the offset from the beginning of the trace is subtracted.
|
||||
"""
|
||||
|
||||
d1 = data.view(np.ndarray)
|
||||
d2 = [d1[:window], d1[-window:]]
|
||||
@ -211,8 +213,11 @@ def histogramDetrend(data, window=500, bins=50, threshold=3.0):
|
||||
ind = np.argmax(y)
|
||||
v[i] = 0.5 * (x[ind] + x[ind+1])
|
||||
|
||||
base = np.linspace(v[0], v[1], len(data))
|
||||
d3 = data.view(np.ndarray) - base
|
||||
if offsetOnly:
|
||||
d3 = data.view(np.ndarray) - v[0]
|
||||
else:
|
||||
base = np.linspace(v[0], v[1], len(data))
|
||||
d3 = data.view(np.ndarray) - base
|
||||
|
||||
if (hasattr(data, 'implements') and data.implements('MetaArray')):
|
||||
return MetaArray(d3, info=data.infoCopy())
|
||||
|
@ -261,7 +261,7 @@ def mkPen(*args, **kargs):
|
||||
if isinstance(arg, dict):
|
||||
return mkPen(**arg)
|
||||
if isinstance(arg, QtGui.QPen):
|
||||
return arg
|
||||
return QtGui.QPen(arg) ## return a copy of this pen
|
||||
elif arg is None:
|
||||
style = QtCore.Qt.NoPen
|
||||
else:
|
||||
|
@ -56,7 +56,7 @@ class AxisItem(GraphicsWidget):
|
||||
self.labelText = ''
|
||||
self.labelUnits = ''
|
||||
self.labelUnitPrefix=''
|
||||
self.labelStyle = {'color': '#CCC'}
|
||||
self.labelStyle = {}
|
||||
self.logMode = False
|
||||
|
||||
self.textHeight = 18
|
||||
@ -167,7 +167,7 @@ class AxisItem(GraphicsWidget):
|
||||
|
||||
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)
|
||||
|
||||
@ -192,7 +192,7 @@ class AxisItem(GraphicsWidget):
|
||||
def pen(self):
|
||||
if self._pen is None:
|
||||
return fn.mkPen(pg.getConfigOption('foreground'))
|
||||
return self._pen
|
||||
return pg.mkPen(self._pen)
|
||||
|
||||
def setPen(self, pen):
|
||||
"""
|
||||
@ -202,6 +202,10 @@ class AxisItem(GraphicsWidget):
|
||||
"""
|
||||
self._pen = pen
|
||||
self.picture = None
|
||||
if pen is None:
|
||||
pen = pg.getConfigOption('foreground')
|
||||
self.labelStyle['color'] = '#' + pg.colorStr(pg.mkPen(pen).color())[:6]
|
||||
self.setLabel()
|
||||
self.update()
|
||||
|
||||
def setScale(self, scale=None):
|
||||
@ -299,8 +303,8 @@ class AxisItem(GraphicsWidget):
|
||||
self.drawPicture(painter)
|
||||
finally:
|
||||
painter.end()
|
||||
p.setRenderHint(p.Antialiasing, False)
|
||||
p.setRenderHint(p.TextAntialiasing, True)
|
||||
#p.setRenderHint(p.Antialiasing, False) ## Sometimes we get a segfault here ???
|
||||
#p.setRenderHint(p.TextAntialiasing, True)
|
||||
self.picture.play(p)
|
||||
|
||||
|
||||
|
@ -47,6 +47,8 @@ class GradientLegend(UIGraphicsItem):
|
||||
UIGraphicsItem.paint(self, p, opt, widget)
|
||||
rect = self.boundingRect() ## Boundaries of visible area 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
|
||||
labelWidth = 0
|
||||
|
@ -1017,7 +1017,7 @@ class PlotItem(GraphicsWidget):
|
||||
(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):
|
||||
"""
|
||||
|
@ -71,7 +71,6 @@ class ScatterPlotItem(GraphicsObject):
|
||||
#sigPointClicked = QtCore.Signal(object, object)
|
||||
sigClicked = QtCore.Signal(object, object) ## self, points
|
||||
sigPlotChanged = QtCore.Signal(object)
|
||||
|
||||
def __init__(self, *args, **kargs):
|
||||
"""
|
||||
Accepts the same arguments as setData()
|
||||
@ -231,6 +230,9 @@ class ScatterPlotItem(GraphicsObject):
|
||||
self.generateSpotItems()
|
||||
self.sigPlotChanged.emit(self)
|
||||
|
||||
def getData(self):
|
||||
return self.data['x'], self.data['y']
|
||||
|
||||
|
||||
def setPoints(self, *args, **kargs):
|
||||
##Deprecated; use setData
|
||||
|
@ -310,6 +310,12 @@ class Parameter(QtCore.QObject):
|
||||
"""
|
||||
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):
|
||||
"""
|
||||
Set any arbitrary options on this parameter.
|
||||
|
@ -26,6 +26,7 @@ class ParameterItem(QtGui.QTreeWidgetItem):
|
||||
param.sigLimitsChanged.connect(self.limitsChanged)
|
||||
param.sigDefaultChanged.connect(self.defaultChanged)
|
||||
param.sigOptionsChanged.connect(self.optsChanged)
|
||||
param.sigParentChanged.connect(self.parentChanged)
|
||||
|
||||
|
||||
opts = param.opts
|
||||
@ -93,6 +94,10 @@ class ParameterItem(QtGui.QTreeWidgetItem):
|
||||
self.takeChild(i)
|
||||
break
|
||||
|
||||
def parentChanged(self, param, parent):
|
||||
## called when the parameter's parent has changed.
|
||||
pass
|
||||
|
||||
def contextMenuEvent(self, ev):
|
||||
if not self.param.opts.get('removable', False) and not self.param.opts.get('renamable', False):
|
||||
return
|
||||
|
@ -290,23 +290,7 @@ class GroupParameterItem(ParameterItem):
|
||||
"""
|
||||
def __init__(self, param, depth):
|
||||
ParameterItem.__init__(self, param, depth)
|
||||
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))
|
||||
self.updateDepth(depth)
|
||||
|
||||
self.addItem = None
|
||||
if 'addText' in param.opts:
|
||||
@ -331,6 +315,27 @@ class GroupParameterItem(ParameterItem):
|
||||
self.addItem.setFlags(QtCore.Qt.ItemIsEnabled)
|
||||
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):
|
||||
"""Called when "add new" button is clicked
|
||||
The parameter MUST have an 'addNew' method defined.
|
||||
|
@ -90,4 +90,4 @@ class CheckTable(QtGui.QWidget):
|
||||
rowNum = self.rowNames.index(r[0])
|
||||
for i in range(1, len(r)):
|
||||
self.rowWidgets[rowNum][i].setChecked(r[i])
|
||||
|
||||
|
||||
|
@ -127,6 +127,12 @@ class SpinBox(QtGui.QAbstractSpinBox):
|
||||
self.editingFinished.connect(self.editingFinishedEvent)
|
||||
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.
|
||||
def setOpts(self, **opts):
|
||||
"""
|
||||
|
Loading…
Reference in New Issue
Block a user