def __init__(self, data_source, input_link=None, highlight_link=None): """Parallel coordinates view constructor needs a valid DataSource plus and external annotation link (from the icicle view). """ self.ds = data_source self.input_link = None if input_link is not None: self.SetInputAnnotationLink(input_link) # Set up a 2D scene, add an XY chart to it self.view = vtk.vtkContextView() self.view.GetRenderer().SetBackground(1.0, 1.0, 1.0) self.view.GetRenderWindow().SetSize(600,300) self.chart = vtkvtg.vtkMyChartParallelCoordinates() self.highlight_link = None if highlight_link is not None: self.SetHighlightAnnotationLink(highlight_link) # Create a annotation link to access selection in parallel coordinates view self.link = vtk.vtkAnnotationLink() # If you don't set the FieldType explicitly it ends up as UNKNOWN (as of 21 Feb 2010) # See vtkSelectionNode doc for field and content type enum values self.link.GetCurrentSelection().GetNode(0).SetFieldType(1) # Point # The chart seems to force INDEX selection, so I'm using vtkConvertSelection below to get # out PedigreeIds... self.link.GetCurrentSelection().GetNode(0).SetContentType(4) # 2 = PedigreeIds, 4 = Indices # Connect the annotation link to the parallel coordinates representation self.chart.SetAnnotationLink(self.link) # Set up callback for ID -> Pedigree ID conversion & copy to output link self.link.AddObserver("AnnotationChangedEvent", self.PCoordsSelectionCallback) # Set up output annotation link which will carry pedigree ids to image flow view # Type and field will be set during conversion to pedigree ids in PCoordsSelectionCallback self.output_link = vtk.vtkAnnotationLink() self.view.GetScene().AddItem(self.chart) # self.view.ResetCamera() # self.view.Render() # Set default scale range to show: 'all', 'coarse', 'fine' # TODO: Should check the menu to see which is checked so default is # set by GUI self.scale_range = 'coarse' # Want to keep track of whether the node coming in on the input_link # is new or not self.input_link_idx = 0 # Flag for whether to color by 'category_ids' # TODO: Should check the menu to see which is checked so default is # set by GUI self.SetColorByArray("None")
def __init__(self, parent=None): QCellWidget.__init__(self, parent) centralLayout = QtGui.QVBoxLayout() self.setLayout(centralLayout) centralLayout.setMargin(0) centralLayout.setSpacing(0) self.view = vtk.vtkContextView() self.widget = QVTKRenderWindowInteractor(self, rw=self.view.GetRenderWindow(), iren=self.view.GetInteractor() ) self.chart = vtk.vtkChartParallelCoordinates() self.view.GetScene().AddItem(self.chart) self.layout().addWidget(self.widget) # Create a annotation link to access selection in parallel coordinates view self.annotationLink = vtk.vtkAnnotationLink() # If you don't set the FieldType explicitly it ends up as UNKNOWN (as of 21 Feb 2010) # See vtkSelectionNode doc for field and content type enum values self.annotationLink.GetCurrentSelection().GetNode(0).SetFieldType(1) # Point self.annotationLink.GetCurrentSelection().GetNode(0).SetContentType(4) # Indices # Connect the annotation link to the parallel coordinates representation self.chart.SetAnnotationLink(self.annotationLink) self.annotationLink.AddObserver("AnnotationChangedEvent", self.selectionCallback)
def __init__(self, parent=None): QCellWidget.__init__(self, parent) centralLayout = QtGui.QVBoxLayout() self.setLayout(centralLayout) centralLayout.setMargin(0) centralLayout.setSpacing(0) self.view = vtk.vtkContextView() self.widget = QVTKRenderWindowInteractor( self, rw=self.view.GetRenderWindow(), iren=self.view.GetInteractor()) self.chart = vtk.vtkChartParallelCoordinates() self.view.GetScene().AddItem(self.chart) self.layout().addWidget(self.widget) # Create a annotation link to access selection in parallel coordinates view self.annotationLink = vtk.vtkAnnotationLink() # If you don't set the FieldType explicitly it ends up as UNKNOWN (as of 21 Feb 2010) # See vtkSelectionNode doc for field and content type enum values self.annotationLink.GetCurrentSelection().GetNode(0).SetFieldType( 1) # Point self.annotationLink.GetCurrentSelection().GetNode(0).SetContentType( 4) # Indices # Connect the annotation link to the parallel coordinates representation self.chart.SetAnnotationLink(self.annotationLink) self.annotationLink.AddObserver("AnnotationChangedEvent", self.selectionCallback)
def __init__(self, data_source, input_link): """Parallel coordinates view constructor needs a valid DataSource plus and external annotation link (from the icicle view). """ self.ds = data_source self.input_link = input_link # Set up callback to listen for changes in IcicleView selections self.input_link.AddObserver("AnnotationChangedEvent", self.InputSelectionCallback) # Set up an annotation link for other views to monitor selected image self.output_link = vtk.vtkAnnotationLink() # If you don't set the FieldType explicitly it ends up as UNKNOWN (as of 21 Feb 2010) # See vtkSelectionNode doc for field and content type enum values self.output_link.GetCurrentSelection().GetNode(0).SetFieldType(1) # Point # The chart seems to force INDEX selection, so I'm using vtkConvertSelection below to get # out PedigreeIds... self.output_link.GetCurrentSelection().GetNode(0).SetContentType(2) # 2 = PedigreeIds, 4 = Indices # Going to manually create output_link selection list, so not setting up callback for it... # self.renderer = vtk.vtkRenderer() # Setting as if nothing picked even though initialized position & orientation to actor0 self.highlightIndex = -1
def __init__(self): self.link = vtk.vtkAnnotationLink() self.link.GetCurrentSelection().GetNode(0).SetFieldType(3) # Vertex self.link.GetCurrentSelection().GetNode(0).SetContentType(2) # Pedigree Ids # Set up callback to update 3d render window when selections are changed in # parallel coordinates view self.link.AddObserver("AnnotationChangedEvent", self.SelectionCallback)
def generateParallelCoordinatesChart(self): input = self.inputModule().getOutput() ptData = input.GetPointData() narrays = ptData.GetNumberOfArrays() arrays = [] # Create a table with some points in it... table = vtk.vtkTable() for iArray in range(narrays): table.AddColumn(ptData.GetArray(iArray)) # Set up a 2D scene, add an XY chart to it view = vtk.vtkContextView() # view.SetRenderer( self.renderer ) # view.SetRenderWindow( self.renderer.GetRenderWindow() ) view.GetRenderer().SetBackground(1.0, 1.0, 1.0) view.GetRenderWindow().SetSize(600, 300) chart = vtk.vtkChartParallelCoordinates() brush = vtk.vtkBrush() brush.SetColorF(0.1, 0.1, 0.1) chart.SetBackgroundBrush(brush) # Create a annotation link to access selection in parallel coordinates view annotationLink = vtk.vtkAnnotationLink() # If you don't set the FieldType explicitly it ends up as UNKNOWN (as of 21 Feb 2010) # See vtkSelectionNode doc for field and content type enum values annotationLink.GetCurrentSelection().GetNode(0).SetFieldType( 1) # Point annotationLink.GetCurrentSelection().GetNode(0).SetContentType( 4) # Indices # Connect the annotation link to the parallel coordinates representation chart.SetAnnotationLink(annotationLink) view.GetScene().AddItem(chart) chart.GetPlot(0).SetInput(table) def selectionCallback(caller, event): annSel = annotationLink.GetCurrentSelection() if annSel.GetNumberOfNodes() > 0: idxArr = annSel.GetNode(0).GetSelectionList() if idxArr.GetNumberOfTuples() > 0: print VN.vtk_to_numpy(idxArr) # Set up callback to update 3d render window when selections are changed in # parallel coordinates view annotationLink.AddObserver("AnnotationChangedEvent", selectionCallback) # view.ResetCamera() # view.Render() # view.GetInteractor().Start() return view
def generateParallelCoordinatesChart( self ): input = self.inputModule().getOutput() ptData = input.GetPointData() narrays = ptData.GetNumberOfArrays() arrays = [] # Create a table with some points in it... table = vtk.vtkTable() for iArray in range( narrays ): table.AddColumn( ptData.GetArray( iArray ) ) # Set up a 2D scene, add an XY chart to it view = vtk.vtkContextView() # view.SetRenderer( self.renderer ) # view.SetRenderWindow( self.renderer.GetRenderWindow() ) view.GetRenderer().SetBackground(1.0, 1.0, 1.0) view.GetRenderWindow().SetSize(600,300) chart = vtk.vtkChartParallelCoordinates() brush = vtk.vtkBrush() brush.SetColorF (0.1,0.1,0.1) chart.SetBackgroundBrush(brush) # Create a annotation link to access selection in parallel coordinates view annotationLink = vtk.vtkAnnotationLink() # If you don't set the FieldType explicitly it ends up as UNKNOWN (as of 21 Feb 2010) # See vtkSelectionNode doc for field and content type enum values annotationLink.GetCurrentSelection().GetNode(0).SetFieldType(1) # Point annotationLink.GetCurrentSelection().GetNode(0).SetContentType(4) # Indices # Connect the annotation link to the parallel coordinates representation chart.SetAnnotationLink(annotationLink) view.GetScene().AddItem(chart) chart.GetPlot(0).SetInput(table) def selectionCallback(caller, event): annSel = annotationLink.GetCurrentSelection() if annSel.GetNumberOfNodes() > 0: idxArr = annSel.GetNode(0).GetSelectionList() if idxArr.GetNumberOfTuples() > 0: print VN.vtk_to_numpy(idxArr) # Set up callback to update 3d render window when selections are changed in # parallel coordinates view annotationLink.AddObserver("AnnotationChangedEvent", selectionCallback) # view.ResetCamera() # view.Render() # view.GetInteractor().Start() return view
def SetHighlightAnnotationLink(self, link): self.highlight_link = link # Set up callback to listen for changes in IcicleView selections self.highlight_link.AddObserver("AnnotationChangedEvent", self.HighlightSelectionCallback) # Set up annotation link which will carry indices to parallel coordinates chart # for highlighting outside selections (e.g. back from image_flow) # This needs to carry indices, while image_flow link outputs pedigree ids # so conversion happens in HighlightSelectionCallback self.highlight_link_idxs = vtk.vtkAnnotationLink() self.highlight_link_idxs.GetCurrentSelection().GetNode(0).SetFieldType(1) # Point self.highlight_link_idxs.GetCurrentSelection().GetNode(0).SetContentType(4) # 2 = PedigreeIds, 4 = Indices self.chart.SetHighlightLink(self.highlight_link_idxs)
def update(self, input_data): # Create layout strategy layoutStrategy = vtk.vtkAssignCoordinatesLayoutStrategy() layoutStrategy.SetYCoordArrayName('Y') layoutStrategy.SetXCoordArrayName('X') self.AddRepresentationFromInput(input_data) self.SetVertexLabelArrayName("VertexID") self.SetVertexLabelVisibility(True) self.SetLayoutStrategy(layoutStrategy) annotation_link = vtk.vtkAnnotationLink() annotation_link.AddObserver("AnnotationChangedEvent", self.select_callback) self.GetRepresentation(0).SetAnnotationLink(annotation_link) self.GetRepresentation(0).SetScalingArrayName('VertexID') self.GetRepresentation(0).ScalingOn() self.ResetCamera() self.Render()
def __init__(self, data_source, input_link): """Parallel coordinates view constructor needs a valid DataSource plus and external annotation link (from the icicle view). """ self.ds = data_source self.input_link = input_link # Set up callback to listen for changes in IcicleView selections self.input_link.AddObserver("AnnotationChangedEvent", self.InputSelectionCallback) # Set up an annotation link for other views to monitor selected image self.output_link = vtk.vtkAnnotationLink() # If you don't set the FieldType explicitly it ends up as UNKNOWN (as of 21 Feb 2010) # See vtkSelectionNode doc for field and content type enum values self.output_link.GetCurrentSelection().GetNode(0).SetFieldType(1) # Point # The chart seems to force INDEX selection, so I'm using vtkConvertSelection below to get # out PedigreeIds... self.output_link.GetCurrentSelection().GetNode(0).SetContentType(2) # 2 = PedigreeIds, 4 = Indices # Going to manually create output_link selection list, so not setting up callback for it... if os.path.isfile(os.path.abspath('BlankImage.png')): blank_file = 'BlankImage.png' else: # For use in app bundles blank_file = os.path.join(sys.path[0],'BlankImage.png') self.blankImageReader = vtk.vtkPNGReader() self.blankImageReader.SetFileName(blank_file) self.blankImageReader.Update() tmp = self.blankImageReader.GetOutput().GetBounds() self.flowSpacing = float(tmp[1]-tmp[0])*1.1 # Create a greyscale lookup table self.lut = self.ds.GetGrayscaleLUT('gray') self.lut.SetRange(self.blankImageReader.GetOutput().GetPointData().GetArray('PNGImage').GetRange()) # image intensity range # Map the image through the lookup table self.color = vtk.vtkImageMapToColors() self.color.SetLookupTable(self.lut) self.color.SetInput(self.blankImageReader.GetOutput()) self.resliceList = [] self.actorList = [] self.numImages = 1 # Map between indices of images and their Pedigree ID self.pedigree_id_dict = {} blankImageActor = vtk.vtkImageActor() blankImageActor.SetInput(self.color.GetOutput()) blankImageActor.SetPickable(False) blankImageActor.SetOpacity(0.1) self.actorList.append(blankImageActor) self.expSpread = 0.5 self.maxAngle = 80.0 self.renderer = vtk.vtkRenderer() self.cam = self.renderer.GetActiveCamera() # renderer.SetBackground(0.15, 0.12, 0.1) # cc0,cc1,cc2 = [float(ccVal)/255.0 for ccVal in [68,57,53]] # self.renderer.SetBackground(cc0,cc1,cc2) # cc0,cc1,cc2 = [float(ccVal)/255.0 for ccVal in [60,60,60]] cc0,cc1,cc2 = [float(ccVal)/255.0 for ccVal in [160, 160, 160]] self.renderer.SetBackground(cc0,cc1,cc2) self.renderer.AddActor(self.actorList[0]) self.highlightRect = vtk.vtkOutlineSource() self.highlightRect.SetBounds(self.actorList[0].GetBounds()) self.highlightMapper = vtk.vtkPolyDataMapper() self.highlightMapper.SetInputConnection(self.highlightRect.GetOutputPort(0)) self.highlightActor = vtk.vtkActor() self.highlightActor.SetMapper(self.highlightMapper) self.highlightActor.GetProperty().SetColor(0,0.5,1.0) self.highlightActor.GetProperty().SetLineWidth(6.0) self.highlightActor.GetProperty().SetOpacity(0.5) self.highlightActor.SetOrientation(self.actorList[0].GetOrientation()) tmpPos = self.actorList[0].GetPosition() usePos = (tmpPos[0],tmpPos[1],tmpPos[2]+0.01) self.highlightActor.SetPosition(usePos) # Setting as if nothing picked even though initialized position & orientation to actor0 self.highlightIndex = -1 self.highlightActor.SetPickable(False) self.highlightActor.SetVisibility(False) self.renderer.AddActor(self.highlightActor) # Create the slider which will control the image positions self.sliderRep = vtk.vtkSliderRepresentation2D() self.sliderRep.SetMinimumValue(0) self.sliderRep.SetMaximumValue(self.numImages-1) self.sliderRep.SetValue(0) self.window = vtk.vtkRenderWindow() self.window.SetSize(600,300) self.window.AddRenderer(self.renderer) # Set up the interaction self.interactorStyle = vtk.vtkInteractorStyleImage() self.interactor = vtk.vtkRenderWindowInteractor() self.interactor.SetInteractorStyle(self.interactorStyle) self.window.SetInteractor(self.interactor) self.sliderWidget = vtk.vtkSliderWidget() self.sliderWidget.SetInteractor(self.interactor) self.sliderWidget.SetRepresentation(self.sliderRep) self.sliderWidget.SetAnimationModeToAnimate() self.sliderWidget.EnabledOn() self.sliderWidget.AddObserver("InteractionEvent", self.sliderCallback) self.sliderWidget.AddObserver("EndInteractionEvent", self.endSliderCallback) # Default flow direction Horizontal self.FlowDirection = Direction.Horizontal self.SetFlowDirection(self.FlowDirection) # Set up callback to toggle between inspect modes (manip axes & select data) # self.interactorStyle.AddObserver("SelectionChangedEvent", self.selectImage) # Create callbacks for mouse events self.mouseActions = {} self.mouseActions["LeftButtonDown"] = 0 self.mouseActions["Picking"] = 0 self.interactorStyle.AddObserver("MouseMoveEvent", self.MouseMoveCallback) self.interactorStyle.AddObserver("LeftButtonPressEvent", self.LeftButtonPressCallback) self.interactorStyle.AddObserver("LeftButtonReleaseEvent", self.LeftButtonReleaseCallback) self.cam.ParallelProjectionOn() self.renderer.ResetCamera(self.actorList[0].GetBounds()) self.cam.Elevation(10) self.renderer.ResetCameraClippingRange()
# self.view.GetRepresentation(0).SetAnnotationLink(self.link) # self.link.AddObserver("AnnotationChangedEvent", self.IcicleSelectionCallback) if __name__ == "__main__": # from tkFileDialog import askopenfilename from data_source import DataSource # data_file = askopenfilename() data_file = '/Users/emonson/Data/Fodava/EMoGWDataSets/mnist1_5c_20100324.mat' # DataSource loads .mat file and can generate data from it for other views ds = DataSource(data_file) # Set up an annotation link as if selections were coming from another class dummy_link = vtk.vtkAnnotationLink() dummy_link.GetCurrentSelection().GetNode(0).SetFieldType(1) # Point dummy_link.GetCurrentSelection().GetNode(0).SetContentType(2) # 2 = PedigreeIds, 4 = Indices if_class = ImageFlow(ds, dummy_link) if_class.GetRenderWindow().SetSize(600,300) if_class.SetFlowDirection(Direction.Horizontal) # if_class.GetRenderWindow().SetSize(300,600) # if_class.SetFlowDirection(Direction.Vertical) # Fill selection link with dummy IDs id_array = N.array(range(50),dtype='int64') id_list = VN.numpy_to_vtkIdTypeArray(id_array) dummy_link.GetCurrentSelection().GetNode(0).SetSelectionList(id_list) dummy_link.InvokeEvent("AnnotationChangedEvent")
def main(): user_file = "./data/M2/Flitter_Names.txt" friend_file = "./data/M2/Links_Table.txt" community_file = "./data/M2/People_Cities.txt" ## Read user_file and friend_file with numpy names = pd.read_csv(user_file, delimiter='\t') friends = pd.read_csv(friend_file, delimiter='\t') communities = pd.read_csv(community_file, delimiter='\t') ## Add the size of each users network to the pandas dataframe ## and the city of each user to the pandas dataframe size = [] for i in range(0, len(names)): size.append(friends[friends.ID2 == i].ID2.size + friends[friends.ID1 == i].ID1.size) names.loc[:, 'followers'] = size names.loc[:, 'city'] = communities.City.tolist() ## First round of checks, do the sizes of their networks make sense? employees = names[(names['followers'] >= 37) & (names['followers'] <= 43)] handlers = names[(names['followers'] >= 28) & (names['followers'] <= 42)] middlemen = names[(names['followers'] >= 4) & (names['followers'] <= 5)] leaders = names[(names['followers'] >= 125)] middlemen = check(middlemen, leaders, friends, 1, "ge") potentials = leaders potentials = update_suspects(potentials, handlers, employees, middlemen, leaders) allgraph = vtk.vtkMutableDirectedGraph() allgraph = makegraph(potentials, friends, "city") ## Second round of check, do they havethe appropriate links? handlers = check(handlers, handlers, friends, 2, "le") employees = check(employees, handlers, friends, 3, "eq") middlemen = check(middlemen, handlers, friends, 2, "ge") ## Finally we remove all extras based on our employees handlers = check(handlers, employees, friends, 1, "eq") middlemen = check(middlemen, handlers, friends, 1, "ge") leaders = check(leaders, middlemen, friends, 1, "ge") potentials = update_suspects(potentials, handlers, employees, middlemen, leaders) potentialgraph = vtk.vtkMutableDirectedGraph() potentialgraph = makesolution(potentials, friends, "criminal") ### VTK pipeline stuff strategy = vtk.vtkAttributeClustering2DLayoutStrategy() strategy.SetVertexAttribute("city") strategy.SetGraph(allgraph) graphLayoutView = vtk.vtkGraphLayoutView() graphLayoutView.AddRepresentationFromInput(allgraph) graphLayoutView.GetRenderWindow().SetSize(1024, 1024) graphLayoutView.SetLayoutStrategy(strategy) graphLayoutView.SetVertexLabelArrayName("city") graphLayoutView.SetVertexLabelVisibility(1) graphLayoutView.ResetCamera() ## Render Just potential employees, handlers, middlemen, and leaders strategy2 = vtk.vtkAttributeClustering2DLayoutStrategy() strategy2.SetVertexAttribute("criminal") strategy2.SetGraph(potentialgraph) graphLayoutView2 = vtk.vtkGraphLayoutView() graphLayoutView2.AddRepresentationFromInput(potentialgraph) graphLayoutView2.GetRenderWindow().SetSize(1024, 1024) graphLayoutView2.SetLayoutStrategy(strategy2) graphLayoutView2.SetVertexLabelArrayName("username") graphLayoutView2.SetVertexLabelVisibility(1) graphLayoutView2.ResetCamera() ### implementing kayleigh's fancy linking code annotationlink = vtk.vtkAnnotationLink() graphLayoutView.GetRepresentation(0).SetAnnotationLink(annotationlink) graphLayoutView2.GetRepresentation(0).SetAnnotationLink(annotationlink) updater = vtk.vtkViewUpdater() updater.AddAnnotationLink(annotationlink) updater.AddView(graphLayoutView) updater.AddView(graphLayoutView2) graphLayoutView.Render() graphLayoutView.GetInteractor().Start() graphLayoutView2.Render() graphLayoutView2.GetInteractor().Start()
def __init__(self, parent = None): QtGui.QMainWindow.__init__(self, parent) self.ui = Ui_MainWindow() self.renWinList = [] # data_file = askopenfilename() data_file = '/Users/emonson/Data/Fodava/EMoGWDataSets/mnist1_5c_20100324.mat' # self.openFilesDefaultPath = QtCore.QDir.homePath() # data_file = QtGui.QFileDialog.getOpenFileName(self, # "Load Saved Matlab File", # self.openFilesDefaultPath, # "All Files (*);;Matlab Files (*.mat)") # DataSource loads .mat file and can generate data from it for other views self.ds = DataSource(str(data_file)) # All view classes have access to an instance of that data source for internal queries # Note that the only view which will pull and display data right away is the icicle view # the other views need to be able to initialize without any data and only pull and show # upon the first AnnotationChanged event... # View #0 -- Icicle View # Set up a 2D scene, add an XY chart to it self.chartView = vtk.vtkContextView() self.chartView.GetRenderer().SetBackground(1.0, 1.0, 1.0) self.renWinList.append(self.chartView.GetRenderWindow()) self.chart = vtkvtg.vtkMyChartXY() self.chartView.GetScene().AddItem(self.chart) # View #1 -- AxisImageView self.axisView = vtk.vtkContextView() self.axisView.GetRenderer().SetBackground(1.0, 1.0, 1.0) self.renWinList.append(self.axisView.GetRenderWindow()) self.ai = vtkvtg.vtkAxisImageItem() self.axisView.GetScene().AddItem(self.ai) # Set up all the render windows in the GUI self.ui.setupUi(self, self.renWinList) # Now need to get all the interactors working properly # XY style0 = vtk.vtkInteractorStyleRubberBand2D() self.chartView.GetInteractor().SetInteractorStyle(style0) self.chartView.GetScene().SetInteractorStyle(style0) # Axis images style1 = vtk.vtkInteractorStyleRubberBand2D() self.axisView.GetInteractor().SetInteractorStyle(style1) self.axisView.GetScene().SetInteractorStyle(style1) # Set sizes for veritcal splitters self.ui.splitter.setSizes([200,400]) # Connect signals and slots QtCore.QObject.connect(self.ui.actionExit, QtCore.SIGNAL("triggered()"), self.fileExit) # CORE setting up chart and axis images test_id = 68 self.table = self.ds.GetNodeOneScaleCoeffTable(test_id) line1 = vtkvtg.vtkMyPlotPoints() # line1.DebugOn() self.chart.AddPlot(line1) # POINTS line1.SetInput(self.table, 0, 1) line1.SetMarkerStyle(2) line1.SetColor(0, 0, 0, 255) # Tooltip image stack will now be owned by the tooltip, so need to do that differently... id_list = self.ds.PIN[test_id] image_stack = self.ds.GetProjectedImages(id_list) self.chart.SetTooltipImageStack(image_stack) self.chart.SetTooltipShowImage(True) # self.chart.SetTooltipImageScalingFactor(2.0) self.chart.SetTooltipImageTargetSize(40) axis_images = self.ds.GetNodeBasisImages(test_id) center_image = self.ds.GetNodeCenterImage(test_id) self.ai.SetAxisImagesHorizontal() self.ai.SetChartXY(self.chart) self.ai.SetChartXYView(self.chartView) self.ai.SetAxisImageStack(axis_images) self.ai.SetCenterImage(center_image) # Set up annotation link which will carry indices to parallel coordinates chart # for highlighting outside selections (e.g. back from image_flow) # This needs to carry indices, while image_flow link outputs pedigree ids # so conversion happens in HighlightSelectionCallback # data_col_idxs = vtk.vtkAnnotationLink() # data_col_idxs.GetCurrentSelection().GetNode(0).SetFieldType(1) # Point # data_col_idxs.GetCurrentSelection().GetNode(0).SetContentType(4) # 2 = PedigreeIds, 4 = Indices # self.chart.SetDataColumnsLink(data_col_idxs) # self.ai.SetDataColumnsLink(data_col_idxs) # Create a annotation link to access selection in XY chart annotationLink = vtk.vtkAnnotationLink() annotationLink.GetCurrentSelection().GetNode(0).SetFieldType(1) # Point annotationLink.GetCurrentSelection().GetNode(0).SetContentType(4) # Indices # Connect the annotation link to the parallel coordinates representation self.chart.SetAnnotationLink(annotationLink) self.chart.GetAnnotationLink().AddObserver("AnnotationChangedEvent", self.IcicleSelectionCallback) # Set up annotation link which will carry indices to parallel coordinates chart # for highlighting outside selections (e.g. back from image_flow) # This needs to carry indices, while image_flow link outputs pedigree ids # so conversion happens in HighlightSelectionCallback highlight_link_idxs = vtk.vtkAnnotationLink() highlight_link_idxs.GetCurrentSelection().GetNode(0).SetFieldType(1) # Point highlight_link_idxs.GetCurrentSelection().GetNode(0).SetContentType(4) # 2 = PedigreeIds, 4 = Indices self.chart.SetHighlightLink(highlight_link_idxs) # Fill selection link with dummy IDs id_array = N.array([0],dtype='int64') id_list = VN.numpy_to_vtkIdTypeArray(id_array, deep=True) highlight_link_idxs.GetCurrentSelection().GetNode(0).SetSelectionList(id_list) highlight_link_idxs.InvokeEvent("AnnotationChangedEvent") # self.updater = vtk.vtkViewUpdater() # self.updater.AddAnnotationLink(data_col_idxs) # self.updater.AddView(self.axisView) # self.updater.AddView(self.chartView) # col_array = N.array([0,1],dtype='int64') # col_vtk = VN.numpy_to_vtkIdTypeArray(col_array, deep=True) # data_col_idxs.GetCurrentSelection().GetNode(0).SetSelectionList(col_vtk) # data_col_idxs.InvokeEvent("AnnotationChangedEvent") self.chart.RecalculateBounds() # Only need to Start() interactor for one view # self.pc_class.GetView().GetInteractor().Start() # Shouldn't have to do this render... for rw in self.renWinList: rw.Render()
def main(): # Generate an image data set with multiple attribute arrays to probe and view rt = vtk.vtkRTAnalyticSource() rt.SetWholeExtent(-3, 3, -3, 3, -3, 3) grad = vtk.vtkImageGradient() grad.SetDimensionality(3) grad.SetInputConnection(rt.GetOutputPort()) brown = vtk.vtkBrownianPoints() brown.SetMinimumSpeed(0.5) brown.SetMaximumSpeed(1.0) brown.SetInputConnection(grad.GetOutputPort()) elev = vtk.vtkElevationFilter() elev.SetLowPoint(-3, -3, -3) elev.SetHighPoint(3, 3, 3) elev.SetInputConnection(brown.GetOutputPort()) # Updating here because I will need to probe scalar ranges before # the render window updates the pipeline elev.Update() # Set up parallel coordinates representation to be used in View rep = vtk.vtkParallelCoordinatesRepresentation() rep.SetInputConnection(elev.GetOutputPort()) rep.SetInputArrayToProcess(0, 0, 0, 0, 'RTDataGradient') rep.SetInputArrayToProcess(1, 0, 0, 0, 'RTData') rep.SetInputArrayToProcess(2, 0, 0, 0, 'Elevation') rep.SetInputArrayToProcess(3, 0, 0, 0, 'BrownianVectors') rep.SetUseCurves(0) # set to 1 to use smooth curves rep.SetLineOpacity(0.5) # Set up the Parallel Coordinates View and hook in representation view = vtk.vtkParallelCoordinatesView() view.SetRepresentation(rep) view.SetInspectMode(view.VTK_INSPECT_SELECT_DATA) view.SetBrushOperatorToReplace() view.SetBrushModeToLasso() # Create a annotation link to access selection in parallel coordinates view annotationLink = vtk.vtkAnnotationLink() # If you don't set the FieldType explicitly it ends up as UNKNOWN # (as of 21 Feb 2010) # See vtkSelectionNode doc for field and content type enum values annotationLink.GetCurrentSelection().GetNode(0).SetFieldType(1) # Point annotationLink.GetCurrentSelection().GetNode(0).SetContentType( 4) # Indices # Update before passing annotationLink to vtkExtractSelection annotationLink.Update() # Connect the annotation link to the parallel coordinates representation rep.SetAnnotationLink(annotationLink) # Extract portion of data corresponding to parallel coordinates selection extract = vtk.vtkExtractSelection() extract.SetInputConnection(0, elev.GetOutputPort()) extract.SetInputConnection(1, annotationLink.GetOutputPort(2)) def update_render_windows(obj, event): """ Handle updating of RenderWindow since it's not a "View" and so not covered by vtkViewUpdater :param obj: :param event: :return: """ # ren.ResetCamera() renWin.Render() # Set up callback to update 3d render window when selections are changed in # parallel coordinates view annotationLink.AddObserver("AnnotationChangedEvent", update_render_windows) def toggle_inspectors(obj, event): if view.GetInspectMode() == 0: view.SetInspectMode(1) else: view.SetInspectMode(0) # Set up callback to toggle between inspect modes (manip axes & select data) view.GetInteractor().AddObserver("UserEvent", toggle_inspectors) # 3D outline of image data bounds outline = vtk.vtkOutlineFilter() outline.SetInputConnection(elev.GetOutputPort()) outlineMapper = vtk.vtkPolyDataMapper() outlineMapper.SetInputConnection(outline.GetOutputPort()) outlineActor = vtk.vtkActor() outlineActor.SetMapper(outlineMapper) # Build the lookup table for the 3d data scalar colors (brown to white) lut = vtk.vtkLookupTable() lut.SetTableRange(0, 256) lut.SetHueRange(0.1, 0.1) lut.SetSaturationRange(1.0, 0.1) lut.SetValueRange(0.4, 1.0) lut.Build() # Set up the 3d rendering parameters # of the image data which is selected in parallel coordinates coloring_by = 'Elevation' dataMapper = vtk.vtkDataSetMapper() dataMapper.SetInputConnection(extract.GetOutputPort()) dataMapper.SetScalarModeToUsePointFieldData() dataMapper.SetColorModeToMapScalars() data = elev.GetOutputDataObject(0).GetPointData() dataMapper.ScalarVisibilityOn() dataMapper.SetScalarRange(data.GetArray(coloring_by).GetRange()) dataMapper.SetLookupTable(lut) dataMapper.SelectColorArray(coloring_by) dataActor = vtk.vtkActor() dataActor.SetMapper(dataMapper) dataActor.GetProperty().SetRepresentationToPoints() dataActor.GetProperty().SetPointSize(10) # Set up the 3d render window and add both actors ren = vtk.vtkRenderer() ren.AddActor(outlineActor) ren.AddActor(dataActor) renWin = vtk.vtkRenderWindow() renWin.AddRenderer(ren) iren = vtk.vtkRenderWindowInteractor() iren.SetRenderWindow(renWin) ren.ResetCamera() renWin.Render() # Finalize parallel coordinates view and start interaction event loop view.GetRenderWindow().SetSize(600, 300) view.ResetCamera() view.Render() view.GetInteractor().Start()
def __init__(self, parent = None): # Number of slider divisions per integer value self.divs = 10 # self.rot_method = 'alt_axis' self.rot_method = '111' # self.rot_method = 'simple' self.axis_rescale = False QtGui.QMainWindow.__init__(self, parent) self.ui = Ui_MainWindow() # Set up a 2D scene, add an XY chart to it self.view = vtk.vtkContextView() self.view.GetRenderer().SetBackground(1.0, 1.0, 1.0) self.ui.setupUi(self, self.view.GetRenderWindow()) if self.rot_method == 'alt_axis': self.ui.comboBox.setCurrentIndex(0) elif self.rot_method == '111': self.ui.comboBox.setCurrentIndex(1) else: self.ui.comboBox.setCurrentIndex(2) style = vtk.vtkInteractorStyleRubberBand2D() self.view.GetInteractor().SetInteractorStyle(style) self.view.GetScene().SetInteractorStyle(style) # Need this additional command (plus above set style) for this class # self.view.SetInteractionModeTo2D() self.chart = vtk.vtkChartXY() self.chart.SetShowLegend(False) # Create a annotation link to access selection in parallel coordinates view annotationLink = vtk.vtkAnnotationLink() # If you don't set the FieldType explicitly it ends up as UNKNOWN (as of 21 Feb 2010) # See vtkSelectionNode doc for field and content type enum values annotationLink.GetCurrentSelection().GetNode(0).SetFieldType(1) # Point annotationLink.GetCurrentSelection().GetNode(0).SetContentType(4) # Indices # Connect the annotation link to the parallel coordinates representation self.chart.SetAnnotationLink(annotationLink) self.view.GetScene().AddItem(self.chart) # Set up callback to update 3d render window when selections are changed in # parallel coordinates view annotationLink.AddObserver("AnnotationChangedEvent", self.selectionCallback) QtCore.QObject.connect(self.ui.actionExit, QtCore.SIGNAL("triggered()"), self.fileExit) QtCore.QObject.connect(self.ui.actionOpen, QtCore.SIGNAL("triggered()"), self.LoadData) QtCore.QObject.connect(self.ui.horizontalSlider, QtCore.SIGNAL("valueChanged(int)"), self.columnUpdate) QtCore.QObject.connect(self.ui.comboBox, QtCore.SIGNAL("currentIndexChanged(int)"), self.rotMethodChanged) self.LoadData() self.view.ResetCamera() self.ui.vtkWidget.GetRenderWindow().Render() self.view.GetInteractor().Start()
# the other views need to be able to initialize without any data and only pull and show # upon the first AnnotationChanged event... ice_class = IcicleNoView(data_source_list[0]) ice_class.GetRenderWindow().SetPosition(50,500) ice_class.GetRenderWindow().SetSize(630,470) ice_al_out = ice_class.GetOutputAnnotationLink() print "Looping..." for index in [0, 1, 2, 0, 1, 2, 0, 1, 2]: ice_class.SetDataSource(data_source_list[index]) ice_class.LoadData() # Set up an xy or PC plot annotation link as if selections were coming from another class group_link = vtk.vtkAnnotationLink() group_link.GetCurrentSelection().GetNode(0).SetFieldType(1) # Point group_link.GetCurrentSelection().GetNode(0).SetContentType(2) # 2 = PedigreeIds, 4 = Indices ice_class.SetGroupAnnotationLink(group_link) # Fill selection link with individual data point IDs group_id_array = N.array([3,5,10,200,103,54],dtype='int64') group_id_list = VN.numpy_to_vtkIdTypeArray(group_id_array) group_link.GetCurrentSelection().GetNode(0).SetSelectionList(group_id_list) group_link.InvokeEvent("AnnotationChangedEvent") # Set up highlight annotation link as if selections were coming from another class highlight_link = vtk.vtkAnnotationLink() highlight_link.GetCurrentSelection().GetNode(0).SetFieldType(1) # Point
rep.SetInputArrayToProcess(0, 0, 0, 0, 'RTDataGradient') rep.SetInputArrayToProcess(1, 0, 0, 0, 'RTData') rep.SetInputArrayToProcess(2, 0, 0, 0, 'Elevation') rep.SetInputArrayToProcess(3, 0, 0, 0, 'BrownianVectors') rep.SetUseCurves(0) # set to 1 to use smooth curves rep.SetLineOpacity(0.5) # Set up the Parallel Coordinates View and hook in representation view = vtk.vtkParallelCoordinatesView() view.SetRepresentation(rep) view.SetInspectMode(1) # VTK_INSPECT_SELECT_DATA = 1 view.SetBrushOperatorToReplace() view.SetBrushModeToLasso() # Create a annotation link to access selection in parallel coordinates view annotationLink = vtk.vtkAnnotationLink() # If you don't set the FieldType explicitly it ends up as UNKNOWN # (as of 21 Feb 2010) # See vtkSelectionNode doc for field and content type enum values annotationLink.GetCurrentSelection().GetNode(0).SetFieldType(1) # Point annotationLink.GetCurrentSelection().GetNode(0).SetContentType(4) # Indices # Update before passing annotationLink to vtkExtractSelection annotationLink.Update() # Connect the annotation link to the parallel coordinates representation rep.SetAnnotationLink(annotationLink) # Extract portion of data corresponding to parallel coordinates selection extract = vtk.vtkExtractSelection() if vtk.VTK_MAJOR_VERSION <= 5: extract.SetInput(0, elev.GetOutput()) extract.SetInput(1, annotationLink.GetOutputDataObject(2))
def __init__(self, data_source, input_link): """Parallel coordinates view constructor needs a valid DataSource plus and external annotation link (from the icicle view). """ self.ds = data_source self.input_link = input_link # Set up callback to listen for changes in IcicleView selections self.input_link.AddObserver("AnnotationChangedEvent", self.InputSelectionCallback) # Set up an annotation link for other views to monitor selected image self.output_link = vtk.vtkAnnotationLink() # If you don't set the FieldType explicitly it ends up as UNKNOWN (as of 21 Feb 2010) # See vtkSelectionNode doc for field and content type enum values self.output_link.GetCurrentSelection().GetNode(0).SetFieldType(1) # Point # The chart seems to force INDEX selection, so I'm using vtkConvertSelection below to get # out PedigreeIds... self.output_link.GetCurrentSelection().GetNode(0).SetContentType(2) # 2 = PedigreeIds, 4 = Indices # Going to manually create output_link selection list, so not setting up callback for it... if os.path.isfile(os.path.abspath('BlankImage.png')): blank_file = 'BlankImage.png' else: # For use in app bundles blank_file = os.path.join(sys.path[0],'BlankImage.png') self.blankImageReader = vtk.vtkPNGReader() self.blankImageReader.SetFileName(blank_file) self.blankImageReader.Update() tmp = self.blankImageReader.GetOutput().GetBounds() self.flowSpacing = float(tmp[1]-tmp[0])*1.1 self.nupSpacing = float(tmp[3]-tmp[2])*1.1 # Create a blue-white-red lookup table self.lut = vtk.vtkLookupTable() lutNum = 256 self.lut.SetNumberOfTableValues(lutNum) ctf = vtk.vtkColorTransferFunction() ctf.SetColorSpaceToDiverging() c_blue = N.array([59,76,192],dtype='float')/255.0 # c_gray = [0.8, 0.8, 0.8] c_red = N.array([180,4,38],dtype='float')/255.0 ctf.AddRGBPoint(0.0, c_blue[0], c_blue[1], c_blue[2]) # blue # ctf.AddRGBPoint(0.5, c_gray[0], c_gray[1], c_gray[2]) # blue ctf.AddRGBPoint(1.0, c_red[0], c_red[1], c_red[2]) # red for ii,ss in enumerate([float(xx)/float(lutNum) for xx in range(lutNum)]): cc = ctf.GetColor(ss) self.lut.SetTableValue(ii,cc[0],cc[1],cc[2],1.0) self.lut.SetRange(-10,10) # Map the image through the lookup table self.color = vtk.vtkImageMapToColors() self.color.SetLookupTable(self.lut) self.color.SetInput(self.blankImageReader.GetOutput()) self.resliceList = [] self.actorList = [] self.numImages = 1 # Map between indices of images and their Pedigree ID self.pedigree_id_dict = {} blankImageActor = vtk.vtkImageActor() blankImageActor.SetInput(self.color.GetOutput()) blankImageActor.SetPickable(False) blankImageActor.SetOpacity(0.1) self.actorList.append(blankImageActor) self.expSpread = 0.5 self.maxAngle = 80.0 self.renderer = vtk.vtkRenderer() self.cam = self.renderer.GetActiveCamera() # renderer.SetBackground(0.15, 0.12, 0.1) cc = [68,57,53] cc0,cc1,cc2 = [float(ccVal)/255.0 for ccVal in cc] self.renderer.SetBackground(cc0,cc1,cc2) self.renderer.AddActor(self.actorList[0]) self.highlightRect = vtk.vtkOutlineSource() self.highlightRect.SetBounds(self.actorList[0].GetBounds()) self.highlightMapper = vtk.vtkPolyDataMapper() self.highlightMapper.SetInputConnection(self.highlightRect.GetOutputPort(0)) self.highlightActor = vtk.vtkActor() self.highlightActor.SetMapper(self.highlightMapper) self.highlightActor.GetProperty().SetColor(1,0.8,0.2) self.highlightActor.GetProperty().SetLineWidth(3.0) self.highlightActor.SetOrientation(self.actorList[0].GetOrientation()) tmpPos = self.actorList[0].GetPosition() usePos = (tmpPos[0],tmpPos[1],tmpPos[2]+0.01) self.highlightActor.SetPosition(usePos) # Setting as if nothing picked even though initialized position & orientation to actor0 self.highlightIndex = -1 self.highlightActor.SetPickable(False) self.highlightActor.SetVisibility(False) self.renderer.AddActor(self.highlightActor) # Create the slider which will control the image positions self.sliderRep = vtk.vtkSliderRepresentation2D() self.sliderRep.SetMinimumValue(0) self.sliderRep.SetMaximumValue(self.numImages) self.sliderRep.SetValue(0) self.window = vtk.vtkRenderWindow() self.window.SetSize(600,300) self.window.AddRenderer(self.renderer) # Set up the interaction self.interactorStyle = vtk.vtkInteractorStyleRubberBand3D() self.interactor = vtk.vtkRenderWindowInteractor() self.interactor.SetInteractorStyle(self.interactorStyle) self.window.SetInteractor(self.interactor) self.sliderWidget = vtk.vtkSliderWidget() self.sliderWidget.SetInteractor(self.interactor) self.sliderWidget.SetRepresentation(self.sliderRep) self.sliderWidget.SetAnimationModeToAnimate() self.sliderWidget.EnabledOn() self.sliderWidget.AddObserver("InteractionEvent", self.sliderCallback) self.sliderWidget.AddObserver("EndInteractionEvent", self.endSliderCallback) # Default flow direction Horizontal self.FlowDirection = Direction.Horizontal self.SetFlowDirection(self.FlowDirection) # Set up callback to toggle between inspect modes (manip axes & select data) self.interactorStyle.AddObserver("SelectionChangedEvent", self.selectImage) # Set up callback to toggle between inspect modes (manip axes & select data) self.interactor.AddObserver("UserEvent", self.PrintCameraPosition) self.cam.ParallelProjectionOn() self.renderer.ResetCamera(self.actorList[0].GetBounds()) self.cam.Elevation(10) self.renderer.ResetCameraClippingRange() self.window.Render()
# Create a graph layout view view = vtk.vtkGraphLayoutView() view.AddRepresentationFromInputConnection(source.GetOutputPort()) view.SetVertexLabelArrayName("vertex id") view.SetVertexLabelVisibility(True) view.SetVertexColorArrayName("vertex id") view.SetColorVertices(True) view.SetEdgeColorArrayName("edge weight") view.SetColorEdges(True) view.SetLayoutStrategy(strategy) # Make sure the views are using a pedigree id selection view.GetRepresentation(0).SetSelectionType(2) # Create a selection link and set both view to use it annotationLink = vtk.vtkAnnotationLink() view.GetRepresentation(0).SetAnnotationLink(annotationLink) def select_callback(caller, event): # In this particular data representation the current selection in the # annotation link should always contain two nodes: one for the edges and # one for the vertices. Which is which is not consistent, so you need to # check the FieldType of each SelectionNode sel = caller.GetCurrentSelection() for nn in range(sel.GetNumberOfNodes()): sel_ids = sel.GetNode(nn).GetSelectionList() field_type = sel.GetNode(nn).GetFieldType() if field_type == 3:
def __init__(self, data_source, input_link): """Parallel coordinates view constructor needs a valid DataSource plus and external annotation link (from the icicle view). """ self.ds = data_source self.input_link = input_link # Set up callback to listen for changes in IcicleView selections self.input_link.AddObserver("AnnotationChangedEvent", self.InputSelectionCallback) # Set up an annotation link for other views to monitor selected image # This link will be created here, but used back and forth between this detail view # and the icicle view. It carries the current "scale" selected in both. self.output_link = vtk.vtkAnnotationLink() # If you don't set the FieldType explicitly it ends up as UNKNOWN (as of 21 Feb 2010) # See vtkSelectionNode doc for field and content type enum values self.output_link.GetCurrentSelection().GetNode(0).SetFieldType(1) # Point # Here I'm outputting the "scale" of the selection, so I'm not sure it matters # whether output is index or other content type... self.output_link.GetCurrentSelection().GetNode(0).SetContentType(4) # 2 = PedigreeIds, 4 = Indices # Set up callback which will work either internally or triggered by change from icicle view. self.output_link.AddObserver("AnnotationChangedEvent", self.ScaleSelectionCallback) # Create a set of empty image stacks for use in empty selections # but use the dimensions of a "projected image" so scales match example_image = self.ds.GetProjectedImages([0]) example_image.UpdateInformation() (xMin, xMax, yMin, yMax, zMin, zMax) = example_image.GetWholeExtent() (xSpacing, ySpacing, zSpacing) = example_image.GetSpacing() (x0, y0, z0) = example_image.GetOrigin() blankR = xMax - xMin + 1 blankC = yMax - yMin + 1 numScales = len(self.ds.ScaleMaxDim) # Note: accessing member variable directly self.blank_image_list = [] self.blank_image_weights = [] self.numImagesList = [] nDim = 3 # 3-dim for now... for dd in range(numScales): images_linear = N.zeros( blankR*blankC*nDim, dtype='float') intensity = VN.numpy_to_vtk(images_linear, deep=True) intensity.SetName('PNGImage') imageData = vtk.vtkImageData() imageData.SetOrigin(x0, y0, z0) imageData.SetSpacing(xSpacing, ySpacing, zSpacing) imageData.SetExtent(xMin,xMax,yMin,yMax,0,nDim-1) imageData.GetPointData().AddArray(intensity) imageData.GetPointData().SetActiveScalars('PNGImage') self.blank_image_list.append(imageData) self.blank_image_weights.append(0.1*N.ones(nDim, dtype='float')) self.numImagesList.append(nDim) for dd in range(len(self.blank_image_list)): self.blank_image_list[dd].UpdateInformation() # Create a BrBg7 lookup table self.lut = self.ds.GetDivergingLUT('BrBg') self.colorList = [] self.resliceList = [] self.assemblyList = [] self.numScales = len(self.ds.ScaleMaxDim) # Note: accessing member variable self.expSpread = 0.5 self.renderer = vtk.vtkRenderer() self.cam = self.renderer.GetActiveCamera() # renderer.SetBackground(0.15, 0.12, 0.1) # cc0,cc1,cc2 = [float(ccVal)/255.0 for ccVal in [40,40,40]] cc0,cc1,cc2 = [float(ccVal)/255.0 for ccVal in [60, 60, 60]] self.renderer.SetBackground(cc0,cc1,cc2) self.highlightRect = vtk.vtkOutlineSource() self.highlightMapper = vtk.vtkPolyDataMapper() self.highlightMapper.SetInputConnection(self.highlightRect.GetOutputPort(0)) self.highlightActor = vtk.vtkActor() self.highlightActor.SetMapper(self.highlightMapper) self.highlightActor.GetProperty().SetColor(1,0.8,0.2) self.highlightActor.GetProperty().SetLineWidth(3.0) self.highlightActor.GetProperty().SetOpacity(0.6) # Setting as if nothing picked even though initialized position & orientation to actor0 self.highlightIndex = -1 self.highlightActor.SetPickable(False) self.highlightActor.SetVisibility(False) self.renderer.AddActor(self.highlightActor) # Create the slider which will control the image positions self.sliderRep = vtk.vtkSliderRepresentation2D() self.sliderRep.SetMinimumValue(0) self.sliderRep.SetMaximumValue(self.numScales-1) self.sliderRep.SetValue(0) # For remembering the previous slider setting when switching data sets self.prevSliderValue = int(self.numScales/2.0) # And need to keep track of whether to reset view self.needToResetCamera = True self.window = vtk.vtkRenderWindow() self.window.SetSize(600,300) self.window.AddRenderer(self.renderer) # Set up the interaction self.interactorStyle = vtk.vtkInteractorStyleImage() self.interactor = vtk.vtkRenderWindowInteractor() self.interactor.SetInteractorStyle(self.interactorStyle) self.window.SetInteractor(self.interactor) self.sliderWidget = vtk.vtkSliderWidget() self.sliderWidget.SetInteractor(self.interactor) self.sliderWidget.SetRepresentation(self.sliderRep) self.sliderWidget.SetAnimationModeToAnimate() self.sliderWidget.EnabledOn() self.sliderWidget.AddObserver("InteractionEvent", self.sliderCallback) self.sliderWidget.AddObserver("EndInteractionEvent", self.endSliderCallback) # Default flow direction Horizontal # Setting self.maxAngle in SetFlowDirection() self.FlowDirection = Direction.Vertical self.SetFlowDirection(self.FlowDirection) # Set up callback to toggle between inspect modes (manip axes & select data) # self.interactorStyle.AddObserver("SelectionChangedEvent", self.selectImage) # Create callbacks for mouse events self.mouseActions = {} self.mouseActions["LeftButtonDown"] = 0 self.mouseActions["Picking"] = 0 self.interactorStyle.AddObserver("MouseMoveEvent", self.MouseMoveCallback) self.interactorStyle.AddObserver("LeftButtonPressEvent", self.LeftButtonPressCallback) self.interactorStyle.AddObserver("LeftButtonReleaseEvent", self.LeftButtonReleaseCallback) # Done setting up all of the image stuff, so call selection callback # to set up view with blank images # self.input_link.InvokeEvent('AnnotationChangedEvent') self.InputSelectionCallback(self.input_link,None) self.cam.ParallelProjectionOn()
def __init__(self, data_source, input_link=None, highlight_link=None): """Parallel coordinates view constructor needs a valid DataSource plus and external annotation link (from the icicle view). """ self.ds = data_source self.input_link = None if input_link is not None: self.SetInputAnnotationLink(input_link) # Set up a 2D scene, add an XY chart to it # Relies on changes to VTK (drawimage branch) that allow DrawImage() scaling factor self.chartView = vtk.vtkContextView() self.chartView.GetRenderer().SetBackground(1.0, 1.0, 1.0) # vtkChart:: # PAN # ZOOM # SELECT # vtkContextMouseEvent: # enum # { NO_BUTTON = 0, LEFT_BUTTON = 1, MIDDLE_BUTTON = 2, RIGHT_BUTTON = 4 } self.chart = vtkvtg.vtkMyChartXY() # self.chart.SetMouseMoveSelectZoomButtons(2,1,4) self.chart.SetActionToButton(vtk.vtkChart.PAN, 2) self.chart.SetActionToButton(vtk.vtkChart.ZOOM, 4) self.chart.SetActionToButton(vtk.vtkChart.SELECT, 1) self.chartView.GetScene().AddItem(self.chart) self.axisView = vtk.vtkContextView() self.axisView.GetRenderer().SetBackground(1.0, 1.0, 1.0) self.ai = vtkvtg.vtkAxisImageItem() self.axisView.GetScene().AddItem(self.ai) # Create a BrBg7 lookup table self.lut = self.ds.GetDivergingLUT('BrBg') self.ai.SetAxisImagesLookupTable(self.lut) # Create a greyscale lookup table self.lutBW = self.ds.GetGrayscaleLUT('gray') self.ai.SetCenterImageLookupTable(self.lutBW) self.highlight_link = None if highlight_link is not None: self.SetHighlightAnnotationLink(highlight_link) # Set up callback to listen for changes in IcicleView selections self.highlight_link.AddObserver("AnnotationChangedEvent", self.HighlightSelectionCallback) # Set up annotation link which will carry indices to parallel coordinates chart # for highlighting outside selections (e.g. back from image_flow) # This needs to carry indices, while image_flow link outputs pedigree ids # so conversion happens in HighlightSelectionCallback self.highlight_link_idxs = vtk.vtkAnnotationLink() self.highlight_link_idxs.GetCurrentSelection().GetNode(0).SetFieldType(1) # Point self.highlight_link_idxs.GetCurrentSelection().GetNode(0).SetContentType(4) # 2 = PedigreeIds, 4 = Indices self.chart.SetHighlightLink(self.highlight_link_idxs) # Create a annotation link to access selection in parallel coordinates view self.link = vtk.vtkAnnotationLink() # If you don't set the FieldType explicitly it ends up as UNKNOWN (as of 21 Feb 2010) # See vtkSelectionNode doc for field and content type enum values self.link.GetCurrentSelection().GetNode(0).SetFieldType(1) # Point # The chart seems to force INDEX selection, so I'm using vtkConvertSelection below to get # out PedigreeIds... self.link.GetCurrentSelection().GetNode(0).SetContentType(4) # 2 = PedigreeIds, 4 = Indices # Connect the annotation link to the parallel coordinates representation self.chart.SetAnnotationLink(self.link) # Set up callback for ID -> Pedigree ID conversion & copy to output link # self.link.AddObserver("AnnotationChangedEvent", self.PCoordsSelectionCallback) # Set up output annotation link which will carry pedigree ids to image flow view # Type and field will be set during conversion to pedigree ids in PCoordsSelectionCallback # self.output_link = vtk.vtkAnnotationLink() # self.chartView.ResetCamera() # self.chartView.Render() # Want to keep track of whether the node coming in on the input_link # is new or not self.input_link_idx = 0 # TODO: Should check the menu to see which is checked so default is # set by GUI self.SetColorByArray("None")
def main(): source = vtk.vtkRandomGraphSource() source.DirectedOff() source.SetNumberOfVertices(100) source.SetEdgeProbability(0) # Basically generates a tree source.SetUseEdgeProbability(True) source.SetStartWithTree(True) source.IncludeEdgeWeightsOn() # Create force directed layout strategy = vtk.vtkSimple2DLayoutStrategy() strategy.SetInitialTemperature(5) # Create a graph layout view view = vtk.vtkGraphLayoutView() view.AddRepresentationFromInputConnection(source.GetOutputPort()) view.SetVertexLabelArrayName("vertex id") view.SetVertexLabelVisibility(True) view.SetVertexColorArrayName("vertex id") view.SetColorVertices(True) view.SetEdgeColorArrayName("edge weight") view.SetColorEdges(True) view.SetLayoutStrategy(strategy) # Make sure the views are using a pedigree id selection view.GetRepresentation(0).SetSelectionType(2) # Create a selection link and set both view to use it annotationLink = vtk.vtkAnnotationLink() view.GetRepresentation(0).SetAnnotationLink(annotationLink) def select_callback(caller, event): """ In this particular data representation the current selection in the annotation link should always contain two nodes: one for the edges and one for the vertices. Which is which is not consistent, so you need to check the FieldType of each SelectionNode :param caller: :param event: :return: """ sel = caller.GetCurrentSelection() for nn in range(sel.GetNumberOfNodes()): sel_ids = sel.GetNode(nn).GetSelectionList() field_type = sel.GetNode(nn).GetFieldType() if field_type == 3: print("Vertex selection Pedigree IDs") if field_type == 4: print("Edge selection Pedigree IDs") if sel_ids.GetNumberOfTuples() > 0: for ii in range(sel_ids.GetNumberOfTuples()): print(int(sel_ids.GetTuple1(ii))) else: print("-- empty") print("") # AnnotationChangedEvent will fire when the selection is changed annotationLink.AddObserver("AnnotationChangedEvent", select_callback) # Set the theme on the view theme = vtk.vtkViewTheme.CreateMellowTheme() theme.SetLineWidth(5) theme.SetPointSize(10) theme.SetCellOpacity(0.99) theme.SetOutlineColor(0.6, 0.6, 0.6) # Vertices theme.SetSelectedPointColor(0, 0.5, 1) theme.SetPointHueRange(1.0, 1.0) theme.SetPointSaturationRange(1.0, 1.0) theme.SetPointValueRange(0.0, 1.0) # theme.SetPointAlphaRange(0.2, 0.8) # Edges theme.SetSelectedCellColor(1.0, 0.95, 0.75) theme.SetCellHueRange(0.1, 0.1) theme.SetCellSaturationRange(0.2, 1.0) theme.SetCellValueRange(0.5, 1.0) # theme.SetPointAlphaRange(0.2, 0.8) view.ApplyViewTheme(theme) theme.FastDelete() view.GetRenderWindow().SetSize(600, 600) view.ResetCamera() view.Render() view.GetInteractor().Start()
# DataSource loads .mat file and can generate data from it for other views ds = DataSource(data_file) # Set up a 2D scene, add an XY chart to it view = vtk.vtkContextView() view.GetRenderWindow().SetSize(400, 300) # Testing my custom chart class which has image hover tooltips chart = vtkvtg.vtkMyChartXY() chart.SetActionToButton(vtk.vtkChart.PAN, 2) chart.SetActionToButton(vtk.vtkChart.ZOOM, 4) chart.SetActionToButton(vtk.vtkChart.SELECT, 1) view.GetScene().AddItem(chart) # Create a annotation link to access selection in parallel coordinates view annotationLink = vtk.vtkAnnotationLink() # If you don't set the FieldType explicitly it ends up as UNKNOWN (as of 21 Feb 2010) # See vtkSelectionNode doc for field and content type enum values annotationLink.GetCurrentSelection().GetNode(0).SetFieldType(1) # Point annotationLink.GetCurrentSelection().GetNode(0).SetContentType(4) # Indices # Connect the annotation link to the parallel coordinates representation chart.SetAnnotationLink(annotationLink) test_id = 3 table = ds.GetNodeOneScaleCoeffTable(test_id) chart.ClearPlots() line1 = vtkvtg.vtkMyPlotPoints() chart.AddPlot(line1) # POINTS line1.SetInput(table, 0, 1)
def __init__(self, parent = None): QtGui.QMainWindow.__init__(self, parent) self.ui = Ui_MainWindow() self.ui.setupUi(self) # Set up a 2D scene (later we'll add a pcoords chart to it) self.view = vtk.vtkContextView() # self.view.GetRenderer().SetBackground(1.0, 1.0, 1.0) # // QVTKWidget *widget = new QVTKWidget; # // vtkContextView *view = vtkContextView::New(); # // view->SetInteractor(widget->GetInteractor()); # // widget->SetRenderWindow(view->GetRenderWindow()); # Necessary for RenderView types self.view.SetInteractor(self.ui.vtkWidget.GetInteractor()) self.ui.vtkWidget.SetRenderWindow(self.view.GetRenderWindow()) data_file = '/Users/emonson/Data/Fodava/EMoGWDataSets/mnist12_1k_20101119.mat' # DataSource loads .mat file and can generate data from it for other views ds = DataSource(data_file) # Testing my custom chart class which has image hover tooltips chart = vtkvtg.vtkMyChartXY() chart.SetActionToButton(vtk.vtkChart.PAN, 2) chart.SetActionToButton(vtk.vtkChart.ZOOM, 4) chart.SetActionToButton(vtk.vtkChart.SELECT, 1) self.view.GetScene().AddItem(chart) # Create a annotation link to access selection in parallel coordinates view annotationLink = vtk.vtkAnnotationLink() # If you don't set the FieldType explicitly it ends up as UNKNOWN (as of 21 Feb 2010) # See vtkSelectionNode doc for field and content type enum values annotationLink.GetCurrentSelection().GetNode(0).SetFieldType(1) # Point annotationLink.GetCurrentSelection().GetNode(0).SetContentType(4) # Indices # Connect the annotation link to the parallel coordinates representation chart.SetAnnotationLink(annotationLink) test_id = 3 table = ds.GetNodeOneScaleCoeffTable(test_id) chart.ClearPlots() line1 = vtkvtg.vtkMyPlotPoints() chart.AddPlot(line1) # POINTS line1.SetInput(table, 0, 1) line1.SetMarkerStyle(2) line1.SetColor(0, 0, 0, 255) # Tooltip image stack will now be owned by the tooltip, so need to do that differently... id_list = ds.PointsInNet[test_id] image_stack = ds.GetProjectedImages(id_list) chart.SetTooltipImageStack(image_stack) chart.SetTooltipShowImage(True) # chart.SetTooltipImageScalingFactor(2.0) chart.SetTooltipImageTargetSize(40) # Set up annotation link which will carry indices to parallel coordinates chart # for highlighting outside selections (e.g. back from image_flow) # This needs to carry indices, while image_flow link outputs pedigree ids # so conversion happens in HighlightSelectionCallback highlight_link_idxs = vtk.vtkAnnotationLink() highlight_link_idxs.GetCurrentSelection().GetNode(0).SetFieldType(1) # Point highlight_link_idxs.GetCurrentSelection().GetNode(0).SetContentType(4) # 2 = PedigreeIds, 4 = Indices chart.SetHighlightLink(highlight_link_idxs) # Finally render the scene and compare the image to a reference image # view.GetRenderWindow().SetMultiSamples(0) annotationLink.AddObserver("AnnotationChangedEvent", self.selectionCallback) # view.ResetCamera() # view.Render() # Fill selection link with dummy IDs id_array = N.array([0],dtype='int64') id_list = VN.numpy_to_vtkIdTypeArray(id_array) highlight_link_idxs.GetCurrentSelection().GetNode(0).SetSelectionList(id_list) highlight_link_idxs.InvokeEvent("AnnotationChangedEvent") # Set up annotation link which will carry indices to parallel coordinates chart # for highlighting outside selections (e.g. back from image_flow) # This needs to carry indices, while image_flow link outputs pedigree ids # so conversion happens in HighlightSelectionCallback data_col_idxs = vtk.vtkAnnotationLink() data_col_idxs.GetCurrentSelection().GetNode(0).SetFieldType(1) # Point data_col_idxs.GetCurrentSelection().GetNode(0).SetContentType(4) # 2 = PedigreeIds, 4 = Indices chart.SetDataColumnsLink(data_col_idxs) # Fill selection link with dummy IDs col_array = N.array([1,2],dtype='int64') col_list = VN.numpy_to_vtkIdTypeArray(col_array) data_col_idxs.GetCurrentSelection().GetNode(0).SetSelectionList(col_list) data_col_idxs.InvokeEvent("AnnotationChangedEvent") # Start interaction event loop self.ui.vtkWidget.show()
# self.view.GetRepresentation(0).SetAnnotationLink(self.link) # self.link.AddObserver("AnnotationChangedEvent", self.IcicleSelectionCallback) if __name__ == "__main__": # from tkFileDialog import askopenfilename from data_source import DataSource # data_file = askopenfilename() data_file = '/Users/emonson/Data/Fodava/EMoGWDataSets/test_mnist12.mat' # DataSource loads .mat file and can generate data from it for other views ds = DataSource(data_file) # Set up an annotation link as if selections were coming from another class ice_output_link = vtk.vtkAnnotationLink() # ice_output_link.GetCurrentSelection().GetNode(0).SetFieldType(3) # Vertex # ice_output_link.GetCurrentSelection().GetNode(0).SetContentType(2) # Pedigree Ids # Above are the correct types, but we need a blank selection to begin ice_output_link.GetCurrentSelection().RemoveAllNodes() pc_class = PCoordsChart(ds) pc_class.SetInputAnnotationLink(ice_output_link) pc_class.GetView().GetRenderWindow().SetSize(600,300) pc_class.SetColorByArray('label_0_ids') # Set up an annotation link as if selections were coming from another class dummy_link2 = vtk.vtkAnnotationLink() dummy_link2.GetCurrentSelection().GetNode(0).SetFieldType(1) # Point dummy_link2.GetCurrentSelection().GetNode(0).SetContentType(4) # 2 = PedigreeIds, 4 = Indices pc_class.SetHighlightAnnotationLink(dummy_link2)
def __init__(self, data_source, group_link=None, highlight_link=None, scale_link=None): """Icicle view constructor needs a valid DataSource and will pull data from it immediately.""" self.ds = data_source self.SHRINK = 0.15 self.THICK = 1.0 self.group_link = None if group_link is not None: self.SetGroupAnnotationLink(group_link) self.highlight_link = None if highlight_link is not None: self.SetHighlightAnnotationLink(highlight_link) self.scale_link = None if scale_link is not None: self.SetScaleAnnotationLink(scale_link) # Create the RenderWindow, Renderer and both Actors self.renderer = vtk.vtkRenderer() self.renWin = vtk.vtkRenderWindow() self.renWin.AddRenderer(self.renderer) self.interactor = vtk.vtkRenderWindowInteractor() self.interactor.SetRenderWindow(self.renWin) self.istyle = vtk.vtkInteractorStyleImage() self.interactor.SetInteractorStyle(self.istyle) self.renderer.GetActiveCamera().ParallelProjectionOn() # TEST # self.renderer.GetActiveCamera().SetViewUp(1,0,0) # Create callbacks for mouse events self.mouseActions = {} self.mouseActions["LeftButtonDown"] = 0 self.mouseActions["Picking"] = 0 # self.istyle.AddObserver("MouseMoveEvent", self.MouseMoveCallback) self.istyle.AddObserver("LeftButtonPressEvent", self.LeftButtonPressCallback) self.istyle.AddObserver("LeftButtonReleaseEvent", self.LeftButtonReleaseCallback) # Apply a theme to the views self.theme = vtk.vtkViewTheme.CreateMellowTheme() self.theme.SetPointColor(0,0,0) # self.theme.SetPointOpacity(0.1) # lines around icicle blocks self.theme.SetPointOpacity(0) c = N.array([255,204,0])/255.0 # nice yellow self.theme.SetSelectedPointColor(c[0],c[1],c[2]) self.theme.SetBackgroundColor(0.1, 0.1, 0.06) self.theme.SetBackgroundColor2(0.25, 0.25, 0.2) # self.renderer.SetBackground(self.theme.GetBackgroundColor()) # self.renderer.SetBackground2(self.theme.GetBackgroundColor2()) # self.renderer.SetGradientBackground(True) # cc0,cc1,cc2 = [float(ccVal)/255.0 for ccVal in [40, 40, 40]] cc0,cc1,cc2 = [float(ccVal)/255.0 for ccVal in [60, 60, 60]] self.renderer.SetBackground(cc0,cc1,cc2) self.renderer.SetGradientBackground(False) # Grab annotation link to monitor selection changes # self.output_link = rep.GetAnnotationLink() self.output_link = vtk.vtkAnnotationLink() # If you don't set the FieldType explicitly it ends up as UNKNOWN (as of 21 Feb 2010) # See vtkSelectionNode doc for field and content type enum values # enum SelectionContent { # SELECTIONS, GLOBALIDS, PEDIGREEIDS, VALUES, # INDICES, FRUSTUM, LOCATIONS, THRESHOLDS, # BLOCKS # } # enum SelectionField { # CELL, POINT, FIELD, VERTEX, # EDGE, ROW # } # Note: This may be the defaults, anyway, for the IcicleView annotation link # self.output_link.GetCurrentSelection().GetNode(0).SetFieldType(3) # Vertex # self.output_link.GetCurrentSelection().GetNode(0).SetContentType(2) # Pedigree Ids # Above are the correct types, but we need a blank selection to begin self.output_link.GetCurrentSelection().RemoveAllNodes() # TEST: Set up callback to test icicle view selection IDs self.output_link.AddObserver("AnnotationChangedEvent", self.IcicleSelectionCallback) # Flag for whether scale selection is internal or external self.scale_internal_call = False # Connect the annotation link to the icicle representation # rep = self.view.GetRepresentation(0) # Create Navigation Menu self.menu = NavMenu() menu_actor_list = self.menu.GetActorList() for m_actor in menu_actor_list: self.renderer.AddActor(m_actor) # Create a list of functions to be called depending on which nav button is clicked # Note: this is a bit fragile since it needs to correspond in number and routine # to the same order as created in nav menu class... self.menu_functions = [] self.menu_functions.append(self.OnNavUp) self.menu_functions.append(self.OnNavL) self.menu_functions.append(self.OnNavR) self.menu_functions.append(self.OnNavLDown) self.menu_functions.append(self.OnNavRDown) # Define color by array variables self.color_by_array = False self.color_array_name = '' # Load Data self.LoadData()