def __init__(self, parent=None): QtGui.QWidget.__init__(self, parent) self.set_title("Mashup Pipeline") layout = QtGui.QVBoxLayout() self.parameter_panel = QAliasParameterPanel() font = QtGui.QFont("Arial", 11, QtGui.QFont.Normal) font.setItalic(True) label = QtGui.QLabel("Double-click a parameter to change alias") label.setFont(font) param_group = QtGui.QGroupBox(self.parameter_panel.windowTitle()) g_layout = QtGui.QVBoxLayout() g_layout.setMargin(0) g_layout.setSpacing(2) g_layout.addWidget(label) g_layout.addWidget(self.parameter_panel) param_group.setLayout(g_layout) layout.addWidget(param_group) self.pipeline_view = QAnnotatedPipelineView() self.pipeline_view.setReadOnlyMode(True) p_view_group = QtGui.QGroupBox(self.pipeline_view.windowTitle()) g_layout = QtGui.QVBoxLayout() g_layout.setMargin(0) g_layout.setSpacing(0) g_layout.addWidget(self.pipeline_view) p_view_group.setLayout(g_layout) layout.addWidget(p_view_group) self.setLayout(layout) self.parameter_panel.treeWidget.aliasChanged.connect(self.aliasChanged)
def __init__(self, controller=None, parent=None): QtGui.QWidget.__init__(self, parent) self.set_title('Pipeline Methods') self.controller = None vLayout = QtGui.QVBoxLayout() vLayout.setMargin(0) vLayout.setSpacing(5) self.setLayout(vLayout) self.toggleUnsetParameters = QtGui.QCheckBox('Show Unset Parameters') vLayout.addWidget(self.toggleUnsetParameters, 0, QtCore.Qt.AlignRight) self.parameterWidget = QParameterWidget() vLayout.addWidget(self.parameterWidget) self.treeWidget = self.parameterWidget.treeWidget self.pipeline_view = QAnnotatedPipelineView() self.pipeline_view.setReadOnlyMode(True) vLayout.addWidget(self.pipeline_view) vLayout.setStretch(0, 0) vLayout.setStretch(1, 1) vLayout.setStretch(2, 0) self.connect(self.toggleUnsetParameters, QtCore.SIGNAL("toggled(bool)"), self.parameterWidget.treeWidget.toggleUnsetParameters) self.set_controller(controller)
def __init__(self, parent=None): """ QParameterExplorationTab(parent: QWidget) -> QParameterExplorationTab Make it a main window with dockable area and a QParameterExplorationTable """ QDockContainer.__init__(self, parent) self.setWindowTitle('Parameter Exploration') self.toolWindow().setFeatures(QtGui.QDockWidget.NoDockWidgetFeatures) self.toolWindow().hide() self.peWidget = QParameterExplorationWidget() self.setCentralWidget(self.peWidget) self.connect(self.peWidget.table, QtCore.SIGNAL('exploreChange(bool)'), self.exploreChange) self.paramView = QParameterView(self) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.paramView.toolWindow()) self.annotatedPipelineView = QAnnotatedPipelineView(self) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.annotatedPipelineView.toolWindow()) self.virtualCell = QVirtualCellWindow(self) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.virtualCell.toolWindow()) self.controller = None self.currentVersion = -1
class QParameterView(QtGui.QWidget, QVistrailsPaletteInterface): """ QParameterView contains the parameter exploration properties and the parameter palette """ def __init__(self, controller=None, parent=None): QtGui.QWidget.__init__(self, parent) self.set_title('Pipeline Methods') self.controller = None vLayout = QtGui.QVBoxLayout() vLayout.setMargin(0) vLayout.setSpacing(5) self.setLayout(vLayout) self.toggleUnsetParameters = QtGui.QCheckBox('Show Unset Parameters') vLayout.addWidget(self.toggleUnsetParameters, 0, QtCore.Qt.AlignRight) self.parameterWidget = QParameterWidget() vLayout.addWidget(self.parameterWidget) self.treeWidget = self.parameterWidget.treeWidget self.pipeline_view = QAnnotatedPipelineView() self.pipeline_view.setReadOnlyMode(True) vLayout.addWidget(self.pipeline_view) vLayout.setStretch(0, 0) vLayout.setStretch(1, 1) vLayout.setStretch(2, 0) self.connect(self.toggleUnsetParameters, QtCore.SIGNAL("toggled(bool)"), self.parameterWidget.treeWidget.toggleUnsetParameters) self.set_controller(controller) def set_controller(self, controller): if self.controller == controller: return self.controller = controller self.pipeline_view.set_controller(controller) if self.controller is not None: self.set_pipeline(controller.current_pipeline) else: self.set_pipeline(None) def set_pipeline(self, pipeline): if self.controller is None: return self.pipeline = pipeline self.parameterWidget.set_pipeline(pipeline, self.controller) if pipeline: self.pipeline_view.scene().setupScene(pipeline) else: self.pipeline_view.scene().clear() self.pipeline_view.updateAnnotatedIds(pipeline)
class QParameterView(QtGui.QWidget, QVistrailsPaletteInterface): """ QParameterView contains the parameter exploration properties and the parameter palette """ def __init__(self, controller=None, parent=None): QtGui.QWidget.__init__(self, parent) self.set_title('Pipeline Methods') self.controller = None vLayout = QtGui.QVBoxLayout() vLayout.setMargin(0) vLayout.setSpacing(5) self.setLayout(vLayout) self.toggleUnsetParameters = QtGui.QCheckBox('Show Unset Parameters') vLayout.addWidget(self.toggleUnsetParameters, 0, QtCore.Qt.AlignRight) self.parameterWidget = QParameterWidget() vLayout.addWidget(self.parameterWidget) self.treeWidget = self.parameterWidget.treeWidget self.pipeline_view = QAnnotatedPipelineView() self.pipeline_view.setReadOnlyMode(True) vLayout.addWidget(self.pipeline_view) vLayout.setStretch(0,0) vLayout.setStretch(1,1) vLayout.setStretch(2,0) self.connect(self.toggleUnsetParameters, QtCore.SIGNAL("toggled(bool)"), self.parameterWidget.treeWidget.toggleUnsetParameters) self.set_controller(controller) def set_controller(self, controller): if self.controller == controller: return self.controller = controller self.pipeline_view.set_controller(controller) if self.controller is not None: self.set_pipeline(controller.current_pipeline) else: self.set_pipeline(None) def set_pipeline(self, pipeline): if self.controller is None: return self.pipeline = pipeline self.parameterWidget.set_pipeline(pipeline, self.controller) if pipeline: self.pipeline_view.scene().setupScene(pipeline) else: self.pipeline_view.scene().clear() self.pipeline_view.updateAnnotatedIds(pipeline)
def setCellData(self, cellType, cellId): """ setCellData(cellType: str, cellId: int) -> None Create an image based on the cell type and id. Then assign it to the label. If cellType is None, the cell will be drawn with transparent background. If cellType is '', the cell will be drawn with the caption 'Empty'. Otherwise, the cell will be drawn with white background containing cellType as caption and a small rounded shape on the lower right painted with cellId """ self.type = cellType self.id = cellId size = QtCore.QSize(*CurrentTheme.VIRTUAL_CELL_LABEL_SIZE) image = QtGui.QImage(size.width() + 12, size.height() + 12, QtGui.QImage.Format_ARGB32_Premultiplied) image.fill(0) font = QtGui.QFont() font.setStyleStrategy(QtGui.QFont.ForceOutline) painter = QtGui.QPainter() painter.begin(image) painter.setRenderHint(QtGui.QPainter.Antialiasing) if self.type is None: painter.setPen(QtCore.Qt.NoPen) painter.setBrush(QtCore.Qt.NoBrush) else: if self.type == '': painter.setPen(QtCore.Qt.gray) painter.setBrush(QtCore.Qt.NoBrush) else: painter.setPen(QtCore.Qt.black) painter.setBrush(QtCore.Qt.lightGray) painter.drawRoundRect( QtCore.QRectF(0.5, 0.5, image.width() - 1, image.height() - 1), 25, 25) painter.setFont(font) if self.type is not None: painter.drawText( QtCore.QRect(QtCore.QPoint(6, 6), size), QtCore.Qt.AlignCenter | QtCore.Qt.TextWrapAnywhere, split_camel_case(self.type)) # Draw the lower right corner number if there is an id if self.id >= 0 and self.type: QAnnotatedPipelineView.drawId( painter, image.rect(), self.id, QtCore.Qt.AlignRight | QtCore.Qt.AlignBottom) painter.end() self.setPixmap(QtGui.QPixmap.fromImage(image))
def setCellData(self, cellType, cellId): """ setCellData(cellType: str, cellId: int) -> None Create an image based on the cell type and id. Then assign it to the label. If cellType is None, the cell will be drawn with transparent background. If cellType is '', the cell will be drawn with the caption 'Empty'. Otherwise, the cell will be drawn with white background containing cellType as caption and a small rounded shape on the lower right painted with cellId """ self.type = cellType self.id = cellId size = QtCore.QSize(*CurrentTheme.VIRTUAL_CELL_LABEL_SIZE) image = QtGui.QImage(size.width() + 12, size.height()+ 12, QtGui.QImage.Format_ARGB32_Premultiplied) image.fill(0) font = QtGui.QFont() font.setStyleStrategy(QtGui.QFont.ForceOutline) painter = QtGui.QPainter() painter.begin(image) painter.setRenderHint(QtGui.QPainter.Antialiasing) if self.type==None: painter.setPen(QtCore.Qt.NoPen) painter.setBrush(QtCore.Qt.NoBrush) else: if self.type=='': painter.setPen(QtCore.Qt.gray) painter.setBrush(QtCore.Qt.NoBrush) else: painter.setPen(QtCore.Qt.black) painter.setBrush(QtCore.Qt.lightGray) painter.drawRoundRect(QtCore.QRectF(0.5, 0.5, image.width()-1, image.height()-1), 25, 25) painter.setFont(font) if self.type!=None: painter.drawText(QtCore.QRect(QtCore.QPoint(6, 6), size), QtCore.Qt.AlignCenter | QtCore.Qt.TextWrapAnywhere, split_camel_case(self.type)) # Draw the lower right corner number if there is an id if self.id>=0 and self.type: QAnnotatedPipelineView.drawId(painter, image.rect(), self.id, QtCore.Qt.AlignRight | QtCore.Qt.AlignBottom) painter.end() self.setPixmap(QtGui.QPixmap.fromImage(image))
def paint(self, painter, option, index): """ painter(painter: QPainter, option QStyleOptionViewItem, index: QModelIndex) -> None Repaint the top-level item to have a button-look style """ model = index.model() if (model.parent(index).isValid()==False or model.parent(index).parent().isValid()==False): style = self.treeView.style() r = option.rect textrect = QtCore.QRect(r.left() + 10, r.top(), r.width() - 10, r.height()) font = painter.font() font.setBold(True) painter.setFont(font) text = option.fontMetrics.elidedText( model.data(index, QtCore.Qt.DisplayRole), QtCore.Qt.ElideMiddle, textrect.width()-10) style.drawItemText(painter, textrect, QtCore.Qt.AlignLeft, option.palette, self.treeView.isEnabled(), text) painter.setPen(QtGui.QPen(QtCore.Qt.black)) fm = QtGui.QFontMetrics(font) size = fm.size(QtCore.Qt.TextSingleLine, text) #painter.drawLine(textrect.left()-5, # textrect.bottom()-1, # textrect.left()+size.width()+5, # textrect.bottom()-1) annotatedId = model.data(index, QtCore.Qt.UserRole+1) if annotatedId: idRect = QtCore.QRect( QtCore.QPoint(textrect.left()+size.width()+5, textrect.top()), textrect.bottomRight()) QAnnotatedPipelineView.drawId(painter, idRect, annotatedId, QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) else: QtGui.QItemDelegate.paint(self, painter, option, index)
def __init__(self, controller=None, parent=None): QtGui.QWidget.__init__(self, parent) self.set_title('Pipeline Methods') self.controller = controller vLayout = QtGui.QVBoxLayout() vLayout.setMargin(0) vLayout.setSpacing(5) self.setLayout(vLayout) self.toggleUnsetParameters = QtGui.QCheckBox('Show Unset Parameters') vLayout.addWidget(self.toggleUnsetParameters, 0, QtCore.Qt.AlignRight) self.parameterWidget = QParameterWidget() vLayout.addWidget(self.parameterWidget) self.treeWidget = self.parameterWidget.treeWidget self.pipeline_view = QAnnotatedPipelineView() vLayout.addWidget(self.pipeline_view) vLayout.setStretch(0,0) vLayout.setStretch(1,1) vLayout.setStretch(2,0) self.connect(self.toggleUnsetParameters, QtCore.SIGNAL("toggled(bool)"), self.parameterWidget.treeWidget.toggleUnsetParameters)
class QAliasParameterView(QtGui.QWidget, QVistrailsPaletteInterface): def __init__(self, parent=None): QtGui.QWidget.__init__(self, parent) self.set_title("Mashup Pipeline") layout = QtGui.QVBoxLayout() self.parameter_panel = QAliasParameterPanel() font = QtGui.QFont("Arial", 11, QtGui.QFont.Normal) font.setItalic(True) label = QtGui.QLabel("Double-click a parameter to change alias") label.setFont(font) param_group = QtGui.QGroupBox(self.parameter_panel.windowTitle()) g_layout = QtGui.QVBoxLayout() g_layout.setMargin(0) g_layout.setSpacing(2) g_layout.addWidget(label) g_layout.addWidget(self.parameter_panel) param_group.setLayout(g_layout) layout.addWidget(param_group) self.pipeline_view = QAnnotatedPipelineView() self.pipeline_view.setReadOnlyMode(True) p_view_group = QtGui.QGroupBox(self.pipeline_view.windowTitle()) g_layout = QtGui.QVBoxLayout() g_layout.setMargin(0) g_layout.setSpacing(0) g_layout.addWidget(self.pipeline_view) p_view_group.setLayout(g_layout) layout.addWidget(p_view_group) self.setLayout(layout) self.parameter_panel.treeWidget.aliasChanged.connect(self.aliasChanged) def updateMshpController(self, mshpController): from vistrails.gui.vistrails_window import _app self.mshpController = mshpController self.parameter_panel.set_pipeline(self.mshpController.vtPipeline) self.pipeline_view.set_controller(self.mshpController.vtController) self.mshpController.vtController.current_pipeline_view = \ self.pipeline_view self.pipeline_view.scene( ).current_pipeline = self.mshpController.vtPipeline self.mshpController.vtController.current_pipeline = self.mshpController.vtPipeline #print "**** should update mashup pipeline view " #self.pipeline_view.scene().setupScene(self.mshpController.vtPipeline) self.pipeline_view.scene().clear() self.pipeline_view.version_changed() self.pipeline_view.updateAnnotatedIds(self.mshpController.vtPipeline) #_app.notify('mashup_pipeline_view_set') def updateMshpVersion(self, version): #print "will update alias param view" self.parameter_panel.set_pipeline(self.mshpController.vtPipeline) self.pipeline_view.version_changed() def zoomToFit(self): if self.pipeline_view: self.pipeline_view.zoomToFit() def aliasChanged(self, param): from vistrails.gui.vistrails_window import _app _app.notify('alias_changed', param)
class QParameterExplorationTab(QDockContainer, QToolWindowInterface): """ QParameterExplorationTab is a tab containing different widgets related to parameter exploration """ explorationId = 0 def __init__(self, parent=None): """ QParameterExplorationTab(parent: QWidget) -> QParameterExplorationTab Make it a main window with dockable area and a QParameterExplorationTable """ QDockContainer.__init__(self, parent) self.setWindowTitle('Parameter Exploration') self.toolWindow().setFeatures(QtGui.QDockWidget.NoDockWidgetFeatures) self.toolWindow().hide() self.peWidget = QParameterExplorationWidget() self.setCentralWidget(self.peWidget) self.connect(self.peWidget.table, QtCore.SIGNAL('exploreChange(bool)'), self.exploreChange) self.paramView = QParameterView(self) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.paramView.toolWindow()) self.annotatedPipelineView = QAnnotatedPipelineView(self) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.annotatedPipelineView.toolWindow()) self.virtualCell = QVirtualCellWindow(self) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.virtualCell.toolWindow()) self.controller = None self.currentVersion = -1 def addViewActionsToMenu(self, menu): """addViewActionsToMenu(menu: QMenu) -> None Add toggle view actions to menu """ menu.addAction(self.paramView.toolWindow().toggleViewAction()) menu.addAction(self.annotatedPipelineView.toolWindow().toggleViewAction()) menu.addAction(self.virtualCell.toolWindow().toggleViewAction()) def removeViewActionsFromMenu(self, menu): """removeViewActionsFromMenu(menu: QMenu) -> None Remove toggle view actions from menu """ menu.removeAction(self.paramView.toolWindow().toggleViewAction()) menu.removeAction(self.annotatedPipelineView.toolWindow().toggleViewAction()) menu.removeAction(self.virtualCell.toolWindow().toggleViewAction()) def setController(self, controller): """ setController(controller: VistrailController) -> None Assign a controller to the parameter exploration tab """ self.controller = controller def getParameterExploration(self): """ getParameterExploration() -> string Generates an XML string that represents the current parameter exploration, and which can be loaded with setParameterExploration(). """ # Construct xml for persisting parameter exploration escape_dict = { "'":"'", '"':'"', '\n':'
' } timestamp = strftime(current_time(), '%Y-%m-%d %H:%M:%S') # TODO: For now, we use the timestamp as the 'name' - Later, we should set 'name' based on a UI input field xml = '\t<paramexp dims="%s" layout="%s" date="%s" name="%s">' % (str(self.peWidget.table.label.getCounts()), str(self.virtualCell.getConfiguration()[2]), timestamp, timestamp) for i in xrange(self.peWidget.table.layout().count()): pEditor = self.peWidget.table.layout().itemAt(i).widget() if pEditor and isinstance(pEditor, QParameterSetEditor): firstParam = True for paramWidget in pEditor.paramWidgets: paramInfo = paramWidget.param interpolator = paramWidget.editor.stackedEditors.currentWidget() intType = interpolator.exploration_name # Write function tag prior to the first parameter of the function if firstParam: xml += '\n\t\t<function id="%s" alias="%s" name="%s">' % (paramInfo.parent_id, paramInfo.is_alias, pEditor.info[0]) firstParam = False # Write parameter tag xml += '\n\t\t\t<param id="%s" dim="%s" interp="%s"' % (paramInfo.id, paramWidget.getDimension(), intType) if intType == 'Linear Interpolation': xml += ' min="%s" max="%s"' % (interpolator.fromEdit.get_value(), interpolator.toEdit.get_value()) elif intType == 'List': xml += ' values="%s"' % escape(str(interpolator._str_values), escape_dict) elif intType == 'User-defined Function': xml += ' code="%s"' % escape(interpolator.function, escape_dict) xml += '/>' xml += '\n\t\t</function>' xml += '\n\t</paramexp>' return xml def setParameterExploration(self, xmlString): """ setParameterExploration(xmlString: string) -> None Sets the current parameter exploration to the one defined by 'xmlString'. """ if not xmlString: return # Parse/validate the xml try: xmlDoc = parseString(xmlString).documentElement except Exception: debug.critical("Parameter Exploration load failed because of " "invalid XML:\n\n%s" % xmlString) return # Set the exploration dimensions dims = literal_eval(xmlDoc.attributes['dims'].value) self.peWidget.table.label.setCounts(dims) # Set the virtual cell layout layout = literal_eval(xmlDoc.attributes['layout'].value) self.virtualCell.setConfiguration(layout) # Populate parameter exploration window with stored functions and aliases for f in xmlDoc.getElementsByTagName('function'): # Retrieve function attributes f_id = long(f.attributes['id'].value) f_name = str(f.attributes['name'].value) f_is_alias = (str(f.attributes['alias'].value) == 'True') # Search the parameter treeWidget for this function and add it directly newEditor = None for tidx in xrange(self.paramView.treeWidget.topLevelItemCount()): moduleItem = self.paramView.treeWidget.topLevelItem(tidx) for cidx in xrange(moduleItem.childCount()): paramInfo = moduleItem.child(cidx).parameter name, params = paramInfo if params[0].parent_id == f_id and params[0].is_alias == f_is_alias: newEditor = self.peWidget.table.addParameter(paramInfo) # Retrieve params for this function and set their values in the UI if newEditor: for p in f.getElementsByTagName('param'): # Locate the param in the newly added param editor and set values p_id = long(p.attributes['id'].value) for paramWidget in newEditor.paramWidgets: if paramWidget.param.id == p_id: # Set Parameter Dimension (radio button) p_dim = int(p.attributes['dim'].value) paramWidget.setDimension(p_dim) # Set Interpolator Type (dropdown list) p_intType = str(p.attributes['interp'].value) paramWidget.editor.selectInterpolator(p_intType) # Set Interpolator Value(s) interpolator = paramWidget.editor.stackedEditors.currentWidget() if p_intType == 'Linear Interpolation': # Set min/max p_min = str(p.attributes['min'].value) p_max = str(p.attributes['max'].value) interpolator.fromEdit.setText(p_min) interpolator.toEdit.setText(p_max) elif p_intType == 'List': p_values = str(p.attributes['values'].value) # Set internal list structure interpolator._str_values = \ literal_eval(p_values) # Update UI list if interpolator.type == 'String': interpolator.listValues.setText(p_values) else: interpolator.listValues.setText(p_values.replace("'", "").replace('"', '')) elif p_intType == 'User-defined Function': # Set function code p_code = str(p.attributes['code'].value) interpolator.function = p_code def showEvent(self, event): """ showEvent(event: QShowEvent) -> None Update the tab when it is shown """ if self.currentVersion!=self.controller.current_version: self.currentVersion = self.controller.current_version # Update the virtual cell pipeline = self.controller.current_pipeline self.virtualCell.updateVirtualCell(pipeline) # Now we need to inspect the parameter list self.paramView.treeWidget.updateFromPipeline(pipeline) # Update the annotated ids self.annotatedPipelineView.updateAnnotatedIds(pipeline) # Update the parameter exploration table self.peWidget.updatePipeline(pipeline) # Update the UI with the most recent parameter exploration # TODO: For now, we just strip the root tags since there's only one # exploration - Later we should parse the root tree and select # the active exploration based on date, or user choice xmlString = self.controller.vistrail.get_paramexp(self.currentVersion) if xmlString is not None: striplen = len("<paramexps>") xmlString = xmlString[striplen:-(striplen+1)].strip() self.setParameterExploration(xmlString) def performParameterExploration(self): """ performParameterExploration() -> None Perform the exploration by collecting a list of actions corresponding to each dimension """ registry = get_module_registry() actions = self.peWidget.table.collectParameterActions() spreadsheet_pkg = '%s.spreadsheet' % get_vistrails_default_pkg_prefix() # Set the annotation to persist the parameter exploration # TODO: For now, we just replace the existing exploration - Later we should append them. xmlString = "<paramexps>\n" + self.getParameterExploration() + "\n</paramexps>" self.controller.vistrail.set_paramexp(self.currentVersion, xmlString) self.controller.set_changed(True) if self.controller.current_pipeline and actions: explorer = ActionBasedParameterExploration() (pipelines, performedActions) = explorer.explore( self.controller.current_pipeline, actions) dim = [max(1, len(a)) for a in actions] if (registry.has_module(spreadsheet_pkg, 'CellLocation') and registry.has_module(spreadsheet_pkg, 'SheetReference')): modifiedPipelines = self.virtualCell.positionPipelines( 'PE#%d %s' % (QParameterExplorationTab.explorationId, self.controller.name), dim[2], dim[1], dim[0], pipelines, self.controller) else: modifiedPipelines = pipelines mCount = [] for p in modifiedPipelines: if len(mCount)==0: mCount.append(0) else: mCount.append(len(p.modules)+mCount[len(mCount)-1]) # Now execute the pipelines totalProgress = sum([len(p.modules) for p in modifiedPipelines]) progress = QtGui.QProgressDialog('Performing Parameter ' 'Exploration...', '&Cancel', 0, totalProgress) progress.setWindowTitle('Parameter Exploration') progress.setWindowModality(QtCore.Qt.WindowModal) progress.show() QParameterExplorationTab.explorationId += 1 interpreter = get_default_interpreter() for pi in xrange(len(modifiedPipelines)): progress.setValue(mCount[pi]) QtCore.QCoreApplication.processEvents() if progress.wasCanceled(): break def moduleExecuted(objId): if not progress.wasCanceled(): #progress.setValue(progress.value()+1) #the call above was crashing when used by multithreaded #code, replacing with the call below (thanks to Terence #for submitting this fix). QtCore.QMetaObject.invokeMethod(progress, "setValue", QtCore.Q_ARG(int,progress.value()+1)) QtCore.QCoreApplication.processEvents() kwargs = {'locator': self.controller.locator, 'current_version': self.controller.current_version, 'view': self.controller.current_pipeline_scene, 'module_executed_hook': [moduleExecuted], 'reason': 'Parameter Exploration', 'actions': performedActions[pi], } interpreter.execute(modifiedPipelines[pi], **kwargs) progress.setValue(totalProgress) def exploreChange(self, notEmpty): """ exploreChange(notEmpty: bool) -> None echo the signal """ self.emit(QtCore.SIGNAL('exploreChange(bool)'), notEmpty)
class QParameterExplorationTab(QDockContainer, QToolWindowInterface): """ QParameterExplorationTab is a tab containing different widgets related to parameter exploration """ explorationId = 0 def __init__(self, parent=None): """ QParameterExplorationTab(parent: QWidget) -> QParameterExplorationTab Make it a main window with dockable area and a QParameterExplorationTable """ QDockContainer.__init__(self, parent) self.setWindowTitle('Parameter Exploration') self.toolWindow().setFeatures(QtGui.QDockWidget.NoDockWidgetFeatures) self.toolWindow().hide() self.peWidget = QParameterExplorationWidget() self.setCentralWidget(self.peWidget) self.connect(self.peWidget.table, QtCore.SIGNAL('exploreChange(bool)'), self.exploreChange) self.paramView = QParameterView(self) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.paramView.toolWindow()) self.annotatedPipelineView = QAnnotatedPipelineView(self) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.annotatedPipelineView.toolWindow()) self.virtualCell = QVirtualCellWindow(self) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.virtualCell.toolWindow()) self.controller = None self.currentVersion = -1 def addViewActionsToMenu(self, menu): """addViewActionsToMenu(menu: QMenu) -> None Add toggle view actions to menu """ menu.addAction(self.paramView.toolWindow().toggleViewAction()) menu.addAction(self.annotatedPipelineView.toolWindow().toggleViewAction()) menu.addAction(self.virtualCell.toolWindow().toggleViewAction()) def removeViewActionsFromMenu(self, menu): """removeViewActionsFromMenu(menu: QMenu) -> None Remove toggle view actions from menu """ menu.removeAction(self.paramView.toolWindow().toggleViewAction()) menu.removeAction(self.annotatedPipelineView.toolWindow().toggleViewAction()) menu.removeAction(self.virtualCell.toolWindow().toggleViewAction()) def setController(self, controller): """ setController(controller: VistrailController) -> None Assign a controller to the parameter exploration tab """ self.controller = controller def getParameterExploration(self): """ getParameterExploration() -> string Generates an XML string that represents the current parameter exploration, and which can be loaded with setParameterExploration(). """ # Construct xml for persisting parameter exploration escape_dict = { "'":"'", '"':'"', '\n':'
' } timestamp = strftime(current_time(), '%Y-%m-%d %H:%M:%S') # TODO: For now, we use the timestamp as the 'name' - Later, we should set 'name' based on a UI input field xml = '\t<paramexp dims="%s" layout="%s" date="%s" name="%s">' % (str(self.peWidget.table.label.getCounts()), str(self.virtualCell.getConfiguration()[2]), timestamp, timestamp) for i in xrange(self.peWidget.table.layout().count()): pEditor = self.peWidget.table.layout().itemAt(i).widget() if pEditor and isinstance(pEditor, QParameterSetEditor): firstParam = True for paramWidget in pEditor.paramWidgets: paramInfo = paramWidget.param interpolator = paramWidget.editor.stackedEditors.currentWidget() intType = interpolator.exploration_name # Write function tag prior to the first parameter of the function if firstParam: xml += '\n\t\t<function id="%s" alias="%s" name="%s">' % (paramInfo.parent_id, paramInfo.is_alias, pEditor.info[0]) firstParam = False # Write parameter tag xml += '\n\t\t\t<param id="%s" dim="%s" interp="%s"' % (paramInfo.id, paramWidget.getDimension(), intType) if intType == 'Linear Interpolation': xml += ' min="%s" max="%s"' % (interpolator.fromEdit.get_value(), interpolator.toEdit.get_value()) elif intType == 'List': xml += ' values="%s"' % escape(str(interpolator._str_values), escape_dict) elif intType == 'User-defined Function': xml += ' code="%s"' % escape(interpolator.function, escape_dict) xml += '/>' xml += '\n\t\t</function>' xml += '\n\t</paramexp>' return xml def setParameterExploration(self, xmlString): """ setParameterExploration(xmlString: string) -> None Sets the current parameter exploration to the one defined by 'xmlString'. """ if not xmlString: return # Parse/validate the xml try: xmlDoc = parseString(xmlString).documentElement except Exception: debug.critical("Parameter Exploration load failed because of " "invalid XML:\n\n%s" % xmlString) return # Set the exploration dimensions dims = literal_eval(xmlDoc.attributes['dims'].value) self.peWidget.table.label.setCounts(dims) # Set the virtual cell layout layout = literal_eval(xmlDoc.attributes['layout'].value) self.virtualCell.setConfiguration(layout) # Populate parameter exploration window with stored functions and aliases for f in xmlDoc.getElementsByTagName('function'): # Retrieve function attributes f_id = long(f.attributes['id'].value) f_is_alias = (str(f.attributes['alias'].value) == 'True') # Search the parameter treeWidget for this function and add it directly newEditor = None for tidx in xrange(self.paramView.treeWidget.topLevelItemCount()): moduleItem = self.paramView.treeWidget.topLevelItem(tidx) for cidx in xrange(moduleItem.childCount()): paramInfo = moduleItem.child(cidx).parameter name, params = paramInfo if params[0].parent_id == f_id and params[0].is_alias == f_is_alias: newEditor = self.peWidget.table.addParameter(paramInfo) # Retrieve params for this function and set their values in the UI if newEditor: for p in f.getElementsByTagName('param'): # Locate the param in the newly added param editor and set values p_id = long(p.attributes['id'].value) for paramWidget in newEditor.paramWidgets: if paramWidget.param.id == p_id: # Set Parameter Dimension (radio button) p_dim = int(p.attributes['dim'].value) paramWidget.setDimension(p_dim) # Set Interpolator Type (dropdown list) p_intType = str(p.attributes['interp'].value) paramWidget.editor.selectInterpolator(p_intType) # Set Interpolator Value(s) interpolator = paramWidget.editor.stackedEditors.currentWidget() if p_intType == 'Linear Interpolation': # Set min/max p_min = str(p.attributes['min'].value) p_max = str(p.attributes['max'].value) interpolator.fromEdit.setText(p_min) interpolator.toEdit.setText(p_max) elif p_intType == 'List': p_values = str(p.attributes['values'].value) # Set internal list structure interpolator._str_values = \ literal_eval(p_values) # Update UI list if interpolator.type == 'String': interpolator.listValues.setText(p_values) else: interpolator.listValues.setText(p_values.replace("'", "").replace('"', '')) elif p_intType == 'User-defined Function': # Set function code p_code = str(p.attributes['code'].value) interpolator.function = p_code def showEvent(self, event): """ showEvent(event: QShowEvent) -> None Update the tab when it is shown """ if self.currentVersion!=self.controller.current_version: self.currentVersion = self.controller.current_version # Update the virtual cell pipeline = self.controller.current_pipeline self.virtualCell.updateVirtualCell(pipeline) # Now we need to inspect the parameter list self.paramView.treeWidget.updateFromPipeline(pipeline) # Update the annotated ids self.annotatedPipelineView.updateAnnotatedIds(pipeline) # Update the parameter exploration table self.peWidget.updatePipeline(pipeline) # Update the UI with the most recent parameter exploration # TODO: For now, we just strip the root tags since there's only one # exploration - Later we should parse the root tree and select # the active exploration based on date, or user choice xmlString = self.controller.vistrail.get_paramexp(self.currentVersion) if xmlString is not None: striplen = len("<paramexps>") xmlString = xmlString[striplen:-(striplen+1)].strip() self.setParameterExploration(xmlString) def performParameterExploration(self): """ performParameterExploration() -> None Perform the exploration by collecting a list of actions corresponding to each dimension """ registry = get_module_registry() actions = self.peWidget.table.collectParameterActions() spreadsheet_pkg = 'org.vistrails.vistrails.spreadsheet' # Set the annotation to persist the parameter exploration # TODO: For now, we just replace the existing exploration - Later we should append them. xmlString = "<paramexps>\n" + self.getParameterExploration() + "\n</paramexps>" self.controller.vistrail.set_paramexp(self.currentVersion, xmlString) self.controller.set_changed(True) if self.controller.current_pipeline and actions: explorer = ActionBasedParameterExploration() (pipelines, performedActions) = explorer.explore( self.controller.current_pipeline, actions) dim = [max(1, len(a)) for a in actions] if (registry.has_module(spreadsheet_pkg, 'CellLocation') and registry.has_module(spreadsheet_pkg, 'SheetReference')): modifiedPipelines = self.virtualCell.positionPipelines( 'PE#%d %s' % (QParameterExplorationTab.explorationId, self.controller.name), dim[2], dim[1], dim[0], pipelines, self.controller) else: modifiedPipelines = pipelines mCount = [] for p in modifiedPipelines: if len(mCount)==0: mCount.append(0) else: mCount.append(len(p.modules)+mCount[len(mCount)-1]) # Now execute the pipelines totalProgress = sum([len(p.modules) for p in modifiedPipelines]) progress = QtGui.QProgressDialog('Performing Parameter ' 'Exploration...', '&Cancel', 0, totalProgress) progress.setWindowTitle('Parameter Exploration') progress.setWindowModality(QtCore.Qt.WindowModal) progress.show() QParameterExplorationTab.explorationId += 1 interpreter = get_default_interpreter() for pi in xrange(len(modifiedPipelines)): progress.setValue(mCount[pi]) QtCore.QCoreApplication.processEvents() if progress.wasCanceled(): break def moduleExecuted(objId): if not progress.wasCanceled(): #progress.setValue(progress.value()+1) #the call above was crashing when used by multithreaded #code, replacing with the call below (thanks to Terence #for submitting this fix). QtCore.QMetaObject.invokeMethod(progress, "setValue", QtCore.Q_ARG(int,progress.value()+1)) QtCore.QCoreApplication.processEvents() kwargs = {'locator': self.controller.locator, 'current_version': self.controller.current_version, 'view': self.controller.current_pipeline_scene, 'module_executed_hook': [moduleExecuted], 'reason': 'Parameter Exploration', 'actions': performedActions[pi], } interpreter.execute(modifiedPipelines[pi], **kwargs) progress.setValue(totalProgress) def exploreChange(self, notEmpty): """ exploreChange(notEmpty: bool) -> None echo the signal """ self.emit(QtCore.SIGNAL('exploreChange(bool)'), notEmpty)
class QAliasParameterView(QtGui.QWidget, QVistrailsPaletteInterface): def __init__(self, parent=None): QtGui.QWidget.__init__(self, parent) self.set_title("Mashup Pipeline") layout = QtGui.QVBoxLayout() self.parameter_panel = QAliasParameterPanel() font = QtGui.QFont("Arial", 11, QtGui.QFont.Normal) font.setItalic(True) label = QtGui.QLabel("Double-click a parameter to change alias") label.setFont(font) param_group = QtGui.QGroupBox(self.parameter_panel.windowTitle()) g_layout = QtGui.QVBoxLayout() g_layout.setMargin(0) g_layout.setSpacing(2) g_layout.addWidget(label) g_layout.addWidget(self.parameter_panel) param_group.setLayout(g_layout) layout.addWidget(param_group) self.pipeline_view = QAnnotatedPipelineView() self.pipeline_view.setReadOnlyMode(True) p_view_group = QtGui.QGroupBox(self.pipeline_view.windowTitle()) g_layout = QtGui.QVBoxLayout() g_layout.setMargin(0) g_layout.setSpacing(0) g_layout.addWidget(self.pipeline_view) p_view_group.setLayout(g_layout) layout.addWidget(p_view_group) self.setLayout(layout) self.parameter_panel.treeWidget.aliasChanged.connect(self.aliasChanged) def updateMshpController(self, mshpController): from vistrails.gui.vistrails_window import _app self.mshpController = mshpController self.parameter_panel.set_pipeline(self.mshpController.vtPipeline) self.pipeline_view.set_controller(self.mshpController.vtController) self.mshpController.vtController.current_pipeline_view = self.pipeline_view self.pipeline_view.scene().current_pipeline = self.mshpController.vtPipeline self.mshpController.vtController.current_pipeline = self.mshpController.vtPipeline # print "**** should update mashup pipeline view " # self.pipeline_view.scene().setupScene(self.mshpController.vtPipeline) self.pipeline_view.scene().clear() self.pipeline_view.version_changed() self.pipeline_view.updateAnnotatedIds(self.mshpController.vtPipeline) # _app.notify('mashup_pipeline_view_set') def updateMshpVersion(self, version): # print "will update alias param view" self.parameter_panel.set_pipeline(self.mshpController.vtPipeline) self.pipeline_view.version_changed() def zoomToFit(self): if self.pipeline_view: self.pipeline_view.zoomToFit() def aliasChanged(self, param): from vistrails.gui.vistrails_window import _app _app.notify("alias_changed", param)