def __init__(self):
        super(TransferFunctionWidget, self).__init__()

        self.nodes = []
        self.lines = []
        self.histogram = Histogram()
        self.histogram.enabled = False

        # Create a histogram widget for the background of the transfer function editor
        self.histogramWidget = HistogramWidget()
        self.histogramWidget.setHistogram(self.histogram)
        self.histogramWidget.setAxeMode(bottom=HistogramWidget.AxeClear,
                                        left=HistogramWidget.AxeLog)
        self.histogramWidget.update()
        self.histogramWidget._histogramItem.delegate = self
        Style.styleWidgetForTab(self.histogramWidget)

        # Invisible item that catches mouse events on top of the histogram
        self.transferfunctionItem = TransferFunctionItem()
        self.transferfunctionItem.setZValue(250)
        self.transferfunctionItem.delegate = self
        self.histogramWidget.addItem(self.transferfunctionItem)

        # Create a widget for editing the selected node of the transfer function
        self.nodeItemWidget = NodeItemWidget()
        self.nodeItemWidget.setEnabled(False)
        self.nodeItemWidget.nodeUpdated.connect(self.updateNode)
        self.nodeItemWidget.removePoint.connect(self.removePoint)

        layout = QGridLayout()
        layout.setSpacing(0)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.histogramWidget, 0, 0)
        layout.addWidget(self.nodeItemWidget, 1, 0)
        self.setLayout(layout)
	def __init__(self):
		super(TransferFunctionWidget, self).__init__()

		self.nodes = []
		self.lines = []
		self.histogram = Histogram()
		self.histogram.enabled = False

		# Create a histogram widget for the background of the transfer function editor
		self.histogramWidget = HistogramWidget()
		self.histogramWidget.setHistogram(self.histogram)
		self.histogramWidget.setAxeMode(bottom=HistogramWidget.AxeClear, left=HistogramWidget.AxeLog)
		self.histogramWidget.update()
		self.histogramWidget._histogramItem.delegate = self
		Style.styleWidgetForTab(self.histogramWidget)

		# Invisible item that catches mouse events on top of the histogram
		self.transferfunctionItem = TransferFunctionItem()
		self.transferfunctionItem.setZValue(250)
		self.transferfunctionItem.delegate = self
		self.histogramWidget.addItem(self.transferfunctionItem)

		# Create a widget for editing the selected node of the transfer function
		self.nodeItemWidget = NodeItemWidget()
		self.nodeItemWidget.setEnabled(False)
		self.nodeItemWidget.nodeUpdated.connect(self.updateNode)
		self.nodeItemWidget.removePoint.connect(self.removePoint)

		layout = QGridLayout()
		layout.setSpacing(0)
		layout.setContentsMargins(0, 0, 0, 0)
		layout.addWidget(self.histogramWidget, 0, 0)
		layout.addWidget(self.nodeItemWidget, 1, 0)
		self.setLayout(layout)
