def __init__(self, parent, selected_module_ids, selected_connection_ids, scene): """ QControlFlowAssistDialog(selected_module_ids: list, selected_connection_ids: list, scene: QGraphicsScene) -> None Creates the control flow assistant dialog """ # FIXME do this here to avoid circular refs from pipeline_view_select import QReadOnlyPortSelectPipelineView QtGui.QDialog.__init__(self, parent) self.module_ids = selected_module_ids self.connection_ids = selected_connection_ids self.setWindowTitle('Control Flow Assistant') layout = QtGui.QVBoxLayout(self) self.setLayout(layout) # Add instruction label self.instructionLabel = QtGui.QLabel( 'Select one or more Input Ports to receive Lists, and one Output Port to produce a List' ) layout.addWidget(self.instructionLabel) # Add pipeline view self.pipelineView = QReadOnlyPortSelectPipelineView( self, scene, True, selected_module_ids) self.controller = self.pipelineView.scene().controller layout.addWidget(self.pipelineView) self.enablePackage() # Add ok/cancel buttons buttonLayout = QtGui.QHBoxLayout() buttonLayout.setMargin(5) self.okButton = QtGui.QPushButton('&OK', self) self.okButton.setAutoDefault(False) self.okButton.setFixedWidth(100) buttonLayout.addWidget(self.okButton) self.cancelButton = QtGui.QPushButton('&Cancel', self) self.cancelButton.setAutoDefault(False) self.cancelButton.setShortcut('Esc') self.cancelButton.setFixedWidth(100) buttonLayout.addWidget(self.cancelButton) layout.addLayout(buttonLayout) self.connect(self.okButton, QtCore.SIGNAL('clicked(bool)'), self.okClicked) self.connect(self.cancelButton, QtCore.SIGNAL('clicked(bool)'), self.close)
def __init__(self, parent, selected_module_ids, selected_connection_ids, scene): """ QControlFlowAssistDialog(selected_module_ids: list, selected_connection_ids: list, scene: QGraphicsScene) -> None Creates the control flow assistant dialog """ # FIXME do this here to avoid circular refs from pipeline_view_select import QReadOnlyPortSelectPipelineView QtGui.QDialog.__init__(self, parent) self.module_ids = selected_module_ids self.connection_ids = selected_connection_ids self.setWindowTitle('Control Flow Assistant') layout = QtGui.QVBoxLayout(self) self.setLayout(layout) # Add instruction label self.instructionLabel = QtGui.QLabel('Select one or more Input Ports to receive Lists, and one Output Port to produce a List') layout.addWidget(self.instructionLabel) # Add pipeline view self.pipelineView = QReadOnlyPortSelectPipelineView(self, scene, True, selected_module_ids) self.controller = self.pipelineView.scene().controller layout.addWidget(self.pipelineView) self.enablePackage() # Add ok/cancel buttons buttonLayout = QtGui.QHBoxLayout() buttonLayout.setMargin(5) self.okButton = QtGui.QPushButton('&OK', self) self.okButton.setAutoDefault(False) self.okButton.setFixedWidth(100) buttonLayout.addWidget(self.okButton) self.cancelButton = QtGui.QPushButton('&Cancel', self) self.cancelButton.setAutoDefault(False) self.cancelButton.setShortcut('Esc') self.cancelButton.setFixedWidth(100) buttonLayout.addWidget(self.cancelButton) layout.addLayout(buttonLayout) self.connect(self.okButton, QtCore.SIGNAL('clicked(bool)'), self.okClicked) self.connect(self.cancelButton, QtCore.SIGNAL('clicked(bool)'), self.close)
class QControlFlowAssistDialog(QtGui.QDialog): def __init__(self, parent, selected_module_ids, selected_connection_ids, scene): """ QControlFlowAssistDialog(selected_module_ids: list, selected_connection_ids: list, scene: QGraphicsScene) -> None Creates the control flow assistant dialog """ # FIXME do this here to avoid circular refs from pipeline_view_select import QReadOnlyPortSelectPipelineView QtGui.QDialog.__init__(self, parent) self.module_ids = selected_module_ids self.connection_ids = selected_connection_ids self.setWindowTitle('Control Flow Assistant') layout = QtGui.QVBoxLayout(self) self.setLayout(layout) # Add instruction label self.instructionLabel = QtGui.QLabel('Select one or more Input Ports to receive Lists, and one Output Port to produce a List') layout.addWidget(self.instructionLabel) # Add pipeline view self.pipelineView = QReadOnlyPortSelectPipelineView(self, scene, True, selected_module_ids) self.controller = self.pipelineView.scene().controller layout.addWidget(self.pipelineView) self.enablePackage() # Add ok/cancel buttons buttonLayout = QtGui.QHBoxLayout() buttonLayout.setMargin(5) self.okButton = QtGui.QPushButton('&OK', self) self.okButton.setAutoDefault(False) self.okButton.setFixedWidth(100) buttonLayout.addWidget(self.okButton) self.cancelButton = QtGui.QPushButton('&Cancel', self) self.cancelButton.setAutoDefault(False) self.cancelButton.setShortcut('Esc') self.cancelButton.setFixedWidth(100) buttonLayout.addWidget(self.cancelButton) layout.addLayout(buttonLayout) self.connect(self.okButton, QtCore.SIGNAL('clicked(bool)'), self.okClicked) self.connect(self.cancelButton, QtCore.SIGNAL('clicked(bool)'), self.close) def enablePackage(self): """ enablePackge() -> None Tries to enable the controlflow package through the controller. """ pm = get_package_manager() cf_pkg_id = 'org.vistrails.vistrails.control_flow' if not pm.has_package(cf_pkg_id): dep_graph = pm.build_dependency_graph([cf_pkg_id]) if not self.controller.try_to_enable_package(cf_pkg_id, dep_graph): raise MissingPackage(cf_pkg_id) def getInputPortsInfo(self): """ getInputPortsInfo() -> list Gets a list of tuples from the selected input port (QGraphicsPortItem) objects containing: (module, portspec, incoming_connections, halfwidth) """ return [(gport.parentItem().module, gport.port, gport.controller.get_connections_to(gport.controller.current_pipeline, [gport.parentItem().module.id], gport.port.name), (gport.parentItem().boundingRect().right()-gport.parentItem().boundingRect().left())/2) for gport in self.pipelineView.getSelectedInputPorts()] def getOutputPortsInfo(self): """ getOutputPortsInfo() -> list Gets a list of tuples from the selected output port (QGraphicsPortItem) objects containing: (module, portspec, outgoing_connections, halfwidth) """ return [(gport.parentItem().module, gport.port, gport.controller.get_connections_from(gport.controller.current_pipeline, [gport.parentItem().module.id], gport.port.name), (gport.parentItem().boundingRect().right()-gport.parentItem().boundingRect().left())/2) for gport in self.pipelineView.getSelectedOutputPorts()] def okClicked(self): """ okClicked() -> None Verify selected ports and initiate control flow creation """ try: self.enablePackage() except MissingPackage: debug.critical("The controlflow package is not available") return # Verify that at least one input and one output have been chosen input_ports_info = self.getInputPortsInfo() output_ports_info = self.getOutputPortsInfo() if len(input_ports_info) == 0: show_info('No Input Ports Selected', 'No Input Ports have been selected. You must select at least one to proceed.') elif len(output_ports_info) == 0: show_info('No Output Port Selected', 'No Output Port has been selected. You must select one to proceed.') else: self.createControlFlow(input_ports_info, output_ports_info) self.close() def createControlFlow(self, input_ports_info, output_ports_info): """ createControlFlow(input_ports_info: list, output_ports_info: list) -> None Create a control flow from input and output port information. input_ports_info is a list of tuples containing: (module, portspec, incoming_connections, halfwidth) input_ports_info is a list of tuples containing: (module, portspec, outgoing_connections, halfwidth) """ from vistrails.core.modules.basic_modules import identifier as bm_identifier from vistrails.packages.controlflow import identifier as cf_identifier io_modules = [] io_connections = [] # Create and connect InputPort for each of the inputs to force it to exist on group offset = {} for module, portspec, connections, halfwidth in input_ports_info: offset.__setitem__(module, halfwidth+65) for input_module, input_portspec, input_connections, halfwidth in input_ports_info: # Remove function calls to selected input ports try: function_pos = [f.name for f in input_module.functions].index(input_portspec.name) self.controller.delete_method(function_pos, input_module.id) except Exception: pass # Disconnect connections to selected input ports for connection in input_connections: self.connection_ids.remove(connection.id) self.controller.delete_connection(connection.id) group_inport_module = self.controller.add_module(bm_identifier, 'InputPort', x=input_module.location.x-offset[input_module], y=input_module.location.y) io_modules.append(group_inport_module) offset[input_module] += 130 for p in group_inport_module.sourcePorts(): if p.name == 'InternalPipe': group_inport_conn = self.controller.add_connection(input_module.id, input_portspec, group_inport_module.id, p) io_connections.append(group_inport_conn) break # Create and connect OutputPort for desired output to force it to exist on group output_module, output_portspec, output_connections, halfwidth = output_ports_info[0] # Disconnect connections to selected output port for connection in output_connections: self.connection_ids.remove(connection.id) self.controller.delete_connection(connection.id) group_outport_module = self.controller.add_module(bm_identifier, 'OutputPort', x=output_module.location.x+halfwidth+75, y=output_module.location.y) io_modules.append(group_outport_module) for p in group_outport_module.destinationPorts(): if p.name == 'InternalPipe': group_outport_conn = self.controller.add_connection(output_module.id, output_portspec, group_outport_module.id, p) io_connections.append(group_outport_conn) break # Create inner group from selected modules and their connections (plus newly created input/output connections) inner_group = self.controller.create_group(self.module_ids + [m.id for m in io_modules], self.connection_ids + [c.id for c in io_connections]) self.controller.updatePipelineScene() del io_modules[:] del io_connections[:] io_modules.append(inner_group) io_connections.extend(self.controller.get_connections_to_and_from(self.controller.current_pipeline, [inner_group.id])) # Add Map module map_module = self.controller.add_module(cf_identifier, 'Map', x=inner_group.location.x-120, y=inner_group.location.y) io_modules.append(map_module) # Get group 'self' port object for p in inner_group.sourcePorts(): if p.name == 'self': inner_group_selfport = p break # Add PythonSource py_source_module = self.controller.add_module(bm_identifier, 'PythonSource', x=inner_group.location.x, y=inner_group.location.y+75) io_modules.append(py_source_module) group_type = '('+bm_identifier+':Group)' bool_type = '('+bm_identifier+':Boolean)' list_type = '('+bm_identifier+':List)' string_type = '('+bm_identifier+':String)' base_input_ports = [] base_output_ports = [('output', 'InputList', list_type, 0), ('output', 'InputPort', list_type, 1), ('output', 'OutputPort', string_type, 2)] add_input_ports = [('input', 'UseCartesianProduct', bool_type, 1), ('input', 'UserDefinedInputList', list_type, 2)] # Add List port to PythonSource module for each input port selected sortkey = len(base_input_ports) + len(add_input_ports) input_port_names_used = dict([(p[1], 1) for p in base_input_ports]) for input_module, input_portspec, input_connections, halfwidth in input_ports_info: port_name = input_portspec.name if port_name not in input_port_names_used: input_port_names_used[port_name] = 1 else: input_port_names_used[port_name] += 1 port_name += '_%d' % input_port_names_used[port_name] add_input_ports.append(('input', port_name, list_type, sortkey)) sortkey += 1 # Generate the source source_code = ''' psrc_module = self.moduleInfo['pipeline'].modules[self.moduleInfo['moduleId']] input_ports = [p.name for p in psrc_module.input_port_specs if p.name not in ['UseCartesianProduct', 'UserDefinedInputList']] InputPort = input_ports OutputPort = '%s' custom_input_list = self.force_get_input('UserDefinedInputList', []) if custom_input_list: InputList = custom_input_list else: cartesian_product = self.force_get_input('UseCartesianProduct', False) if cartesian_product: input_lists = [self.get_input(input_ports[x]) for x in xrange(len(input_ports))] InputList = [[]] pools = map(tuple, input_lists) for pool in pools: InputList = [x+[y] for x in InputList for y in pool] else: # Dot Product InputList = [] length = len(self.get_input(input_ports[0])) if len(input_ports) > 1: for p in input_ports[1:]: if len(self.get_input(p)) != length: fail('One or more of the input lists have different lengths.') for x in xrange(length): element_list = [] for p in input_ports: element_list.append(self.get_input(p)[x]) InputList.append(element_list) # Compact list format used when only one input port present if len(input_ports) == 1: InputList = [x[0] for x in InputList] ''' % output_portspec.name functions = [('source', [source_code])] self.controller.update_ports_and_functions(py_source_module.id, [], base_input_ports + add_input_ports + base_output_ports, functions) # Create connections to Map map_module = self.controller.current_pipeline.modules[map_module.id] py_source_module = self.controller.current_pipeline.modules[py_source_module.id] psrc_inputlist = py_source_module.get_port_spec('InputList', 'output') psrc_inputport = py_source_module.get_port_spec('InputPort', 'output') psrc_outputport = py_source_module.get_port_spec('OutputPort', 'output') for map_port in map_module.destinationPorts(): # Connect Group 'self' port to Map's FunctionPort if map_port.name == 'FunctionPort': map_conn = self.controller.add_connection(inner_group.id, inner_group_selfport, map_module.id, map_port) # Connect PythonSource output ports to Map input ports elif map_port.name == 'InputList': map_conn = self.controller.add_connection(py_source_module.id, psrc_inputlist, map_module.id, map_port) elif map_port.name == 'InputPort': map_conn = self.controller.add_connection(py_source_module.id, psrc_inputport, map_module.id, map_port) elif map_port.name == 'OutputPort': map_conn = self.controller.add_connection(py_source_module.id, psrc_outputport, map_module.id, map_port) io_connections.append(map_conn) # Create and connect InputPort for each of the PythonSource inputs to force it to exist on group offset = 165 for port_type, port_name, list_type, sortkey in add_input_ports: group_inport_module = self.controller.add_module(bm_identifier, 'InputPort', x=py_source_module.location.x-offset, y=py_source_module.location.y+75) if (port_type, port_name) in [('input', 'UseCartesianProduct'), ('input', 'UserDefinedInputList')]: self.controller.update_ports_and_functions(group_inport_module.id, [], [], [('optional', [True])]) io_modules.append(group_inport_module) offset += 130 input_portspec = py_source_module.get_port_spec(port_name, port_type) for p in group_inport_module.sourcePorts(): if p.name == 'InternalPipe': group_inport_conn = self.controller.add_connection(py_source_module.id, input_portspec, group_inport_module.id, p) io_connections.append(group_inport_conn) break # Create and connect OutputPort from Map to force it to exist on group group_outport_module = self.controller.add_module(bm_identifier, 'OutputPort', x=map_module.location.x, y=map_module.location.y-75) io_modules.append(group_outport_module) output_portspec = map_module.get_port_spec('Result', 'output') for p in group_outport_module.destinationPorts(): if p.name == 'InternalPipe': group_outport_conn = self.controller.add_connection(map_module.id, output_portspec, group_outport_module.id, p) io_connections.append(group_outport_conn) break # Create outer group from PythonSource, Map, and inner Group, along with their connections and IO modules outer_group = self.controller.create_group([m.id for m in io_modules], [c.id for c in io_connections]) self.controller.updatePipelineScene()
class QControlFlowAssistDialog(QtGui.QDialog): def __init__(self, parent, selected_module_ids, selected_connection_ids, scene): """ QControlFlowAssistDialog(selected_module_ids: list, selected_connection_ids: list, scene: QGraphicsScene) -> None Creates the control flow assistant dialog """ # FIXME do this here to avoid circular refs from pipeline_view_select import QReadOnlyPortSelectPipelineView QtGui.QDialog.__init__(self, parent) self.module_ids = selected_module_ids self.connection_ids = selected_connection_ids self.setWindowTitle('Control Flow Assistant') layout = QtGui.QVBoxLayout(self) self.setLayout(layout) # Add instruction label self.instructionLabel = QtGui.QLabel( 'Select one or more Input Ports to receive Lists, and one Output Port to produce a List' ) layout.addWidget(self.instructionLabel) # Add pipeline view self.pipelineView = QReadOnlyPortSelectPipelineView( self, scene, True, selected_module_ids) self.controller = self.pipelineView.scene().controller layout.addWidget(self.pipelineView) self.enablePackage() # Add ok/cancel buttons buttonLayout = QtGui.QHBoxLayout() buttonLayout.setMargin(5) self.okButton = QtGui.QPushButton('&OK', self) self.okButton.setAutoDefault(False) self.okButton.setFixedWidth(100) buttonLayout.addWidget(self.okButton) self.cancelButton = QtGui.QPushButton('&Cancel', self) self.cancelButton.setAutoDefault(False) self.cancelButton.setShortcut('Esc') self.cancelButton.setFixedWidth(100) buttonLayout.addWidget(self.cancelButton) layout.addLayout(buttonLayout) self.connect(self.okButton, QtCore.SIGNAL('clicked(bool)'), self.okClicked) self.connect(self.cancelButton, QtCore.SIGNAL('clicked(bool)'), self.close) def enablePackage(self): """ enablePackge() -> None Tries to enable the controlflow package through the controller. """ pm = get_package_manager() cf_pkg_id = 'org.vistrails.vistrails.control_flow' if not pm.has_package(cf_pkg_id): dep_graph = pm.build_dependency_graph([cf_pkg_id]) if not self.controller.try_to_enable_package(cf_pkg_id, dep_graph): raise MissingPackage(cf_pkg_id) def getInputPortsInfo(self): """ getInputPortsInfo() -> list Gets a list of tuples from the selected input port (QGraphicsPortItem) objects containing: (module, portspec, incoming_connections, halfwidth) """ return [(gport.parentItem().module, gport.port, gport.controller.get_connections_to( gport.controller.current_pipeline, [gport.parentItem().module.id], gport.port.name), (gport.parentItem().boundingRect().right() - gport.parentItem().boundingRect().left()) / 2) for gport in self.pipelineView.getSelectedInputPorts()] def getOutputPortsInfo(self): """ getOutputPortsInfo() -> list Gets a list of tuples from the selected output port (QGraphicsPortItem) objects containing: (module, portspec, outgoing_connections, halfwidth) """ return [(gport.parentItem().module, gport.port, gport.controller.get_connections_from( gport.controller.current_pipeline, [gport.parentItem().module.id], gport.port.name), (gport.parentItem().boundingRect().right() - gport.parentItem().boundingRect().left()) / 2) for gport in self.pipelineView.getSelectedOutputPorts()] def okClicked(self): """ okClicked() -> None Verify selected ports and initiate control flow creation """ try: self.enablePackage() except MissingPackage: debug.critical("The controlflow package is not available") return # Verify that at least one input and one output have been chosen input_ports_info = self.getInputPortsInfo() output_ports_info = self.getOutputPortsInfo() if len(input_ports_info) == 0: show_info( 'No Input Ports Selected', 'No Input Ports have been selected. You must select at least one to proceed.' ) elif len(output_ports_info) == 0: show_info( 'No Output Port Selected', 'No Output Port has been selected. You must select one to proceed.' ) else: self.createControlFlow(input_ports_info, output_ports_info) self.close() def createControlFlow(self, input_ports_info, output_ports_info): """ createControlFlow(input_ports_info: list, output_ports_info: list) -> None Create a control flow from input and output port information. input_ports_info is a list of tuples containing: (module, portspec, incoming_connections, halfwidth) input_ports_info is a list of tuples containing: (module, portspec, outgoing_connections, halfwidth) """ from vistrails.core.modules.basic_modules import identifier as bm_identifier from vistrails.packages.controlflow import identifier as cf_identifier io_modules = [] io_connections = [] # Create and connect InputPort for each of the inputs to force it to exist on group offset = {} for module, portspec, connections, halfwidth in input_ports_info: offset.__setitem__(module, halfwidth + 65) for input_module, input_portspec, input_connections, halfwidth in input_ports_info: # Remove function calls to selected input ports try: function_pos = [f.name for f in input_module.functions ].index(input_portspec.name) self.controller.delete_method(function_pos, input_module.id) except Exception: pass # Disconnect connections to selected input ports for connection in input_connections: self.connection_ids.remove(connection.id) self.controller.delete_connection(connection.id) group_inport_module = self.controller.add_module( bm_identifier, 'InputPort', x=input_module.location.x - offset[input_module], y=input_module.location.y) io_modules.append(group_inport_module) offset[input_module] += 130 for p in group_inport_module.sourcePorts(): if p.name == 'InternalPipe': group_inport_conn = self.controller.add_connection( input_module.id, input_portspec, group_inport_module.id, p) io_connections.append(group_inport_conn) break # Create and connect OutputPort for desired output to force it to exist on group output_module, output_portspec, output_connections, halfwidth = output_ports_info[ 0] # Disconnect connections to selected output port for connection in output_connections: self.connection_ids.remove(connection.id) self.controller.delete_connection(connection.id) group_outport_module = self.controller.add_module( bm_identifier, 'OutputPort', x=output_module.location.x + halfwidth + 75, y=output_module.location.y) io_modules.append(group_outport_module) for p in group_outport_module.destinationPorts(): if p.name == 'InternalPipe': group_outport_conn = self.controller.add_connection( output_module.id, output_portspec, group_outport_module.id, p) io_connections.append(group_outport_conn) break # Create inner group from selected modules and their connections (plus newly created input/output connections) inner_group = self.controller.create_group( self.module_ids + [m.id for m in io_modules], self.connection_ids + [c.id for c in io_connections]) self.controller.updatePipelineScene() del io_modules[:] del io_connections[:] io_modules.append(inner_group) io_connections.extend( self.controller.get_connections_to_and_from( self.controller.current_pipeline, [inner_group.id])) # Add Map module map_module = self.controller.add_module(cf_identifier, 'Map', x=inner_group.location.x - 120, y=inner_group.location.y) io_modules.append(map_module) # Get group 'self' port object for p in inner_group.sourcePorts(): if p.name == 'self': inner_group_selfport = p break # Add PythonSource py_source_module = self.controller.add_module( bm_identifier, 'PythonSource', x=inner_group.location.x, y=inner_group.location.y + 75) io_modules.append(py_source_module) group_type = '(' + bm_identifier + ':Group)' bool_type = '(' + bm_identifier + ':Boolean)' list_type = '(' + bm_identifier + ':List)' string_type = '(' + bm_identifier + ':String)' base_input_ports = [] base_output_ports = [('output', 'InputList', list_type, 0), ('output', 'InputPort', list_type, 1), ('output', 'OutputPort', string_type, 2)] add_input_ports = [('input', 'UseCartesianProduct', bool_type, 1), ('input', 'UserDefinedInputList', list_type, 2)] # Add List port to PythonSource module for each input port selected sortkey = len(base_input_ports) + len(add_input_ports) input_port_names_used = dict([(p[1], 1) for p in base_input_ports]) for input_module, input_portspec, input_connections, halfwidth in input_ports_info: port_name = input_portspec.name if port_name not in input_port_names_used: input_port_names_used[port_name] = 1 else: input_port_names_used[port_name] += 1 port_name += '_%d' % input_port_names_used[port_name] add_input_ports.append(('input', port_name, list_type, sortkey)) sortkey += 1 # Generate the source source_code = ''' psrc_module = self.moduleInfo['pipeline'].modules[self.moduleInfo['moduleId']] input_ports = [p.name for p in psrc_module.input_port_specs if p.name not in ['UseCartesianProduct', 'UserDefinedInputList']] InputPort = input_ports OutputPort = '%s' custom_input_list = self.force_get_input('UserDefinedInputList', []) if custom_input_list: InputList = custom_input_list else: cartesian_product = self.force_get_input('UseCartesianProduct', False) if cartesian_product: input_lists = [self.get_input(input_ports[x]) for x in xrange(len(input_ports))] InputList = [[]] pools = map(tuple, input_lists) for pool in pools: InputList = [x+[y] for x in InputList for y in pool] else: # Dot Product InputList = [] length = len(self.get_input(input_ports[0])) if len(input_ports) > 1: for p in input_ports[1:]: if len(self.get_input(p)) != length: fail('One or more of the input lists have different lengths.') for x in xrange(length): element_list = [] for p in input_ports: element_list.append(self.get_input(p)[x]) InputList.append(element_list) # Compact list format used when only one input port present if len(input_ports) == 1: InputList = [x[0] for x in InputList] print 'InputList: %%s' %% InputList ''' % output_portspec.name functions = [('source', [source_code])] self.controller.update_ports_and_functions( py_source_module.id, [], base_input_ports + add_input_ports + base_output_ports, functions) # Create connections to Map map_module = self.controller.current_pipeline.modules[map_module.id] py_source_module = self.controller.current_pipeline.modules[ py_source_module.id] psrc_inputlist = py_source_module.get_port_spec('InputList', 'output') psrc_inputport = py_source_module.get_port_spec('InputPort', 'output') psrc_outputport = py_source_module.get_port_spec( 'OutputPort', 'output') for map_port in map_module.destinationPorts(): # Connect Group 'self' port to Map's FunctionPort if map_port.name == 'FunctionPort': map_conn = self.controller.add_connection( inner_group.id, inner_group_selfport, map_module.id, map_port) # Connect PythonSource output ports to Map input ports elif map_port.name == 'InputList': map_conn = self.controller.add_connection( py_source_module.id, psrc_inputlist, map_module.id, map_port) elif map_port.name == 'InputPort': map_conn = self.controller.add_connection( py_source_module.id, psrc_inputport, map_module.id, map_port) elif map_port.name == 'OutputPort': map_conn = self.controller.add_connection( py_source_module.id, psrc_outputport, map_module.id, map_port) io_connections.append(map_conn) # Create and connect InputPort for each of the PythonSource inputs to force it to exist on group offset = 165 for port_type, port_name, list_type, sortkey in add_input_ports: group_inport_module = self.controller.add_module( bm_identifier, 'InputPort', x=py_source_module.location.x - offset, y=py_source_module.location.y + 75) if (port_type, port_name) in [('input', 'UseCartesianProduct'), ('input', 'UserDefinedInputList')]: self.controller.update_ports_and_functions( group_inport_module.id, [], [], [('optional', [True])]) io_modules.append(group_inport_module) offset += 130 input_portspec = py_source_module.get_port_spec( port_name, port_type) for p in group_inport_module.sourcePorts(): if p.name == 'InternalPipe': group_inport_conn = self.controller.add_connection( py_source_module.id, input_portspec, group_inport_module.id, p) io_connections.append(group_inport_conn) break # Create and connect OutputPort from Map to force it to exist on group group_outport_module = self.controller.add_module( bm_identifier, 'OutputPort', x=map_module.location.x, y=map_module.location.y - 75) io_modules.append(group_outport_module) output_portspec = map_module.get_port_spec('Result', 'output') for p in group_outport_module.destinationPorts(): if p.name == 'InternalPipe': group_outport_conn = self.controller.add_connection( map_module.id, output_portspec, group_outport_module.id, p) io_connections.append(group_outport_conn) break # Create outer group from PythonSource, Map, and inner Group, along with their connections and IO modules outer_group = self.controller.create_group( [m.id for m in io_modules], [c.id for c in io_connections]) self.controller.updatePipelineScene()