Example #1
0
	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 __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()
chartScene.AddItem(chart)
chartActor.SetScene(chartScene)

# both needed
chartRen.AddActor(chartActor)
chartScene.SetRenderer(chartRen)
chartScene.SetInteractorStyle(istyle)

# AXIS IMAGES
aiRen = vtk.vtkRenderer()
aiRen.SetBackground(1.0,1.0,1.0)
aiRen.SetViewport(viewports[0])
renwin.AddRenderer(aiRen)

# Testing my custom chart class which has image hover tooltips
ai = vtkvtg.vtkAxisImageItem()
aiScene = vtk.vtkContextScene()
aiActor = vtk.vtkContextActor()

aiScene.AddItem(ai)
aiActor.SetScene(aiScene)

# both needed
aiRen.AddActor(aiActor)
aiScene.SetRenderer(aiRen)
aiScene.SetInteractorStyle(istyle)


# 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)