class TransferFunctionWidget(QWidget):
	"""
	TransferFunctionWidget
	"""

	valueChanged = Signal(object)

	def __init__(self):
		super(TransferFunctionWidget, self).__init__()

		self.nodes = []
		self.lines = []
		self.histogram = Histogram()
		self.histogram.enabled = False

		# Create a histogram widget for the background of the transfer function editor
		self.histogramWidget = HistogramWidget()
		self.histogramWidget.setHistogram(self.histogram)
		self.histogramWidget.setAxeMode(bottom=HistogramWidget.AxeClear, left=HistogramWidget.AxeLog)
		self.histogramWidget.update()
		self.histogramWidget._histogramItem.delegate = self
		Style.styleWidgetForTab(self.histogramWidget)

		# Invisible item that catches mouse events on top of the histogram
		self.transferfunctionItem = TransferFunctionItem()
		self.transferfunctionItem.setZValue(250)
		self.transferfunctionItem.delegate = self
		self.histogramWidget.addItem(self.transferfunctionItem)

		# Create a widget for editing the selected node of the transfer function
		self.nodeItemWidget = NodeItemWidget()
		self.nodeItemWidget.setEnabled(False)
		self.nodeItemWidget.nodeUpdated.connect(self.updateNode)
		self.nodeItemWidget.removePoint.connect(self.removePoint)

		layout = QGridLayout()
		layout.setSpacing(0)
		layout.setContentsMargins(0, 0, 0, 0)
		layout.addWidget(self.histogramWidget, 0, 0)
		layout.addWidget(self.nodeItemWidget, 1, 0)
		self.setLayout(layout)

	def setImageData(self, imageData):
		# Clear any previous nodes
		for node in self.nodes:
			self.histogramWidget.scene().removeItem(node)
		self.nodes = []

		# Clear any previous lines
		for line in self.lines:
			self.histogramWidget.scene().removeItem(line)
		self.lines = []

		bins = DataAnalyzer.histogramForData(imageData, 256)
		self.histogram.bins = bins
		self.histogram.enabled = True
		self.range = imageData.GetScalarRange()

		# Create and add nodes from the transfer function
		self.updateNodes()
		self.valueChanged.emit(self)

	def resizeEvent(self, event):
		self.histogramWidget.update()
		self.updateNodes()

	def updateNodes(self):
		for index in range(len(self.transferFunction.points)):
			point = self.transferFunction.points[index]

			if index < len(self.nodes):
				# Just update the node item
				nodeItem = self.nodes[index]
			else:
				# Create a new node item
				nodeItem = TransferFunctionNodeItem()
				nodeItem.setSceneBoundsItem(self.histogramWidget._histogramItem)
				nodeItem.setZValue(300)
				nodeItem.delegate = self
				self.histogramWidget.scene().addItem(nodeItem)
				self.nodes.append(nodeItem)
			nodeItem.setPosition([(point.value - self.range[0]) / (self.range[1] - self.range[0]), point.opacity])
			nodeItem.updateColor(point.color)
			nodeItem.node = point
			if nodeItem.isSelected():
				self.selectedNode(nodeItem)

		# Clean up redundant node items
		if len(self.nodes) > len(self.transferFunction.points):
			# Remove node items from scene
			for index in range(len(self.transferFunction.points), len(self.nodes)):
				nodeItem = self.nodes[index]
				self.histogramWidget.scene().removeItem(nodeItem)

			# Remove them from the nodes
			del self.nodes[len(self.transferFunction.points):]
			assert len(self.nodes) == len(self.transferFunction.points)

		self.updateLines()

	def updateLines(self):
		pen = QPen(QColor.fromHsl(0, 100, 100))
		sortedNodes = sorted(self.nodes, key=lambda x: x.pos().x())
		for index in range(len(self.nodes)-1):
			node = sortedNodes[index]
			nextNode = sortedNodes[index+1]
			if index < len(self.lines):
				# Just update the line segment
				lineItem = self.lines[index]
			else:
				# Create a new line segment
				lineItem = QGraphicsLineItem()
				lineItem.setZValue(250)
				lineItem.setPen(pen)
				self.histogramWidget.scene().addItem(lineItem)
				self.lines.append(lineItem)
			line = QLineF(node.pos(), nextNode.pos())
			lineItem.setLine(line)

		# Clean up redundent lines
		if len(self.lines) >= len(self.nodes):
			# Remove the redundant line segments from the scene
			for index in range(len(self.nodes)-1, len(self.lines)):
				lineItem = self.lines[index]
				self.histogramWidget.scene().removeItem(lineItem)

			# Delete the line segments from the list
			del self.lines[len(self.nodes)-1:]
			assert len(self.lines) == len(self.nodes) - 1

		self.histogramWidget._scene.update()

	def nodeUpdated(self, node):
		position = node.getPosition()
		index = self._indexForNode(node)
		self.transferFunction.updatePointAtIndex(index, position)
		self.nodeItemWidget.setNode(self.transferFunction.points[index])
		self.updateNodes()
		self.valueChanged.emit(self)

	@Slot(object)
	def updateNode(self, point):
		index = self._indexForPoint(point)
		nodeItem = self.nodes[index]
		nodeItem.updateColor(point.color)
		self.transferFunction.updateTransferFunction()
		self.valueChanged.emit(self)

	def selectedNode(self, nodeItem):
		self.nodeItemWidget.setNode(nodeItem.node)

	def addNodeAtCoord(self, coord):
		self.transferFunction.addPointAtCoord(coord, [1, 1, 1])
		self.updateNodes()
		self.valueChanged.emit(self)

	def removePoint(self, point):
		index = self._indexForPoint(point)
		self.transferFunction.removePointAtIndex(index)
		self.updateNodes()

	def unselect(self):
		for node in self.nodes:
			if node.isSelected():
				node.setSelected(False)
		self.nodeItemWidget.setNode(None)
		self.updateNodes()

	def _indexForPoint(self, point):
			for index in range(len(self.transferFunction.points)):
				if point == self.transferFunction.points[index]:
					return index

	def _indexForNode(self, node):
		for index in range(len(self.nodes)):
			if node == self.nodes[index]:
				return index
