Beispiel #1
0
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()