applycolors = tree_to_poly.GetInputConnection(0,0).GetProducer() arealayout = applycolors.GetInputConnection(0,0).GetProducer() treeaggregator = arealayout.GetInputConnection(0,0).GetProducer() # Parallel pipeline with no shrinkage to get TCoords # TODO: Add Tree input" -> TreeLevels -> VertexDegree -> TreeAggregation -> AreaLayout # so that don't have to dig into view to get treeaggregator output # TODO: Set variables so that view and this layout always match options!!! strategy = vtk.vtkStackedTreeLayoutStrategy() strategy.UseRectangularCoordinatesOn() strategy.SetRootStartAngle(0.0) strategy.SetRootEndAngle(15.0) strategy.SetRingThickness(ICEHEIGHT) # layer thickness strategy.ReverseOn() strategy.SetShrinkPercentage(0.0) layout = vtk.vtkAreaLayout() layout.SetLayoutStrategy(strategy) layout.SetInputConnection(treeaggregator.GetOutputPort(0)) layout.SetAreaArrayName("area") layout.SetSizeArrayName("num_in_vertex") areapoly = vtk.vtkTreeMapToPolyData() areapoly.SetInputConnection(layout.GetOutputPort(0)) areapoly.SetInputArrayToProcess( 0, 0, 0, 4, "area") # 4 = vtkDataObject::FIELD_ASSOCIATION_VERTICES texPlane = vtk.vtkTextureMapToPlane() texPlane.SetInputConnection(areapoly.GetOutputPort(0)) texPlane.AutomaticPlaneGenerationOn() texPlane.Update() # Try using a vtkProgrammableAttributeDataFilter to transfer over TCoords def transferTCoords(): input = paf.GetInputDataObject(0,0)
def LoadData(self): # Remove all old actors from renderer self.renderer.RemoveAllViewProps() # Put back nav menu menu_actor_list = self.menu.GetActorList() for m_actor in menu_actor_list: self.renderer.AddActor(m_actor) tree = self.ds.GetTree() # Parallel pipeline with no shrinkage to get TCoords self.TreeLevels = vtk.vtkTreeLevelsFilter() self.TreeLevels.SetInput(tree) VertexDegree = vtk.vtkVertexDegree() VertexDegree.SetInputConnection(self.TreeLevels.GetOutputPort(0)) TreeAggregation = vtk.vtkTreeFieldAggregator() TreeAggregation.LeafVertexUnitSizeOff() TreeAggregation.SetField('size') TreeAggregation.SetInputConnection(VertexDegree.GetOutputPort(0)) # Layout without shrinkage for generating texture coordinates strategy = vtk.vtkStackedTreeLayoutStrategy() strategy.UseRectangularCoordinatesOn() strategy.SetRootStartAngle(0.0) strategy.SetRootEndAngle(15.0) strategy.SetRingThickness(self.THICK) # layer thickness strategy.ReverseOn() strategy.SetShrinkPercentage(0.0) layout = vtk.vtkAreaLayout() layout.SetLayoutStrategy(strategy) layout.SetInputConnection(TreeAggregation.GetOutputPort(0)) layout.SetAreaArrayName("area") layout.SetSizeArrayName("num_in_vertex") areapoly = vtk.vtkTreeMapToPolyData() areapoly.SetInputConnection(layout.GetOutputPort(0)) areapoly.SetAddNormals(0) areapoly.SetInputArrayToProcess( 0, 0, 0, 4, "area") # 4 = vtkDataObject::FIELD_ASSOCIATION_VERTICES texPlane = vtk.vtkTextureMapToPlane() texPlane.SetInputConnection(areapoly.GetOutputPort(0)) texPlane.AutomaticPlaneGenerationOn() texPlane.Update() # Layout with shrinkage for generating geometry strategy0 = vtk.vtkStackedTreeLayoutStrategy() strategy0.UseRectangularCoordinatesOn() strategy0.SetRootStartAngle(0.0) strategy0.SetRootEndAngle(15.0) strategy0.SetRingThickness(self.THICK) # layer thickness strategy0.ReverseOn() strategy0.SetShrinkPercentage(self.SHRINK) layout0 = vtk.vtkAreaLayout() layout0.SetLayoutStrategy(strategy0) layout0.SetInputConnection(TreeAggregation.GetOutputPort(0)) layout0.SetAreaArrayName("area") layout0.SetSizeArrayName("num_in_vertex") areapoly0 = vtk.vtkTreeMapToPolyData() areapoly0.SetAddNormals(0) areapoly0.SetInputConnection(layout0.GetOutputPort(0)) areapoly0.SetInputArrayToProcess( 0, 0, 0, 4, "area") # 4 = vtkDataObject::FIELD_ASSOCIATION_VERTICES areapoly0.Update() # Copy over texture coordinates def transferTCoords(): input = paf.GetInputDataObject(0,0) refin = paf.GetInputList().GetItem(0) output = paf.GetPolyDataOutput() TCorig = refin.GetPointData().GetTCoords() TC = vtk.vtkFloatArray() TC.SetNumberOfComponents(TCorig.GetNumberOfComponents()) TC.SetNumberOfTuples(TCorig.GetNumberOfTuples()) TC.SetName('Texture Coordinates') for ii in range(TCorig.GetNumberOfTuples()): ff = TCorig.GetTuple2(ii) TC.SetTuple2(ii,ff[0],ff[1]) output.GetPointData().AddArray(TC) output.GetPointData().SetActiveTCoords('Texture Coordinates') paf = vtk.vtkProgrammableAttributeDataFilter() paf.SetInput(areapoly0.GetOutput()) paf.AddInput(texPlane.GetOutput()) paf.SetExecuteMethod(transferTCoords) # Need to find proper ordering of wavelet coeffs based on icicle layout # tree.GetVertexData().GetArray('area') is 4-component (Xmin,Xmax,Ymin,Ymax) print 'Reordering wavelet coeffs' out_polys = areapoly.GetOutputDataObject(0) isleaf = VN.vtk_to_numpy(out_polys.GetCellData().GetArray('leaf')) poly_bounds = VN.vtk_to_numpy(out_polys.GetCellData().GetArray('area')) vertex_ids = VN.vtk_to_numpy(out_polys.GetCellData().GetArray('vertex_ids')) self.LeafIds = vertex_ids[isleaf>0] self.LeafXmins = poly_bounds[isleaf>0,0] self.XOrderedLeafIds = self.LeafIds[self.LeafXmins.argsort()] # Grab texture images and color map self.GrabTextureImagesAndLUT() # For each node and corresponding image data in self.WCimageDataList, need to create a texture, # then pull out the correct rectangle from areapoly0 (using vtkExtractSelectedPolyDataIds # and create a mapper and actor and apply the texture. self.texture_list = [] self.tex_mapper_list = [] self.tex_actor_list = [] for ii in range(len(self.WCimageDataList)): # Set up texture with lookup table for matrix polys tex = vtk.vtkTexture() tex.SetInput(self.WCimageDataList[ii]) tex.SetLookupTable(self.lut) self.texture_list.append(tex) # Grab correct poly out of areapoly0 sel = vtk.vtkSelection() node = vtk.vtkSelectionNode() node.SetContentType(4) # 4 = indices node.SetFieldType(0) # 0 = cell id_array = N.array([ii],dtype='int64') id_list = VN.numpy_to_vtkIdTypeArray(id_array) node.SetSelectionList(id_list) sel.AddNode(node) ext_id_poly = vtk.vtkExtractSelectedPolyDataIds() ext_id_poly.SetInput(1, sel) ext_id_poly.SetInputConnection(0, areapoly0.GetOutputPort(0)) # ext_id_poly.Update() # print ext_id_poly.GetOutput() poly_tm = vtk.vtkTextureMapToPlane() poly_tm.SetInputConnection(ext_id_poly.GetOutputPort(0)) poly_tm.AutomaticPlaneGenerationOn() poly_tm.Update() # Separate mapper and actor for textured polys map2 = vtk.vtkPolyDataMapper() map2.SetInputConnection(poly_tm.GetOutputPort(0)) map2.ScalarVisibilityOff() self.tex_mapper_list.append(map2) act2 = vtk.vtkActor() act2.SetMapper(self.tex_mapper_list[ii]) act2.SetTexture(self.texture_list[ii]) act2.GetProperty().SetColor(1,1,1) act2.SetPickable(0) act2.SetPosition(0,0,0.1) # ??? self.tex_actor_list.append(act2) # Add textured polys to the view self.renderer.AddActor(self.tex_actor_list[ii]) # Layout with shrinkage for generating outline geometry for showing selections self.applycolors1 = vtk.vtkApplyColors() self.applycolors1.SetInputConnection(0,layout0.GetOutputPort(0)) self.applycolors1.AddInputConnection(1,self.output_link.GetOutputPort(0)) self.applycolors1.SetDefaultPointColor(self.theme.GetPointColor()) self.applycolors1.SetDefaultPointOpacity(self.theme.GetPointOpacity()) self.applycolors1.SetSelectedPointColor(self.theme.GetSelectedPointColor()) self.applycolors1.SetSelectedPointOpacity(self.theme.GetSelectedPointOpacity()) self.areapoly1 = vtk.vtkTreeMapToPolyData() self.areapoly1.SetInputConnection(self.applycolors1.GetOutputPort(0)) self.areapoly1.SetAddNormals(0) self.areapoly1.SetInputArrayToProcess( 0, 0, 0, 4, "area") # 4 = vtkDataObject::FIELD_ASSOCIATION_VERTICES # Separate mapper and actor for icicle polys outlines (pickable) map = vtk.vtkPolyDataMapper() map.SetInputConnection(self.areapoly1.GetOutputPort(0)) map.SetScalarModeToUseCellFieldData() map.SelectColorArray("vtkApplyColors color") map.SetScalarVisibility(True) act = vtk.vtkActor() act.SetMapper(map) act.GetProperty().SetColor(1,1,1) act.SetPickable(True) act.SetPosition(0,0,0) act.GetProperty().SetRepresentationToWireframe() act.GetProperty().SetLineWidth(4.0) self.icicle_actor = act # Add actor for selection highlight outlines self.renderer.AddActor(act) # Now need to set up data for generating "selection lines" which come from # xy or pcoords chart. Basic method is to create a new scalar array out of x-coord # of the texture coordinates, then do a Delaunay2D on the shrunken polys and contour # that at values obtained by finding what normalized distance along data set are # selected pedigree ids. self.calc = vtk.vtkArrayCalculator() self.calc.SetInputConnection(paf.GetOutputPort()) self.calc.SetAttributeModeToUsePointData() self.calc.AddScalarVariable("tcoords_X", "Texture Coordinates", 0) self.calc.SetFunction("tcoords_X") self.calc.SetResultArrayName("tcx") # self.calc.Update() # print VN.vtk_to_numpy(self.calc.GetOutput().GetPointData().GetArray('tcx')) self.group_contour = vtk.vtkContourFilter() self.group_contour.SetInputConnection(self.calc.GetOutputPort(0)) self.group_contour.SetInputArrayToProcess(0,0,0,0,'tcx') self.highlight_contour = vtk.vtkContourFilter() self.highlight_contour.SetInputConnection(self.calc.GetOutputPort(0)) self.highlight_contour.SetInputArrayToProcess(0,0,0,0,'tcx') # Separate mapper and actor group selection (pcoords or xy) lines map3 = vtk.vtkPolyDataMapper() map3.SetInputConnection(self.group_contour.GetOutputPort(0)) map3.SetScalarVisibility(0) act3 = vtk.vtkActor() act3.SetMapper(map3) act3.SetPickable(False) act3.SetPosition(0,0,0.2) act3.GetProperty().SetRepresentationToWireframe() act3.GetProperty().SetLineWidth(2.0) act3.GetProperty().SetColor(1,0,0) act3.GetProperty().SetOpacity(0.6) self.group_actor = act3 # Add actor for selection highlight outlines self.renderer.AddActor(act3) # Separate mapper and actor for individual (image_flow) selection highlight map4 = vtk.vtkPolyDataMapper() map4.SetInputConnection(self.highlight_contour.GetOutputPort(0)) map4.SetScalarVisibility(0) act4 = vtk.vtkActor() act4.SetMapper(map4) act4.SetPickable(False) act4.SetPosition(0,0,0.25) act4.GetProperty().SetRepresentationToWireframe() act4.GetProperty().SetLineWidth(3.0) act4.GetProperty().SetColor(0,0.5,1) act4.GetProperty().SetOpacity(0.6) self.highlight_actor = act4 # Add actor for selection highlight outlines self.renderer.AddActor(act4) # Get Ordered fractional positions for pedigree ids (for setting contour values) self.ped_id_fracs = self.ds.GetIdsFractionalPosition(self.XOrderedLeafIds) # Clear out selections on data change self.output_link.GetCurrentSelection().RemoveAllNodes() self.output_link.InvokeEvent("AnnotationChangedEvent") self.renderer.ResetCamera(self.icicle_actor.GetBounds())
def __init__(self, data_source): """Icicle view constructor needs a valid DataSource and will pull data from it immediately.""" self.ds = data_source SHRINK = 0.1 THICK = 1.0 tree = self.ds.GetTree() # Build view self.view = vtk.vtkIcicleView() self.view.SetRepresentationFromInput(tree) self.view.SetAreaSizeArrayName("num_in_vertex") self.view.SetAreaColorArrayName("scale") self.view.SetAreaLabelArrayName("blank") self.view.SetLabelPriorityArrayName("VertexDegree") self.view.SetAreaLabelVisibility(True) self.view.SetAreaHoverArrayName("vertex_ids") self.view.SetDisplayHoverText(True) self.view.SetShrinkPercentage(SHRINK) self.view.SetLayerThickness(THICK) self.view.UseGradientColoringOff() self.style = vtk.vtkInteractorStyleImage() self.view.SetInteractorStyle(self.style) # Parallel pipeline with no shrinkage to get TCoords TreeLevels = vtk.vtkTreeLevelsFilter() TreeLevels.SetInput(tree) VertexDegree = vtk.vtkVertexDegree() VertexDegree.SetInputConnection(TreeLevels.GetOutputPort(0)) TreeAggregation = vtk.vtkTreeFieldAggregator() TreeAggregation.LeafVertexUnitSizeOff() TreeAggregation.SetField('size') TreeAggregation.SetInputConnection(VertexDegree.GetOutputPort(0)) # Layout with shrinkage for generating geometry strategy = vtk.vtkStackedTreeLayoutStrategy() strategy.UseRectangularCoordinatesOn() strategy.SetRootStartAngle(0.0) strategy.SetRootEndAngle(15.0) strategy.SetRingThickness(THICK) # layer thickness strategy.ReverseOn() strategy.SetShrinkPercentage(0.0) layout = vtk.vtkAreaLayout() layout.SetLayoutStrategy(strategy) layout.SetInputConnection(TreeAggregation.GetOutputPort(0)) layout.SetAreaArrayName("area") layout.SetSizeArrayName("num_in_vertex") areapoly = vtk.vtkTreeMapToPolyData() areapoly.SetInputConnection(layout.GetOutputPort(0)) areapoly.SetAddNormals(0) areapoly.SetInputArrayToProcess( 0, 0, 0, 4, "area") # 4 = vtkDataObject::FIELD_ASSOCIATION_VERTICES texPlane = vtk.vtkTextureMapToPlane() texPlane.SetInputConnection(areapoly.GetOutputPort(0)) texPlane.AutomaticPlaneGenerationOn() texPlane.Update() # Layout without shrinkage for generating texture coordinates strategy0 = vtk.vtkStackedTreeLayoutStrategy() strategy0.UseRectangularCoordinatesOn() strategy0.SetRootStartAngle(0.0) strategy0.SetRootEndAngle(15.0) strategy0.SetRingThickness(THICK) # layer thickness strategy0.ReverseOn() strategy0.SetShrinkPercentage(SHRINK) layout0 = vtk.vtkAreaLayout() layout0.SetLayoutStrategy(strategy0) layout0.SetInputConnection(TreeAggregation.GetOutputPort(0)) layout0.SetAreaArrayName("area") layout0.SetSizeArrayName("num_in_vertex") areapoly0 = vtk.vtkTreeMapToPolyData() areapoly0.SetAddNormals(0) areapoly0.SetInputConnection(layout0.GetOutputPort(0)) areapoly0.SetInputArrayToProcess( 0, 0, 0, 4, "area") # 4 = vtkDataObject::FIELD_ASSOCIATION_VERTICES areapoly0.Update() # Copy over texture coordinates def transferTCoords(): input = paf.GetInputDataObject(0,0) refin = paf.GetInputList().GetItem(0) output = paf.GetPolyDataOutput() TCorig = refin.GetPointData().GetTCoords() TC = vtk.vtkFloatArray() TC.SetNumberOfComponents(TCorig.GetNumberOfComponents()) TC.SetNumberOfTuples(TCorig.GetNumberOfTuples()) TC.SetName('Texture Coordinates') for ii in range(TCorig.GetNumberOfTuples()): ff = TCorig.GetTuple2(ii) TC.SetTuple2(ii,ff[0],ff[1]) output.GetPointData().AddArray(TC) output.GetPointData().SetActiveTCoords('Texture Coordinates') paf = vtk.vtkProgrammableAttributeDataFilter() paf.SetInput(areapoly0.GetOutput()) paf.AddInput(texPlane.GetOutput()) paf.SetExecuteMethod(transferTCoords) # Need to find proper ordering of wavelet coeffs based on icicle layout # tree.GetVertexData().GetArray('area') is 4-component (Xmin,Xmax,Ymin,Ymax) print 'Reordering wavelet coeffs' out_polys = areapoly.GetOutputDataObject(0) isleaf = VN.vtk_to_numpy(out_polys.GetCellData().GetArray('leaf')) poly_bounds = VN.vtk_to_numpy(out_polys.GetCellData().GetArray('area')) vertex_ids = VN.vtk_to_numpy(out_polys.GetCellData().GetArray('vertex_ids')) LeafIds = vertex_ids[isleaf>0] LeafXmins = poly_bounds[isleaf>0,0] XOrderedLeafIds = LeafIds[LeafXmins.argsort()] # And then grab the Wavelet Coefficients matrix sorted according to this WCimageData = self.ds.GetWaveletCoeffImage(XOrderedLeafIds) WCrange = N.array(WCimageData.GetPointData().GetScalars().GetRange()) WCext = abs(WCrange.min()) if (abs(WCrange.min()) > abs(WCrange.max())) else abs(WCrange.max()) # print WCext # Create blue to white to red lookup table lut = vtk.vtkLookupTable() lutNum = 256 lut.SetNumberOfTableValues(lutNum) lut.Build() ctf = vtk.vtkColorTransferFunction() ctf.SetColorSpaceToDiverging() ctf.AddRGBPoint(0.0, 0, 0, 1.0) ctf.AddRGBPoint(1.0, 1.0, 0, 0) for ii,ss in enumerate([float(xx)/float(lutNum) for xx in range(lutNum)]): cc = ctf.GetColor(ss) lut.SetTableValue(ii,cc[0],cc[1],cc[2],1.0) lut.SetRange(-WCext,WCext) # Set up texture with lookup table for matrix polys tex = vtk.vtkTexture() tex.SetInput(WCimageData) tex.SetLookupTable(lut) # Separate mapper and actor for textured polys map2 = vtk.vtkPolyDataMapper() map2.SetInputConnection(paf.GetOutputPort(0)) map2.ScalarVisibilityOff() act2 = vtk.vtkActor() act2.SetMapper(map2) act2.SetTexture(tex) act2.GetProperty().SetColor(1,1,1) act2.SetPickable(0) act2.SetPosition(0,0,0.1) # Add textured polys to the view ren = self.view.GetRenderer() ren.AddActor(act2) # NOTE: This is the one place I'm still hacking into the view -- to set the # normal icicle view to wireframe and set the color... # Ren has an actor2d which is a scalar bar (edge) acts = ren.GetActors() # Acts has two actors -- graph blocks (0) and labels (1) act0 = acts.GetItemAsObject(0) act0.GetProperty().SetRepresentationToWireframe() act0.GetProperty().SetLineWidth(3.0) # Apply a theme to the views theme = vtk.vtkViewTheme.CreateMellowTheme() theme.SetPointHueRange(0,0) theme.SetPointSaturationRange(0.2,0.5) theme.SetPointValueRange(0.0,0.0) theme.SetPointAlphaRange(0.0,0.0) c = N.array([255,204,0])/255.0 theme.SetSelectedPointColor(c[0],c[1],c[2]) theme.SetBackgroundColor(0.1, 0.1, 0.06) theme.SetBackgroundColor2(0.25, 0.25, 0.2) self.view.ApplyViewTheme(theme) theme.FastDelete() # Connect the annotation link to the icicle representation rep = self.view.GetRepresentation(0) # Grab annotation link to monitor selection changes self.link = rep.GetAnnotationLink() # 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.link.GetCurrentSelection().GetNode(0).SetFieldType(3) # Vertex self.link.GetCurrentSelection().GetNode(0).SetContentType(2) # Pedigree Ids # TEST: Set up callback to test icicle view selection IDs self.link.AddObserver("AnnotationChangedEvent", self.IcicleSelectionCallback) self.view.GetRenderer().GetActiveCamera().ParallelProjectionOn() self.view.ResetCamera() self.view.Render()