Flowchart fixes: better job managing / saving / restoring 'muli' state of terminals
This commit is contained in:
parent
d1fdbadd19
commit
5b6f77be58
@ -71,7 +71,8 @@ class Flowchart(Node):
|
|||||||
if terminals is None:
|
if terminals is None:
|
||||||
terminals = {}
|
terminals = {}
|
||||||
self.filePath = filePath
|
self.filePath = filePath
|
||||||
Node.__init__(self, name) ## create node without terminals; we'll add these later
|
Node.__init__(self, name, allowAddInput=True, allowAddOutput=True) ## create node without terminals; we'll add these later
|
||||||
|
|
||||||
|
|
||||||
self.inputWasSet = False ## flag allows detection of changes in the absence of input change.
|
self.inputWasSet = False ## flag allows detection of changes in the absence of input change.
|
||||||
self._nodes = {}
|
self._nodes = {}
|
||||||
@ -457,7 +458,7 @@ class Flowchart(Node):
|
|||||||
state = Node.saveState(self)
|
state = Node.saveState(self)
|
||||||
state['nodes'] = []
|
state['nodes'] = []
|
||||||
state['connects'] = []
|
state['connects'] = []
|
||||||
state['terminals'] = self.saveTerminals()
|
#state['terminals'] = self.saveTerminals()
|
||||||
|
|
||||||
for name, node in self._nodes.items():
|
for name, node in self._nodes.items():
|
||||||
cls = type(node)
|
cls = type(node)
|
||||||
@ -470,7 +471,7 @@ class Flowchart(Node):
|
|||||||
conn = self.listConnections()
|
conn = self.listConnections()
|
||||||
for a, b in conn:
|
for a, b in conn:
|
||||||
state['connects'].append((a.node().name(), a.name(), b.node().name(), b.name()))
|
state['connects'].append((a.node().name(), a.name(), b.node().name(), b.name()))
|
||||||
|
|
||||||
state['inputNode'] = self.inputNode.saveState()
|
state['inputNode'] = self.inputNode.saveState()
|
||||||
state['outputNode'] = self.outputNode.saveState()
|
state['outputNode'] = self.outputNode.saveState()
|
||||||
|
|
||||||
@ -486,7 +487,8 @@ class Flowchart(Node):
|
|||||||
nodes.sort(lambda a, b: cmp(a['pos'][0], b['pos'][0]))
|
nodes.sort(lambda a, b: cmp(a['pos'][0], b['pos'][0]))
|
||||||
for n in nodes:
|
for n in nodes:
|
||||||
if n['name'] in self._nodes:
|
if n['name'] in self._nodes:
|
||||||
self._nodes[n['name']].moveBy(*n['pos'])
|
#self._nodes[n['name']].graphicsItem().moveBy(*n['pos'])
|
||||||
|
self._nodes[n['name']].restoreState(n['state'])
|
||||||
continue
|
continue
|
||||||
try:
|
try:
|
||||||
node = self.createNode(n['class'], name=n['name'])
|
node = self.createNode(n['class'], name=n['name'])
|
||||||
@ -498,7 +500,7 @@ class Flowchart(Node):
|
|||||||
self.inputNode.restoreState(state.get('inputNode', {}))
|
self.inputNode.restoreState(state.get('inputNode', {}))
|
||||||
self.outputNode.restoreState(state.get('outputNode', {}))
|
self.outputNode.restoreState(state.get('outputNode', {}))
|
||||||
|
|
||||||
self.restoreTerminals(state['terminals'])
|
#self.restoreTerminals(state['terminals'])
|
||||||
for n1, t1, n2, t2 in state['connects']:
|
for n1, t1, n2, t2 in state['connects']:
|
||||||
try:
|
try:
|
||||||
self.connectTerminals(self._nodes[n1][t1], self._nodes[n2][t2])
|
self.connectTerminals(self._nodes[n1][t1], self._nodes[n2][t2])
|
||||||
|
@ -1,16 +1,13 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from pyqtgraph.Qt import QtCore, QtGui
|
from pyqtgraph.Qt import QtCore, QtGui
|
||||||
#from PySide import QtCore, QtGui
|
|
||||||
from pyqtgraph.graphicsItems.GraphicsObject import GraphicsObject
|
from pyqtgraph.graphicsItems.GraphicsObject import GraphicsObject
|
||||||
import pyqtgraph.functions as fn
|
import pyqtgraph.functions as fn
|
||||||
from .Terminal import *
|
from .Terminal import *
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from pyqtgraph.debug import *
|
from pyqtgraph.debug import *
|
||||||
import numpy as np
|
import numpy as np
|
||||||
#from pyqtgraph.ObjectWorkaround import QObjectWorkaround
|
|
||||||
from .eq import *
|
from .eq import *
|
||||||
|
|
||||||
#TETRACYCLINE = True
|
|
||||||
|
|
||||||
def strDict(d):
|
def strDict(d):
|
||||||
return dict([(str(k), v) for k, v in d.items()])
|
return dict([(str(k), v) for k, v in d.items()])
|
||||||
@ -32,8 +29,8 @@ class Node(QtCore.QObject):
|
|||||||
self.bypassButton = None ## this will be set by the flowchart ctrl widget..
|
self.bypassButton = None ## this will be set by the flowchart ctrl widget..
|
||||||
self._graphicsItem = None
|
self._graphicsItem = None
|
||||||
self.terminals = OrderedDict()
|
self.terminals = OrderedDict()
|
||||||
self._inputs = {}
|
self._inputs = OrderedDict()
|
||||||
self._outputs = {}
|
self._outputs = OrderedDict()
|
||||||
self._allowAddInput = allowAddInput ## flags to allow the user to add/remove terminals
|
self._allowAddInput = allowAddInput ## flags to allow the user to add/remove terminals
|
||||||
self._allowAddOutput = allowAddOutput
|
self._allowAddOutput = allowAddOutput
|
||||||
self._allowRemove = allowRemove
|
self._allowRemove = allowRemove
|
||||||
@ -85,24 +82,16 @@ class Node(QtCore.QObject):
|
|||||||
def terminalRenamed(self, term, oldName):
|
def terminalRenamed(self, term, oldName):
|
||||||
"""Called after a terminal has been renamed"""
|
"""Called after a terminal has been renamed"""
|
||||||
newName = term.name()
|
newName = term.name()
|
||||||
#print "node", self, "handling rename..", newName, oldName
|
|
||||||
for d in [self.terminals, self._inputs, self._outputs]:
|
for d in [self.terminals, self._inputs, self._outputs]:
|
||||||
if oldName not in d:
|
if oldName not in d:
|
||||||
continue
|
continue
|
||||||
#print " got one"
|
|
||||||
d[newName] = d[oldName]
|
d[newName] = d[oldName]
|
||||||
del d[oldName]
|
del d[oldName]
|
||||||
|
|
||||||
self.graphicsItem().updateTerminals()
|
self.graphicsItem().updateTerminals()
|
||||||
#self.emit(QtCore.SIGNAL('terminalRenamed'), term, oldName)
|
|
||||||
self.sigTerminalRenamed.emit(term, oldName)
|
self.sigTerminalRenamed.emit(term, oldName)
|
||||||
|
|
||||||
def addTerminal(self, name, **opts):
|
def addTerminal(self, name, **opts):
|
||||||
#print "Node.addTerminal called. name:", name, "opts:", opts
|
|
||||||
#global TETRACYCLINE
|
|
||||||
#print "TETRACYCLINE: ", TETRACYCLINE
|
|
||||||
#if TETRACYCLINE:
|
|
||||||
#print "Creating Terminal..."
|
|
||||||
name = self.nextTerminalName(name)
|
name = self.nextTerminalName(name)
|
||||||
term = Terminal(self, name, **opts)
|
term = Terminal(self, name, **opts)
|
||||||
self.terminals[name] = term
|
self.terminals[name] = term
|
||||||
@ -278,12 +267,20 @@ class Node(QtCore.QObject):
|
|||||||
|
|
||||||
def saveState(self):
|
def saveState(self):
|
||||||
pos = self.graphicsItem().pos()
|
pos = self.graphicsItem().pos()
|
||||||
return {'pos': (pos.x(), pos.y()), 'bypass': self.isBypassed()}
|
state = {'pos': (pos.x(), pos.y()), 'bypass': self.isBypassed()}
|
||||||
|
termsEditable = self._allowAddInput | self._allowAddOutput
|
||||||
|
for term in self._inputs.values() + self._outputs.values():
|
||||||
|
termsEditable |= term._renamable | term._removable | term._multiable
|
||||||
|
if termsEditable:
|
||||||
|
state['terminals'] = self.saveTerminals()
|
||||||
|
return state
|
||||||
|
|
||||||
def restoreState(self, state):
|
def restoreState(self, state):
|
||||||
pos = state.get('pos', (0,0))
|
pos = state.get('pos', (0,0))
|
||||||
self.graphicsItem().setPos(*pos)
|
self.graphicsItem().setPos(*pos)
|
||||||
self.bypass(state.get('bypass', False))
|
self.bypass(state.get('bypass', False))
|
||||||
|
if 'terminals' in state:
|
||||||
|
self.restoreTerminals(state['terminals'])
|
||||||
|
|
||||||
def saveTerminals(self):
|
def saveTerminals(self):
|
||||||
terms = OrderedDict()
|
terms = OrderedDict()
|
||||||
@ -309,8 +306,8 @@ class Node(QtCore.QObject):
|
|||||||
for t in self.terminals.values():
|
for t in self.terminals.values():
|
||||||
t.close()
|
t.close()
|
||||||
self.terminals = OrderedDict()
|
self.terminals = OrderedDict()
|
||||||
self._inputs = {}
|
self._inputs = OrderedDict()
|
||||||
self._outputs = {}
|
self._outputs = OrderedDict()
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
"""Cleans up after the node--removes terminals, graphicsItem, widget"""
|
"""Cleans up after the node--removes terminals, graphicsItem, widget"""
|
||||||
@ -493,10 +490,6 @@ class NodeGraphicsItem(GraphicsObject):
|
|||||||
self.hovered = False
|
self.hovered = False
|
||||||
self.update()
|
self.update()
|
||||||
|
|
||||||
#def mouseReleaseEvent(self, ev):
|
|
||||||
#ret = QtGui.QGraphicsItem.mouseReleaseEvent(self, ev)
|
|
||||||
#return ret
|
|
||||||
|
|
||||||
def keyPressEvent(self, ev):
|
def keyPressEvent(self, ev):
|
||||||
if ev.key() == QtCore.Qt.Key_Delete or ev.key() == QtCore.Qt.Key_Backspace:
|
if ev.key() == QtCore.Qt.Key_Delete or ev.key() == QtCore.Qt.Key_Backspace:
|
||||||
ev.accept()
|
ev.accept()
|
||||||
@ -513,13 +506,8 @@ class NodeGraphicsItem(GraphicsObject):
|
|||||||
return GraphicsObject.itemChange(self, change, val)
|
return GraphicsObject.itemChange(self, change, val)
|
||||||
|
|
||||||
|
|
||||||
#def contextMenuEvent(self, ev):
|
|
||||||
#ev.accept()
|
|
||||||
#self.menu.popup(ev.screenPos())
|
|
||||||
|
|
||||||
def getMenu(self):
|
def getMenu(self):
|
||||||
return self.menu
|
return self.menu
|
||||||
|
|
||||||
|
|
||||||
def getContextMenus(self, event):
|
def getContextMenus(self, event):
|
||||||
return [self.menu]
|
return [self.menu]
|
||||||
@ -548,25 +536,3 @@ class NodeGraphicsItem(GraphicsObject):
|
|||||||
def addOutputFromMenu(self): ## called when add output is clicked in context menu
|
def addOutputFromMenu(self): ## called when add output is clicked in context menu
|
||||||
self.node.addOutput(renamable=True, removable=True, multiable=False)
|
self.node.addOutput(renamable=True, removable=True, multiable=False)
|
||||||
|
|
||||||
#def menuTriggered(self, action):
|
|
||||||
##print "node.menuTriggered called. action:", action
|
|
||||||
#act = str(action.text())
|
|
||||||
#if act == "Add input":
|
|
||||||
#self.node.addInput()
|
|
||||||
#self.updateActionMenu()
|
|
||||||
#elif act == "Add output":
|
|
||||||
#self.node.addOutput()
|
|
||||||
#self.updateActionMenu()
|
|
||||||
#elif act == "Remove node":
|
|
||||||
#self.node.close()
|
|
||||||
#else: ## only other option is to remove a terminal
|
|
||||||
#self.node.removeTerminal(act)
|
|
||||||
#self.terminalMenu.removeAction(action)
|
|
||||||
|
|
||||||
#def updateActionMenu(self):
|
|
||||||
#for t in self.node.terminals:
|
|
||||||
#if t not in [str(a.text()) for a in self.terminalMenu.actions()]:
|
|
||||||
#self.terminalMenu.addAction(t)
|
|
||||||
#for a in self.terminalMenu.actions():
|
|
||||||
#if str(a.text()) not in self.node.terminals:
|
|
||||||
#self.terminalMenu.removeAction(a)
|
|
||||||
|
@ -45,7 +45,7 @@ class Terminal:
|
|||||||
self._value = {} ## dictionary of terminal:value pairs.
|
self._value = {} ## dictionary of terminal:value pairs.
|
||||||
else:
|
else:
|
||||||
self._value = None
|
self._value = None
|
||||||
|
|
||||||
self.valueOk = None
|
self.valueOk = None
|
||||||
self.recolor()
|
self.recolor()
|
||||||
|
|
||||||
@ -70,6 +70,8 @@ class Terminal:
|
|||||||
return
|
return
|
||||||
self._value = val
|
self._value = val
|
||||||
else:
|
else:
|
||||||
|
if not isinstance(self._value, dict):
|
||||||
|
self._value = {}
|
||||||
if val is not None:
|
if val is not None:
|
||||||
self._value.update(val)
|
self._value.update(val)
|
||||||
|
|
||||||
@ -132,9 +134,14 @@ class Terminal:
|
|||||||
def isMultiValue(self):
|
def isMultiValue(self):
|
||||||
return self._multi
|
return self._multi
|
||||||
|
|
||||||
def setMultiValue(self, b):
|
def setMultiValue(self, multi):
|
||||||
"""Set whether this is a multi-value terminal."""
|
"""Set whether this is a multi-value terminal."""
|
||||||
self._multi = b
|
self._multi = multi
|
||||||
|
if not multi and len(self.inputTerminals()) > 1:
|
||||||
|
self.disconnectAll()
|
||||||
|
|
||||||
|
for term in self.inputTerminals():
|
||||||
|
self.inputChanged(term)
|
||||||
|
|
||||||
def isOutput(self):
|
def isOutput(self):
|
||||||
return self._io == 'out'
|
return self._io == 'out'
|
||||||
@ -407,6 +414,8 @@ class TerminalGraphicsItem(GraphicsObject):
|
|||||||
multiAct = QtGui.QAction("Multi-value", self.menu)
|
multiAct = QtGui.QAction("Multi-value", self.menu)
|
||||||
multiAct.setCheckable(True)
|
multiAct.setCheckable(True)
|
||||||
multiAct.setChecked(self.term.isMultiValue())
|
multiAct.setChecked(self.term.isMultiValue())
|
||||||
|
multiAct.setEnabled(self.term.isMultiable())
|
||||||
|
|
||||||
multiAct.triggered.connect(self.toggleMulti)
|
multiAct.triggered.connect(self.toggleMulti)
|
||||||
self.menu.addAction(multiAct)
|
self.menu.addAction(multiAct)
|
||||||
self.menu.multiAct = multiAct
|
self.menu.multiAct = multiAct
|
||||||
|
@ -240,7 +240,7 @@ class EvalNode(Node):
|
|||||||
def saveState(self):
|
def saveState(self):
|
||||||
state = Node.saveState(self)
|
state = Node.saveState(self)
|
||||||
state['text'] = str(self.text.toPlainText())
|
state['text'] = str(self.text.toPlainText())
|
||||||
state['terminals'] = self.saveTerminals()
|
#state['terminals'] = self.saveTerminals()
|
||||||
return state
|
return state
|
||||||
|
|
||||||
def restoreState(self, state):
|
def restoreState(self, state):
|
||||||
@ -282,7 +282,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)
|
term = Node.addInput(self, 'input', renamable=True, removable=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
|
||||||
@ -322,16 +322,14 @@ class ColumnJoinNode(Node):
|
|||||||
|
|
||||||
def restoreState(self, state):
|
def restoreState(self, state):
|
||||||
Node.restoreState(self, state)
|
Node.restoreState(self, state)
|
||||||
inputs = [inp.name() for inp in self.inputs()]
|
inputs = self.inputs()
|
||||||
|
order = [name for name in state['order'] if name in inputs]
|
||||||
for name in inputs:
|
for name in inputs:
|
||||||
if name not in state['order']:
|
if name not in order:
|
||||||
self.removeTerminal(name)
|
order.append(name)
|
||||||
for name in state['order']:
|
|
||||||
if name not in inputs:
|
|
||||||
Node.addInput(self, name, renamable=True)
|
|
||||||
|
|
||||||
self.tree.clear()
|
self.tree.clear()
|
||||||
for name in state['order']:
|
for name in order:
|
||||||
term = self[name]
|
term = self[name]
|
||||||
item = QtGui.QTreeWidgetItem([name])
|
item = QtGui.QTreeWidgetItem([name])
|
||||||
item.term = term
|
item.term = term
|
||||||
|
@ -153,7 +153,7 @@ def denoise(data, radius=2, threshold=4):
|
|||||||
|
|
||||||
r2 = radius * 2
|
r2 = radius * 2
|
||||||
d1 = data.view(np.ndarray)
|
d1 = data.view(np.ndarray)
|
||||||
d2 = data[radius:] - data[:-radius] #a derivative
|
d2 = d1[radius:] - d1[:-radius] #a derivative
|
||||||
#d3 = data[r2:] - data[:-r2]
|
#d3 = data[r2:] - data[:-r2]
|
||||||
#d4 = d2 - d3
|
#d4 = d2 - d3
|
||||||
stdev = d2.std()
|
stdev = d2.std()
|
||||||
|
Loading…
Reference in New Issue
Block a user