class TransferFunctionWidget(QWidget):
    """
	TransferFunctionWidget
	"""

    valueChanged = Signal(object)

    def __init__(self):
        super(TransferFunctionWidget, self).__init__()

        self.nodes = []
        self.lines = []
        self.histogram = Histogram()
        self.histogram.enabled = False

        # Create a histogram widget for the background of the transfer function editor
        self.histogramWidget = HistogramWidget()
        self.histogramWidget.setHistogram(self.histogram)
        self.histogramWidget.setAxeMode(bottom=HistogramWidget.AxeClear,
                                        left=HistogramWidget.AxeLog)
        self.histogramWidget.update()
        self.histogramWidget._histogramItem.delegate = self
        Style.styleWidgetForTab(self.histogramWidget)

        # Invisible item that catches mouse events on top of the histogram
        self.transferfunctionItem = TransferFunctionItem()
        self.transferfunctionItem.setZValue(250)
        self.transferfunctionItem.delegate = self
        self.histogramWidget.addItem(self.transferfunctionItem)

        # Create a widget for editing the selected node of the transfer function
        self.nodeItemWidget = NodeItemWidget()
        self.nodeItemWidget.setEnabled(False)
        self.nodeItemWidget.nodeUpdated.connect(self.updateNode)
        self.nodeItemWidget.removePoint.connect(self.removePoint)

        layout = QGridLayout()
        layout.setSpacing(0)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.histogramWidget, 0, 0)
        layout.addWidget(self.nodeItemWidget, 1, 0)
        self.setLayout(layout)

    def setImageData(self, imageData):
        # Clear any previous nodes
        for node in self.nodes:
            self.histogramWidget.scene().removeItem(node)
        self.nodes = []

        # Clear any previous lines
        for line in self.lines:
            self.histogramWidget.scene().removeItem(line)
        self.lines = []

        bins = DataAnalyzer.histogramForData(imageData, 256)
        self.histogram.bins = bins
        self.histogram.enabled = True
        self.range = imageData.GetScalarRange()

        # Create and add nodes from the transfer function
        self.updateNodes()
        self.valueChanged.emit(self)

    def resizeEvent(self, event):
        self.histogramWidget.update()
        self.updateNodes()

    def updateNodes(self):
        for index in range(len(self.transferFunction.points)):
            point = self.transferFunction.points[index]

            if index < len(self.nodes):
                # Just update the node item
                nodeItem = self.nodes[index]
            else:
                # Create a new node item
                nodeItem = TransferFunctionNodeItem()
                nodeItem.setSceneBoundsItem(
                    self.histogramWidget._histogramItem)
                nodeItem.setZValue(300)
                nodeItem.delegate = self
                self.histogramWidget.scene().addItem(nodeItem)
                self.nodes.append(nodeItem)
            nodeItem.setPosition([(point.value - self.range[0]) /
                                  (self.range[1] - self.range[0]),
                                  point.opacity])
            nodeItem.updateColor(point.color)
            nodeItem.node = point
            if nodeItem.isSelected():
                self.selectedNode(nodeItem)

        # Clean up redundant node items
        if len(self.nodes) > len(self.transferFunction.points):
            # Remove node items from scene
            for index in range(len(self.transferFunction.points),
                               len(self.nodes)):
                nodeItem = self.nodes[index]
                self.histogramWidget.scene().removeItem(nodeItem)

            # Remove them from the nodes
            del self.nodes[len(self.transferFunction.points):]
            assert len(self.nodes) == len(self.transferFunction.points)

        self.updateLines()

    def updateLines(self):
        pen = QPen(QColor.fromHsl(0, 100, 100))
        sortedNodes = sorted(self.nodes, key=lambda x: x.pos().x())
        for index in range(len(self.nodes) - 1):
            node = sortedNodes[index]
            nextNode = sortedNodes[index + 1]
            if index < len(self.lines):
                # Just update the line segment
                lineItem = self.lines[index]
            else:
                # Create a new line segment
                lineItem = QGraphicsLineItem()
                lineItem.setZValue(250)
                lineItem.setPen(pen)
                self.histogramWidget.scene().addItem(lineItem)
                self.lines.append(lineItem)
            line = QLineF(node.pos(), nextNode.pos())
            lineItem.setLine(line)

        # Clean up redundent lines
        if len(self.lines) >= len(self.nodes):
            # Remove the redundant line segments from the scene
            for index in range(len(self.nodes) - 1, len(self.lines)):
                lineItem = self.lines[index]
                self.histogramWidget.scene().removeItem(lineItem)

            # Delete the line segments from the list
            del self.lines[len(self.nodes) - 1:]
            assert len(self.lines) == len(self.nodes) - 1

        self.histogramWidget._scene.update()

    def nodeUpdated(self, node):
        position = node.getPosition()
        index = self._indexForNode(node)
        self.transferFunction.updatePointAtIndex(index, position)
        self.nodeItemWidget.setNode(self.transferFunction.points[index])
        self.updateNodes()
        self.valueChanged.emit(self)

    @Slot(object)
    def updateNode(self, point):
        index = self._indexForPoint(point)
        nodeItem = self.nodes[index]
        nodeItem.updateColor(point.color)
        self.transferFunction.updateTransferFunction()
        self.valueChanged.emit(self)

    def selectedNode(self, nodeItem):
        self.nodeItemWidget.setNode(nodeItem.node)

    def addNodeAtCoord(self, coord):
        self.transferFunction.addPointAtCoord(coord, [1, 1, 1])
        self.updateNodes()
        self.valueChanged.emit(self)

    def removePoint(self, point):
        index = self._indexForPoint(point)
        self.transferFunction.removePointAtIndex(index)
        self.updateNodes()

    def unselect(self):
        for node in self.nodes:
            if node.isSelected():
                node.setSelected(False)
        self.nodeItemWidget.setNode(None)
        self.updateNodes()

    def _indexForPoint(self, point):
        for index in range(len(self.transferFunction.points)):
            if point == self.transferFunction.points[index]:
                return index

    def _indexForNode(self, node):
        for index in range(len(self.nodes)):
            if node == self.nodes[index]:
                return index
	def setFile(self, fileName):
		"""
		Slot that reads properties of the dataset and displays them in a few widgets.
		"""
		if fileName is None:
			return

		self.fileName = fileName

		# Read info from dataset
		# TODO: read out the real world dimensions in inch or cm
		# TODO: scalar type (int, float, short, etc.)
		imageReader = DataReader()
		imageData = imageReader.GetImageData(fileName)

		directory, name = os.path.split(fileName)
		dimensions = imageData.GetDimensions()
		minimum, maximum = imageData.GetScalarRange()
		scalarType = imageData.GetScalarTypeAsString()

		bins = DataAnalyzer.histogramForData(imageData, 256)

		self.histogram = Histogram()
		self.histogram.bins = bins
		self.histogram.enabled = True

		self.histogramWidget = HistogramWidget()
		self.histogramWidget.setMinimumHeight(100)
		self.histogramWidget.setHistogram(self.histogram)
		self.histogramWidget.setAxeMode(bottom=HistogramWidget.AxeClear,
			left=HistogramWidget.AxeLog)
		Style.styleWidgetForTab(self.histogramWidget)

		nameText = name
		dimsText = "(" + str(dimensions[0]) + ", " + str(dimensions[1]) + ", " + str(dimensions[2]) + ")"
		voxsText = str(dimensions[0] * dimensions[1] * dimensions[2])
		rangText = "[" + str(minimum) + " : " + str(maximum) + "]"
		typeText = scalarType

		layout = self.layout()
		if not layout:
			# Create a new layout
			layout = QGridLayout()
			layout.setAlignment(Qt.AlignTop)

			# Create string representations
			nameLabels = []
			nameLabels.append(QLabel("File name:"))
			nameLabels.append(QLabel("Dimensions:"))
			nameLabels.append(QLabel("Voxels:"))
			nameLabels.append(QLabel("Range:"))
			nameLabels.append(QLabel("Data type:"))

			for label in nameLabels:
				label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)

			# Create 'dynamic' labels
			self.labelTitle = QLabel(nameText)
			self.labelDimensions = QLabel(dimsText)
			self.labelVoxels = QLabel(voxsText)
			self.labelRange = QLabel(rangText)
			self.labelType = QLabel(typeText)

			index = 0
			for label in nameLabels:
				layout.addWidget(label, index, 0)
				index += 1

			layout.addWidget(self.labelTitle, 0, 1)
			layout.addWidget(self.labelDimensions, 1, 1)
			layout.addWidget(self.labelVoxels, 2, 1)
			layout.addWidget(self.labelRange, 3, 1)
			layout.addWidget(self.labelType, 4, 1)
			layout.addWidget(self.histogramWidget, 5, 0, 1, 2)

			widget = QWidget()
			widget.setLayout(layout)
			Style.styleWidgetForTab(widget)
			self.scrollArea.setWidget(widget)

			scrollLayout = QGridLayout()
			scrollLayout.setSpacing(0)
			scrollLayout.setContentsMargins(0, 0, 0, 0)
			scrollLayout.addWidget(self.scrollArea)
			self.setLayout(scrollLayout)
		else:
			# Just update the text for the 'dynamic' labels
			self.labelTitle.setText(nameText)
			self.labelDimensions.setText(dimsText)
			self.labelVoxels.setText(voxsText)
			self.labelRange.setText(rangText)
			self.labelType.setText(typeText)
	def setFile(self, fileName):
		"""
		Slot that reads properties of the dataset and displays them in a few widgets.
		"""
		if fileName is None:
			return

		# Read info from dataset
		# TODO: read out the real world dimensions in inch or cm
		# TODO: scalar type (int, float, short, etc.)
		imageReader = DataReader()
		imageData = imageReader.GetImageData(fileName)

		directory, name = os.path.split(fileName)
		dimensions = imageData.GetDimensions()
		minimum, maximum = imageData.GetScalarRange()

		bins = DataAnalyzer.histogramForData(imageData, 256)

		self.histogram = Histogram()
		self.histogram.bins = bins
		self.histogram.enabled = True

		self.histogramWidget = HistogramWidget()
		self.histogramWidget.setHistogram(self.histogram)
		self.histogramWidget.setAxeMode(bottom=HistogramWidget.AxeClear,
			left=HistogramWidget.AxeLog)
		Style.styleWidgetForTab(self.histogramWidget)

		nameText = name
		dimsText = "(" + str(dimensions[0]) + ", " + str(dimensions[1]) + ", " + str(dimensions[2]) + ")"
		voxsText = str(dimensions[0] * dimensions[1] * dimensions[2])
		rangText = "[" + str(minimum) + " : " + str(maximum) + "]"

		layout = self.layout()
		if not layout:
			# Create a new layout
			layout = QGridLayout()
			layout.setAlignment(Qt.AlignTop)

			# Create string representations
			nameField = QLabel("File name:")
			dimsField = QLabel("Dimensions:")
			voxsField = QLabel("Voxels:")
			rangField = QLabel("Range:")

			nameField.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
			dimsField.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
			voxsField.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
			rangField.setAlignment(Qt.AlignRight | Qt.AlignVCenter)

			# Create 'dynamic' labels
			self.labelTitle = QLabel(nameText)
			self.labelDimensions = QLabel(dimsText)
			self.labelVoxels = QLabel(voxsText)
			self.labelRange = QLabel(rangText)

			layout.addWidget(nameField, 0, 0)
			layout.addWidget(dimsField, 1, 0)
			layout.addWidget(voxsField, 2, 0)
			layout.addWidget(rangField, 3, 0)

			layout.addWidget(self.labelTitle, 0, 1)
			layout.addWidget(self.labelDimensions, 1, 1)
			layout.addWidget(self.labelVoxels, 2, 1)
			layout.addWidget(self.labelRange, 3, 1)
			layout.addWidget(self.histogramWidget, 4, 0, 1, 2)
			self.setLayout(layout)
		else:
			# Just update the text for the 'dynamic' labels
			self.labelTitle.setText(nameText)
			self.labelDimensions.setText(dimsText)
			self.labelVoxels.setText(voxsText)
			self.labelRange.setText(rangText)