def __init__(self):
        QtGui.QWidget.__init__(self)
        self._im_view = PixmapStackView()
        self._label = ScalableLabel()

        self._layout = QtGui.QVBoxLayout(self)
        self._layout.addWidget(self._label)

        self._label.setMouseTracking(True)
        self._last_mouse_x = 0
        self._last_mouse_y = 0

        self.connect(self._label, QtCore.SIGNAL("mouse_press"), self.mouse_pressed)
        self.connect(self._label, QtCore.SIGNAL("mouse_move"), self.mouse_pressed)

        self.axis = 2
        self.inc = 1 # index increment
        self._palette_name = None
    def __init__ (self) :
        QMainWindow.__init__(self)

        # points
        self._points = []
        self._id_gen = IdSetGenerator()
#X         self.version = 2

        self._view = PixmapStackView()

        #QGraphicsScene
        self._scene = QGraphicsScene()

        #QGraphicsPixmapItem
        self._item = QGraphicsPixmapItem()
        self._item.setTransformationMode(Qt.SmoothTransformation)
        self._item.setFlag(self._item.ItemIsSelectable,False)
        self._scene.addItem(self._item)

        #QGraphicsView
        self._widget = ScalableGraphicsView(self._scene)
        self.setCentralWidget(self._widget)

        ################### mouse handling ###################
        self._widget.setMouseTracking(True)
        self._last_mouse_x = 0
        self._last_mouse_y = 0
        self._last_slice = 0

        QObject.connect(self._widget,
                    SIGNAL("mouse_press"),
                    self.mouse_pressed)

        QObject.connect(self._widget,
                    SIGNAL("mouse_move"),
                    self.mouse_moved)

        QObject.connect(self,
                    SIGNAL("mouse_moved"),
                    self.coordinates)

        ################### menubar ###################
        self.menu = self.menuBar()
        self.menu_file = self.menu.addMenu('File')

        # Import Points
        self._load_points = self.menu_file.addAction('Import Points')
        QObject.connect(self._load_points,
                        SIGNAL("triggered(bool)"),
                        self.load_points)

        # Save points
        self._save_points = self.menu_file.addAction('Save Points')
        QObject.connect(self._save_points,
                        SIGNAL("triggered(bool)"),
                        self.save_points)

        ################### toolbar ###################
        self._toolbar = self.addToolBar("tools")
        self._toolgroup = QActionGroup(self)

        # QWidgetAction : "Rotation Left"
        self._action_left = self._toolbar.addAction("left rotation")
        self._action_left.setIcon(QIcon(":/image/rotate_left.png") )
        QObject.connect(self._action_left,
                        SIGNAL("triggered(bool)"),
                        self.rotate_left)

        # QWidgetAction : "Rotation Right"
        self._action_right = self._toolbar.addAction("right rotation")
        self._action_right.setIcon(QIcon(":/image/rotate_right.png") )
        QObject.connect(self._action_right,
                        SIGNAL("triggered(bool)"),
                        self.rotate_right)

        # QWidgetAction : "Add point"
        self._action_add = self._toolbar.addAction("Add point")
        self._action_add.setCheckable(True)
        self._toolgroup.addAction(self._action_add)
        self._action_add.setIcon(QIcon(":/image/add.png") )

        # QWidgetAction : "Delete point"
        self._action_delete = self._toolbar.addAction("Delete point")
        self._action_delete.setCheckable(True)
        self._toolgroup.addAction(self._action_delete)
        self._action_delete.setIcon(QIcon(":/image/delete.png") )

        ################### palette ###################
        self._palette_select = QComboBox()
        self._toolbar.addWidget(self._palette_select)
        for palname in palette_names :
            self._palette_select.addItem(palname)

        QObject.connect(self._palette_select,
                    SIGNAL("currentIndexChanged(int)"),
                    self.palette_name_changed)

        ################### slider ###################
        self._bot_toolbar = QToolBar("slider")
        self._img_slider = QSlider(Qt.Horizontal)
        self._img_slider.setRange(0,self._view.nb_slices() - 1)

        QObject.connect(self._img_slider,
                        SIGNAL("valueChanged(int)"),
                        self.slice_changed)

        self._bot_toolbar.addWidget(self._img_slider)
        self.addToolBar(Qt.BottomToolBarArea,self._bot_toolbar)

        ################### statusbar ###################
        self._lab_coord = QLabel("coords:")
        self._lab_xcoord = QLabel("% 4d" % 0)
        self._lab_ycoord = QLabel("% 4d" % 0)
        self._lab_zcoord = QLabel("% 4d" % 0)
        self._lab_intens = QLabel("intens: None")

        self.statusbar = self.statusBar()
        self.statusbar.addPermanentWidget(self._lab_coord)
        self.statusbar.addPermanentWidget(self._lab_xcoord)
        self.statusbar.addPermanentWidget(self._lab_ycoord)
        self.statusbar.addPermanentWidget(self._lab_zcoord)
        self.statusbar.addPermanentWidget(self._lab_intens)
class ImageStackViewerWidget(QtGui.QWidget):

    """
    Widget based on openalea.image.gui.slide_viewer.PixmapStackView
    """
    valueChanged = QtCore.Signal(object)
    stackChanged = QtCore.Signal(object)

    def __init__(self):
        QtGui.QWidget.__init__(self)
        self._im_view = PixmapStackView()
        self._label = ScalableLabel()

        self._layout = QtGui.QVBoxLayout(self)
        self._layout.addWidget(self._label)

        self._label.setMouseTracking(True)
        self._last_mouse_x = 0
        self._last_mouse_y = 0

        self.connect(self._label, QtCore.SIGNAL("mouse_press"), self.mouse_pressed)
        self.connect(self._label, QtCore.SIGNAL("mouse_move"), self.mouse_pressed)

        self.axis = 2
        self.inc = 1 # index increment
        self._palette_name = None

    ##############################################
    #        Qt Control API
    ##############################################

    def setValue(self, img):
        if img is self.value():
            return
        self._im_view.set_image(img)
        try:
            self.resolution = img.resolution[:]
        except AttributeError:
            pass

        self._im_view._reconstruct_pixmaps()
        self.change_axis(0)
        self.slice_changed((0 + self._im_view.nb_slices() - 1) / 2)

        self.emit_stack_changed()

    def value(self):
        return self._im_view.image()

    ##############################################
    #        slots
    ##############################################

    def emit_stack_changed(self):
        img = self.value()
        if img is None:
            self.stackChanged.emit(None)
        else:
            args = dict(shape=img.shape, axis=self.axis,
                        slice=self._im_view.current_slice(),
                        resolution=self.resolution, inc=self.inc,
                        palette_name=self._palette_name)
            self.stackChanged.emit(args)

    def change_axis(self, ind):
        if self.axis == ind:
            return
        try:
            res = list(self.resolution)
            del res[self.axis]
            tr = self._im_view._transform
            print res
            if tr % 180:
                self._label._resolution = res[1], res[0]
            else:
                self._label.set_resolution(*res[:2])
        except AttributeError:
            pass
        self._im_view._reconstruct_pixmaps(self.axis)
        self.emit_stack_changed()
        self.update_pix()
        #self.fill_infos()

    def mouse_pressed(self, event):
        self._last_mouse_x = event.x()
        self._last_mouse_y = event.y()

    def change_palette(self, palette_name):
        if palette_name == self._palette_name:
            return

        self._palette_name = palette_name
        self.emit_stack_changed()

        img = self._im_view.image()
        if img is None:
            return

        palette = palette_factory(palette_name, img.max())
        self._im_view.set_palette(palette, self.axis)
        self.update_pix()

    def update_pix(self):
        pix = self._im_view.pixmap()
        if pix is not None:
            self._label.setPixmap(pix)

    def get_pixel_value_str(self, img, x, y, z):
        px = img[x, y, z]
        if isinstance(px, np.ndarray):
            return str(px)
        else:
            return "%3d" % px

    def slice_changed(self, ind):
        img = self.value()
        if img is None:
            return

        if ind >= img.shape[self.axis]:
            ind = img.shape[self.axis] - 1
        if ind < 0:
            ind = 0
        if self._im_view.current_slice() == ind:
            return
        self._im_view.set_current_slice(ind)
        self.emit_stack_changed()
        self.update_pix()

    def snapshot(self):
        """write the current image
        """
        pix = self._im_view.pixmap()
        if pix is not None:
            pix.save("slice%.4d.png" % self.panel.img_slider.value())

    def wheelEvent(self, event):
        self.inc = event.delta() / 8 / 15
        idx = self._im_view.current_slice()
        self.slice_changed(idx + self.inc)

    def rotate_left(self):
        res = self._label._resolution
        self._label._resolution = res[1], res[0]
        self._im_view.rotate(-1)
        self.update_pix()

    def rotate_right(self):
        res = self._label._resolution
        self._label._resolution = res[1], res[0]
        self._im_view.rotate(1)
        self.update_pix()
    def __init__ (self, parent=None) :
        QMainWindow.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.axis = 2

        #central label
        self._im_view = PixmapStackView()
        self._label = ScalableLabel()
        self.setCentralWidget(self._label)

        #mouse handling
        self._label.setMouseTracking(True)
        self._last_mouse_x = 0
        self._last_mouse_y = 0

        QObject.connect(self._label,
                        SIGNAL("mouse_press"),
                        self.mouse_pressed)

        QObject.connect(self._label,
                        SIGNAL("mouse_move"),
                        self.mouse_pressed)

        #toolbar
        QObject.connect(self.ui.action_close,
                        SIGNAL("triggered(bool)"),
                        self.close)

        QObject.connect(self.ui.action_snapshot,
                        SIGNAL("triggered(bool)"),
                        self.snapshot)

        QObject.connect(self.ui.action_rotate_left,
                        SIGNAL("triggered(bool)"),
                        self.rotate_left)

        QObject.connect(self.ui.action_rotate_right,
                        SIGNAL("triggered(bool)"),
                        self.rotate_right)

        #palette
        self._palette_select = QComboBox()
        self.ui.toolbar.addWidget(self._palette_select)
        for palname in palette_names :
            self._palette_select.addItem(palname)

        QObject.connect(self._palette_select,
                        SIGNAL("currentIndexChanged(int)"),
                        self.palette_name_changed)
        #axis
        self._axis = QComboBox(self)
        self.ui.toolbar.addWidget(self._axis)
        self._axis.addItem("Z-axis")
        self._axis.addItem("Y-axis")
        self._axis.addItem("X-axis")
        self.connect(self._axis, SIGNAL('currentIndexChanged(int)'), self.change_axis )

        #slider
        self._bot_toolbar = QToolBar("slider")

        self._img_slider = QSlider(Qt.Horizontal)
        self._img_slider.setEnabled(False)
        QObject.connect(self._img_slider,
                        SIGNAL("valueChanged(int)"),
                        self.slice_changed)

        self._bot_toolbar.addWidget(self._img_slider)
        self.addToolBar(Qt.BottomToolBarArea,self._bot_toolbar)

        #statusbar
        self._lab_coord = QLabel("coords:")
        self._lab_xcoord = QLabel("% 4d" % 0)
        self._lab_ycoord = QLabel("% 4d" % 0)
        self._lab_zcoord = QLabel("% 4d" % 0)
        self._lab_intens = QLabel("intens: None")

        self.ui.statusbar.addPermanentWidget(self._lab_coord)
        self.ui.statusbar.addPermanentWidget(self._lab_xcoord)
        self.ui.statusbar.addPermanentWidget(self._lab_ycoord)
        self.ui.statusbar.addPermanentWidget(self._lab_zcoord)
        self.ui.statusbar.addPermanentWidget(self._lab_intens)

        self.set_title("<"+str(self.viewer_count)+">")
        SlideViewer.viewer_count += 1
class PointSelection (QMainWindow) :

    def __init__ (self) :
        QMainWindow.__init__(self)

        # points
        self._points = []
        self._id_gen = IdSetGenerator()
#X         self.version = 2

        self._view = PixmapStackView()

        #QGraphicsScene
        self._scene = QGraphicsScene()

        #QGraphicsPixmapItem
        self._item = QGraphicsPixmapItem()
        self._item.setTransformationMode(Qt.SmoothTransformation)
        self._item.setFlag(self._item.ItemIsSelectable,False)
        self._scene.addItem(self._item)

        #QGraphicsView
        self._widget = ScalableGraphicsView(self._scene)
        self.setCentralWidget(self._widget)

        ################### mouse handling ###################
        self._widget.setMouseTracking(True)
        self._last_mouse_x = 0
        self._last_mouse_y = 0
        self._last_slice = 0

        QObject.connect(self._widget,
                    SIGNAL("mouse_press"),
                    self.mouse_pressed)

        QObject.connect(self._widget,
                    SIGNAL("mouse_move"),
                    self.mouse_moved)

        QObject.connect(self,
                    SIGNAL("mouse_moved"),
                    self.coordinates)

        ################### menubar ###################
        self.menu = self.menuBar()
        self.menu_file = self.menu.addMenu('File')

        # Import Points
        self._load_points = self.menu_file.addAction('Import Points')
        QObject.connect(self._load_points,
                        SIGNAL("triggered(bool)"),
                        self.load_points)

        # Save points
        self._save_points = self.menu_file.addAction('Save Points')
        QObject.connect(self._save_points,
                        SIGNAL("triggered(bool)"),
                        self.save_points)

        ################### toolbar ###################
        self._toolbar = self.addToolBar("tools")
        self._toolgroup = QActionGroup(self)

        # QWidgetAction : "Rotation Left"
        self._action_left = self._toolbar.addAction("left rotation")
        self._action_left.setIcon(QIcon(":/image/rotate_left.png") )
        QObject.connect(self._action_left,
                        SIGNAL("triggered(bool)"),
                        self.rotate_left)

        # QWidgetAction : "Rotation Right"
        self._action_right = self._toolbar.addAction("right rotation")
        self._action_right.setIcon(QIcon(":/image/rotate_right.png") )
        QObject.connect(self._action_right,
                        SIGNAL("triggered(bool)"),
                        self.rotate_right)

        # QWidgetAction : "Add point"
        self._action_add = self._toolbar.addAction("Add point")
        self._action_add.setCheckable(True)
        self._toolgroup.addAction(self._action_add)
        self._action_add.setIcon(QIcon(":/image/add.png") )

        # QWidgetAction : "Delete point"
        self._action_delete = self._toolbar.addAction("Delete point")
        self._action_delete.setCheckable(True)
        self._toolgroup.addAction(self._action_delete)
        self._action_delete.setIcon(QIcon(":/image/delete.png") )

        ################### palette ###################
        self._palette_select = QComboBox()
        self._toolbar.addWidget(self._palette_select)
        for palname in palette_names :
            self._palette_select.addItem(palname)

        QObject.connect(self._palette_select,
                    SIGNAL("currentIndexChanged(int)"),
                    self.palette_name_changed)

        ################### slider ###################
        self._bot_toolbar = QToolBar("slider")
        self._img_slider = QSlider(Qt.Horizontal)
        self._img_slider.setRange(0,self._view.nb_slices() - 1)

        QObject.connect(self._img_slider,
                        SIGNAL("valueChanged(int)"),
                        self.slice_changed)

        self._bot_toolbar.addWidget(self._img_slider)
        self.addToolBar(Qt.BottomToolBarArea,self._bot_toolbar)

        ################### statusbar ###################
        self._lab_coord = QLabel("coords:")
        self._lab_xcoord = QLabel("% 4d" % 0)
        self._lab_ycoord = QLabel("% 4d" % 0)
        self._lab_zcoord = QLabel("% 4d" % 0)
        self._lab_intens = QLabel("intens: None")

        self.statusbar = self.statusBar()
        self.statusbar.addPermanentWidget(self._lab_coord)
        self.statusbar.addPermanentWidget(self._lab_xcoord)
        self.statusbar.addPermanentWidget(self._lab_ycoord)
        self.statusbar.addPermanentWidget(self._lab_zcoord)
        self.statusbar.addPermanentWidget(self._lab_intens)

    ##############################################
    #
    #               update GUI
    #
    ##############################################
    def update_pix (self) :
        """
        """
        pix = self._view.pixmap()

        if pix is not None :
            self._item.setPixmap(pix)
        else:
            print 'None pixmap'
        #update points
        ind = self._view.current_slice()
        for point in self._points :
            if point is not None:
                pid,item, x,y,z,textid = point
                visible = abs(z - ind) < 5
                item.setVisible(visible)
                col = QColor.fromHsv( (pid * 10) % 360,255,255)
                if visible :
                    sca = max(0.,(5 - abs(z - ind) ) / 5.)
                    if z == ind :
                        pen = QPen(QColor(255,255,255) )
                        pen.setWidthF(2.)
                        item.setPen(pen)
                        textid.setVisible(True)
                    else :
                        pen = QPen(QColor(0,0,0) )
                        pen.setWidthF(2.)
                        item.setPen(pen)
                        textid.setVisible(False)
                else :
                    sca = 1.
                tr = QTransform()
                tr.scale(sca,sca)
                item.setTransform(tr)
                item.update()

    def coordinates (self,(i,j,k)) :
        self._last_mouse_x,self._last_mouse_y, self._last_slice = i,j,k
        self.fill_infos()
class SlideViewer (QMainWindow) :
    """Display each image in a stack using a slider
    """

    viewer_count = 0

    def __init__ (self, parent=None) :
        QMainWindow.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.axis = 2

        #central label
        self._im_view = PixmapStackView()
        self._label = ScalableLabel()
        self.setCentralWidget(self._label)

        #mouse handling
        self._label.setMouseTracking(True)
        self._last_mouse_x = 0
        self._last_mouse_y = 0

        QObject.connect(self._label,
                        SIGNAL("mouse_press"),
                        self.mouse_pressed)

        QObject.connect(self._label,
                        SIGNAL("mouse_move"),
                        self.mouse_pressed)

        #toolbar
        QObject.connect(self.ui.action_close,
                        SIGNAL("triggered(bool)"),
                        self.close)

        QObject.connect(self.ui.action_snapshot,
                        SIGNAL("triggered(bool)"),
                        self.snapshot)

        QObject.connect(self.ui.action_rotate_left,
                        SIGNAL("triggered(bool)"),
                        self.rotate_left)

        QObject.connect(self.ui.action_rotate_right,
                        SIGNAL("triggered(bool)"),
                        self.rotate_right)

        #palette
        self._palette_select = QComboBox()
        self.ui.toolbar.addWidget(self._palette_select)
        for palname in palette_names :
            self._palette_select.addItem(palname)

        QObject.connect(self._palette_select,
                        SIGNAL("currentIndexChanged(int)"),
                        self.palette_name_changed)
        #axis
        self._axis = QComboBox(self)
        self.ui.toolbar.addWidget(self._axis)
        self._axis.addItem("Z-axis")
        self._axis.addItem("Y-axis")
        self._axis.addItem("X-axis")
        self.connect(self._axis, SIGNAL('currentIndexChanged(int)'), self.change_axis )

        #slider
        self._bot_toolbar = QToolBar("slider")

        self._img_slider = QSlider(Qt.Horizontal)
        self._img_slider.setEnabled(False)
        QObject.connect(self._img_slider,
                        SIGNAL("valueChanged(int)"),
                        self.slice_changed)

        self._bot_toolbar.addWidget(self._img_slider)
        self.addToolBar(Qt.BottomToolBarArea,self._bot_toolbar)

        #statusbar
        self._lab_coord = QLabel("coords:")
        self._lab_xcoord = QLabel("% 4d" % 0)
        self._lab_ycoord = QLabel("% 4d" % 0)
        self._lab_zcoord = QLabel("% 4d" % 0)
        self._lab_intens = QLabel("intens: None")

        self.ui.statusbar.addPermanentWidget(self._lab_coord)
        self.ui.statusbar.addPermanentWidget(self._lab_xcoord)
        self.ui.statusbar.addPermanentWidget(self._lab_ycoord)
        self.ui.statusbar.addPermanentWidget(self._lab_zcoord)
        self.ui.statusbar.addPermanentWidget(self._lab_intens)

        self.set_title("<"+str(self.viewer_count)+">")
        SlideViewer.viewer_count += 1

    ##############################################
    #
    #        update GUI
    #
    ##############################################
    def update_pix (self) :
        pix = self._im_view.pixmap()
        if pix is not None :
            self._label.setPixmap(pix)

    def get_pixel_value_str(self, img, x, y, z):
        px = img[x,y,z]
        if isinstance(px, np.ndarray):
            return str(px)
        else:
            return "%3d"%px

    def fill_infos (self) :
        x,y = self._label.pixmap_coordinates(self._last_mouse_x,
                                             self._last_mouse_y)
        img = self._im_view.image()
        if img is not None :
            i,j,k = self._im_view.data_coordinates(x,y)
            self._lab_xcoord.setText("% 4d" % i)
            self._lab_ycoord.setText("% 4d" % j)
            self._lab_zcoord.setText("% 4d" % k)

            imax,jmax,kmax = img.shape[:3]
            if self.axis==0 : #axis x
                if 0 <= i < jmax and 0 <= j < kmax and 0 <= k < imax :
                    self._lab_intens.setText("intens: %s" % self.get_pixel_value_str(img,k,i,j))
                else :
                    self._lab_intens.setText("intens: None")
            elif self.axis==1 : #axis y
                if 0 <= i < imax and 0 <= j < kmax and 0 <= k < jmax :
                    self._lab_intens.setText("intens: %s" % self.get_pixel_value_str(img,i,k,j))
                else :
                    self._lab_intens.setText("intens: None")
            else : #axis z
                if 0 <= i < imax and 0 <= j < jmax and 0 <= k < kmax :
                    self._lab_intens.setText("intens: %s" % self.get_pixel_value_str(img,i,j,k))
                else :
                    self._lab_intens.setText("intens: None")

    ##############################################
    #
    #        accessors
    #
    ##############################################
    def set_image (self, img) :
        self._im_view.set_image(img)
        try :
            self.resolution = img.resolution[:]
        except AttributeError :
            pass
        self._img_slider.setRange(0,self._im_view.nb_slices() - 1)
        self._img_slider.setEnabled(True)
        self.slice_changed(self._img_slider.value() )

    def set_palette (self, palette, palette_name = None) :
        if palette_name is not None :
            ind = self._palette_select.findText(palette_name)
            self._palette_select.setCurrentIndex(ind)
        self._im_view.set_palette(palette,self.axis)
        self.update_pix()

    def set_title(self, title=None):
        if title is not None :
            self.setWindowTitle(title)

    def change_axis(self,ind):
        self.axis = 2-ind
        try :
            res = list(self.resolution)
            del res[self.axis]
            tr = self._im_view._transform
            if tr % 180 :
                self._label._resolution=res[1],res[0]
            else :
                self._label.set_resolution(*res)
        except AttributeError :
            pass
        self._im_view._reconstruct_pixmaps(self.axis)
        self._img_slider.setRange(0,self._im_view.nb_slices() - 1)
        self._img_slider.setEnabled(True)
        self.update_pix()
        #self.fill_infos()



    ##############################################
    #
    #        slots
    #
    ##############################################
    def palette_name_changed (self, palette_index) :
        palname = str(self._palette_select.currentText() )
        img = self._im_view.image()
        if img is not None :
            self.set_palette(palette_factory(str(palname),img.max()) )

    def slice_changed (self, ind) :
        self._im_view.set_current_slice(ind)
        self.update_pix()
        self.fill_infos()

    def snapshot (self) :
        """write the current image
        """
        pix = self._im_view.pixmap()
        if pix is not None :
            pix.save("slice%.4d.png" % self._img_slider.value() )

    def wheelEvent (self, event) :
        inc = event.delta() / 8 / 15
        self._img_slider.setValue(self._img_slider.value() + inc)

    def rotate_left (self) :
        res=self._label._resolution
        self._label._resolution=res[1],res[0]
        self._im_view.rotate(-1)
        self.update_pix()

    def rotate_right (self) :
        res=self._label._resolution
        self._label._resolution=res[1],res[0]
        self._im_view.rotate(1)
        self.update_pix()

    def mouse_pressed (self, event) :
        self._last_mouse_x = event.x()
        self._last_mouse_y = event.y()
        self.fill_infos()
    def __init__(self):
        QMainWindow.__init__(self)

        # points
        self._points = []
        self._id_gen = IdSetGenerator()
        #X         self.version = 2

        self._view = PixmapStackView()

        #QGraphicsScene
        self._scene = QGraphicsScene()

        #QGraphicsPixmapItem
        self._item = QGraphicsPixmapItem()
        self._item.setTransformationMode(Qt.SmoothTransformation)
        self._item.setFlag(self._item.ItemIsSelectable, False)
        self._scene.addItem(self._item)

        #QGraphicsView
        self._widget = ScalableGraphicsView(self._scene)
        self.setCentralWidget(self._widget)

        ################### mouse handling ###################
        self._widget.setMouseTracking(True)
        self._last_mouse_x = 0
        self._last_mouse_y = 0
        self._last_slice = 0

        QObject.connect(self._widget, SIGNAL("mouse_press"),
                        self.mouse_pressed)

        QObject.connect(self._widget, SIGNAL("mouse_move"), self.mouse_moved)

        QObject.connect(self, SIGNAL("mouse_moved"), self.coordinates)

        ################### menubar ###################
        self.menu = self.menuBar()
        self.menu_file = self.menu.addMenu('File')

        # Import Points
        self._load_points = self.menu_file.addAction('Import Points')
        QObject.connect(self._load_points, SIGNAL("triggered(bool)"),
                        self.load_points)

        # Save points
        self._save_points = self.menu_file.addAction('Save Points')
        QObject.connect(self._save_points, SIGNAL("triggered(bool)"),
                        self.save_points)

        ################### toolbar ###################
        self._toolbar = self.addToolBar("tools")
        self._toolgroup = QActionGroup(self)

        # QWidgetAction : "Rotation Left"
        self._action_left = self._toolbar.addAction("left rotation")
        self._action_left.setIcon(QIcon(":/image/rotate_left.png"))
        QObject.connect(self._action_left, SIGNAL("triggered(bool)"),
                        self.rotate_left)

        # QWidgetAction : "Rotation Right"
        self._action_right = self._toolbar.addAction("right rotation")
        self._action_right.setIcon(QIcon(":/image/rotate_right.png"))
        QObject.connect(self._action_right, SIGNAL("triggered(bool)"),
                        self.rotate_right)

        # QWidgetAction : "Add point"
        self._action_add = self._toolbar.addAction("Add point")
        self._action_add.setCheckable(True)
        self._toolgroup.addAction(self._action_add)
        self._action_add.setIcon(QIcon(":/image/add.png"))

        # QWidgetAction : "Delete point"
        self._action_delete = self._toolbar.addAction("Delete point")
        self._action_delete.setCheckable(True)
        self._toolgroup.addAction(self._action_delete)
        self._action_delete.setIcon(QIcon(":/image/delete.png"))

        ################### palette ###################
        self._palette_select = QComboBox()
        self._toolbar.addWidget(self._palette_select)
        for palname in palette_names:
            self._palette_select.addItem(palname)

        QObject.connect(self._palette_select,
                        SIGNAL("currentIndexChanged(int)"),
                        self.palette_name_changed)

        ################### slider ###################
        self._bot_toolbar = QToolBar("slider")
        self._img_slider = QSlider(Qt.Horizontal)
        self._img_slider.setRange(0, self._view.nb_slices() - 1)

        QObject.connect(self._img_slider, SIGNAL("valueChanged(int)"),
                        self.slice_changed)

        self._bot_toolbar.addWidget(self._img_slider)
        self.addToolBar(Qt.BottomToolBarArea, self._bot_toolbar)

        ################### statusbar ###################
        self._lab_coord = QLabel("coords:")
        self._lab_xcoord = QLabel("% 4d" % 0)
        self._lab_ycoord = QLabel("% 4d" % 0)
        self._lab_zcoord = QLabel("% 4d" % 0)
        self._lab_intens = QLabel("intens: None")

        self.statusbar = self.statusBar()
        self.statusbar.addPermanentWidget(self._lab_coord)
        self.statusbar.addPermanentWidget(self._lab_xcoord)
        self.statusbar.addPermanentWidget(self._lab_ycoord)
        self.statusbar.addPermanentWidget(self._lab_zcoord)
        self.statusbar.addPermanentWidget(self._lab_intens)
class PointSelection(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)

        # points
        self._points = []
        self._id_gen = IdSetGenerator()
        #X         self.version = 2

        self._view = PixmapStackView()

        #QGraphicsScene
        self._scene = QGraphicsScene()

        #QGraphicsPixmapItem
        self._item = QGraphicsPixmapItem()
        self._item.setTransformationMode(Qt.SmoothTransformation)
        self._item.setFlag(self._item.ItemIsSelectable, False)
        self._scene.addItem(self._item)

        #QGraphicsView
        self._widget = ScalableGraphicsView(self._scene)
        self.setCentralWidget(self._widget)

        ################### mouse handling ###################
        self._widget.setMouseTracking(True)
        self._last_mouse_x = 0
        self._last_mouse_y = 0
        self._last_slice = 0

        QObject.connect(self._widget, SIGNAL("mouse_press"),
                        self.mouse_pressed)

        QObject.connect(self._widget, SIGNAL("mouse_move"), self.mouse_moved)

        QObject.connect(self, SIGNAL("mouse_moved"), self.coordinates)

        ################### menubar ###################
        self.menu = self.menuBar()
        self.menu_file = self.menu.addMenu('File')

        # Import Points
        self._load_points = self.menu_file.addAction('Import Points')
        QObject.connect(self._load_points, SIGNAL("triggered(bool)"),
                        self.load_points)

        # Save points
        self._save_points = self.menu_file.addAction('Save Points')
        QObject.connect(self._save_points, SIGNAL("triggered(bool)"),
                        self.save_points)

        ################### toolbar ###################
        self._toolbar = self.addToolBar("tools")
        self._toolgroup = QActionGroup(self)

        # QWidgetAction : "Rotation Left"
        self._action_left = self._toolbar.addAction("left rotation")
        self._action_left.setIcon(QIcon(":/image/rotate_left.png"))
        QObject.connect(self._action_left, SIGNAL("triggered(bool)"),
                        self.rotate_left)

        # QWidgetAction : "Rotation Right"
        self._action_right = self._toolbar.addAction("right rotation")
        self._action_right.setIcon(QIcon(":/image/rotate_right.png"))
        QObject.connect(self._action_right, SIGNAL("triggered(bool)"),
                        self.rotate_right)

        # QWidgetAction : "Add point"
        self._action_add = self._toolbar.addAction("Add point")
        self._action_add.setCheckable(True)
        self._toolgroup.addAction(self._action_add)
        self._action_add.setIcon(QIcon(":/image/add.png"))

        # QWidgetAction : "Delete point"
        self._action_delete = self._toolbar.addAction("Delete point")
        self._action_delete.setCheckable(True)
        self._toolgroup.addAction(self._action_delete)
        self._action_delete.setIcon(QIcon(":/image/delete.png"))

        ################### palette ###################
        self._palette_select = QComboBox()
        self._toolbar.addWidget(self._palette_select)
        for palname in palette_names:
            self._palette_select.addItem(palname)

        QObject.connect(self._palette_select,
                        SIGNAL("currentIndexChanged(int)"),
                        self.palette_name_changed)

        ################### slider ###################
        self._bot_toolbar = QToolBar("slider")
        self._img_slider = QSlider(Qt.Horizontal)
        self._img_slider.setRange(0, self._view.nb_slices() - 1)

        QObject.connect(self._img_slider, SIGNAL("valueChanged(int)"),
                        self.slice_changed)

        self._bot_toolbar.addWidget(self._img_slider)
        self.addToolBar(Qt.BottomToolBarArea, self._bot_toolbar)

        ################### statusbar ###################
        self._lab_coord = QLabel("coords:")
        self._lab_xcoord = QLabel("% 4d" % 0)
        self._lab_ycoord = QLabel("% 4d" % 0)
        self._lab_zcoord = QLabel("% 4d" % 0)
        self._lab_intens = QLabel("intens: None")

        self.statusbar = self.statusBar()
        self.statusbar.addPermanentWidget(self._lab_coord)
        self.statusbar.addPermanentWidget(self._lab_xcoord)
        self.statusbar.addPermanentWidget(self._lab_ycoord)
        self.statusbar.addPermanentWidget(self._lab_zcoord)
        self.statusbar.addPermanentWidget(self._lab_intens)

    ##############################################
    #
    #               update GUI
    #
    ##############################################
    def update_pix(self):
        """
        """
        pix = self._view.pixmap()

        if pix is not None:
            self._item.setPixmap(pix)
        else:
            print 'None pixmap'
        #update points
        ind = self._view.current_slice()
        for point in self._points:
            if point is not None:
                pid, item, x, y, z, textid = point
                visible = abs(z - ind) < 5
                item.setVisible(visible)
                col = QColor.fromHsv((pid * 10) % 360, 255, 255)
                if visible:
                    sca = max(0., (5 - abs(z - ind)) / 5.)
                    if z == ind:
                        pen = QPen(QColor(255, 255, 255))
                        pen.setWidthF(2.)
                        item.setPen(pen)
                        textid.setVisible(True)
                    else:
                        pen = QPen(QColor(0, 0, 0))
                        pen.setWidthF(2.)
                        item.setPen(pen)
                        textid.setVisible(False)
                else:
                    sca = 1.
                tr = QTransform()
                tr.scale(sca, sca)
                item.setTransform(tr)
                item.update()

    def coordinates(self, (i, j, k)):
        self._last_mouse_x, self._last_mouse_y, self._last_slice = i, j, k
        self.fill_infos()
    def __init__ (self, parent=None) :
        QMainWindow.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.axis = 2

        #central label
        self._im_view = PixmapStackView()
        self._label = ScalableLabel()
        self.setCentralWidget(self._label)

        #mouse handling
        self._label.setMouseTracking(True)
        self._last_mouse_x = 0
        self._last_mouse_y = 0

        QObject.connect(self._label,
                        SIGNAL("mouse_press"),
                        self.mouse_pressed)

        QObject.connect(self._label,
                        SIGNAL("mouse_move"),
                        self.mouse_pressed)

        #toolbar
        QObject.connect(self.ui.action_close,
                        SIGNAL("triggered(bool)"),
                        self.close)

        QObject.connect(self.ui.action_snapshot,
                        SIGNAL("triggered(bool)"),
                        self.snapshot)

        QObject.connect(self.ui.action_rotate_left,
                        SIGNAL("triggered(bool)"),
                        self.rotate_left)

        QObject.connect(self.ui.action_rotate_right,
                        SIGNAL("triggered(bool)"),
                        self.rotate_right)

        #palette
        self._palette_select = QComboBox()
        self.ui.toolbar.addWidget(self._palette_select)
        for palname in palette_names :
            self._palette_select.addItem(palname)

        QObject.connect(self._palette_select,
                        SIGNAL("currentIndexChanged(int)"),
                        self.palette_name_changed)
        #axis
        self._axis = QComboBox(self)
        self.ui.toolbar.addWidget(self._axis)
        self._axis.addItem("Z-axis")
        self._axis.addItem("Y-axis")
        self._axis.addItem("X-axis")
        self.connect(self._axis, SIGNAL('currentIndexChanged(int)'), self.change_axis )

        #slider
        self._bot_toolbar = QToolBar("slider")

        self._img_slider = QSlider(Qt.Horizontal)
        self._img_slider.setEnabled(False)
        QObject.connect(self._img_slider,
                        SIGNAL("valueChanged(int)"),
                        self.slice_changed)

        self._bot_toolbar.addWidget(self._img_slider)
        self.addToolBar(Qt.BottomToolBarArea,self._bot_toolbar)

        #statusbar
        self._lab_coord = QLabel("coords:")
        self._lab_xcoord = QLabel("% 4d" % 0)
        self._lab_ycoord = QLabel("% 4d" % 0)
        self._lab_zcoord = QLabel("% 4d" % 0)
        self._lab_intens = QLabel("intens: None")

        self.ui.statusbar.addPermanentWidget(self._lab_coord)
        self.ui.statusbar.addPermanentWidget(self._lab_xcoord)
        self.ui.statusbar.addPermanentWidget(self._lab_ycoord)
        self.ui.statusbar.addPermanentWidget(self._lab_zcoord)
        self.ui.statusbar.addPermanentWidget(self._lab_intens)

        self.set_title("<"+str(self.viewer_count)+">")
        SlideViewer.viewer_count += 1
class SlideViewer (QMainWindow) :
    """Display each image in a stack using a slider
    
    A pure QWidget (instead of QMainWindow) is also available, see openalea.image.gui.slide_viewer_widget.
    """

    viewer_count = 0

    def __init__ (self, parent=None) :
        QMainWindow.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.axis = 2

        #central label
        self._im_view = PixmapStackView()
        self._label = ScalableLabel()
        self.setCentralWidget(self._label)

        #mouse handling
        self._label.setMouseTracking(True)
        self._last_mouse_x = 0
        self._last_mouse_y = 0

        QObject.connect(self._label,
                        SIGNAL("mouse_press"),
                        self.mouse_pressed)

        QObject.connect(self._label,
                        SIGNAL("mouse_move"),
                        self.mouse_pressed)

        #toolbar
        QObject.connect(self.ui.action_close,
                        SIGNAL("triggered(bool)"),
                        self.close)

        QObject.connect(self.ui.action_snapshot,
                        SIGNAL("triggered(bool)"),
                        self.snapshot)

        QObject.connect(self.ui.action_rotate_left,
                        SIGNAL("triggered(bool)"),
                        self.rotate_left)

        QObject.connect(self.ui.action_rotate_right,
                        SIGNAL("triggered(bool)"),
                        self.rotate_right)

        #palette
        self._palette_select = QComboBox()
        self.ui.toolbar.addWidget(self._palette_select)
        for palname in palette_names :
            self._palette_select.addItem(palname)

        QObject.connect(self._palette_select,
                        SIGNAL("currentIndexChanged(int)"),
                        self.palette_name_changed)
        #axis
        self._axis = QComboBox(self)
        self.ui.toolbar.addWidget(self._axis)
        self._axis.addItem("Z-axis")
        self._axis.addItem("Y-axis")
        self._axis.addItem("X-axis")
        self.connect(self._axis, SIGNAL('currentIndexChanged(int)'), self.change_axis )

        #slider
        self._bot_toolbar = QToolBar("slider")

        self._img_slider = QSlider(Qt.Horizontal)
        self._img_slider.setEnabled(False)
        QObject.connect(self._img_slider,
                        SIGNAL("valueChanged(int)"),
                        self.slice_changed)

        self._bot_toolbar.addWidget(self._img_slider)
        self.addToolBar(Qt.BottomToolBarArea,self._bot_toolbar)

        #statusbar
        self._lab_coord = QLabel("coords:")
        self._lab_xcoord = QLabel("% 4d" % 0)
        self._lab_ycoord = QLabel("% 4d" % 0)
        self._lab_zcoord = QLabel("% 4d" % 0)
        self._lab_intens = QLabel("intens: None")

        self.ui.statusbar.addPermanentWidget(self._lab_coord)
        self.ui.statusbar.addPermanentWidget(self._lab_xcoord)
        self.ui.statusbar.addPermanentWidget(self._lab_ycoord)
        self.ui.statusbar.addPermanentWidget(self._lab_zcoord)
        self.ui.statusbar.addPermanentWidget(self._lab_intens)

        self.set_title("<"+str(self.viewer_count)+">")
        SlideViewer.viewer_count += 1

    ##############################################
    #
    #        update GUI
    #
    ##############################################
    def update_pix (self) :
        pix = self._im_view.pixmap()
        if pix is not None :
            self._label.setPixmap(pix)

    def get_pixel_value_str(self, img, x, y, z):
        px = img[x,y,z]
        if isinstance(px, np.ndarray):
            return str(px)
        else:
            return "%3d"%px

    def fill_infos (self) :
        x,y = self._label.pixmap_coordinates(self._last_mouse_x,
                                             self._last_mouse_y)
        img = self._im_view.image()
        if img is not None :
            i,j,k = self._im_view.data_coordinates(x,y)
            self._lab_xcoord.setText("% 4d" % i)
            self._lab_ycoord.setText("% 4d" % j)
            self._lab_zcoord.setText("% 4d" % k)

            imax,jmax,kmax = img.shape[:3]
            if self.axis==0 : #axis x
                if 0 <= i < jmax and 0 <= j < kmax and 0 <= k < imax :
                    self._lab_intens.setText("intens: %s" % self.get_pixel_value_str(img,k,i,j))
                else :
                    self._lab_intens.setText("intens: None")
            elif self.axis==1 : #axis y
                if 0 <= i < imax and 0 <= j < kmax and 0 <= k < jmax :
                    self._lab_intens.setText("intens: %s" % self.get_pixel_value_str(img,i,k,j))
                else :
                    self._lab_intens.setText("intens: None")
            else : #axis z
                if 0 <= i < imax and 0 <= j < jmax and 0 <= k < kmax :
                    self._lab_intens.setText("intens: %s" % self.get_pixel_value_str(img,i,j,k))
                else :
                    self._lab_intens.setText("intens: None")

    ##############################################
    #
    #        accessors
    #
    ##############################################
    def set_image (self, img) :
        self._im_view.set_image(img)
        try :
            self.resolution = img.resolution[:]
        except AttributeError :
            pass
        self._img_slider.setRange(0,self._im_view.nb_slices() - 1)
        self._img_slider.setEnabled(True)
        self.slice_changed(self._img_slider.value() )

    def set_palette (self, palette, palette_name = None) :
        if palette_name is not None :
            ind = self._palette_select.findText(palette_name)
            self._palette_select.setCurrentIndex(ind)
        self._im_view.set_palette(palette,self.axis)
        self.update_pix()

    def set_title(self, title=None):
        if title is not None :
            self.setWindowTitle(title)

    def change_axis(self,ind):
        self.axis = 2-ind
        try :
            res = list(self.resolution)
            del res[self.axis]
            tr = self._im_view._transform
            if tr % 180 :
                self._label._resolution=res[1],res[0]
            else :
                self._label.set_resolution(*res)
        except AttributeError :
            pass
        self._im_view._reconstruct_pixmaps(self.axis)
        self._img_slider.setRange(0,self._im_view.nb_slices() - 1)
        self._img_slider.setEnabled(True)
        self.update_pix()
        #self.fill_infos()



    ##############################################
    #
    #        slots
    #
    ##############################################
    def palette_name_changed (self, palette_index) :
        palname = str(self._palette_select.currentText() )
        img = self._im_view.image()
        if img is not None :
            self.set_palette(palette_factory(str(palname),img.max()) )

    def slice_changed (self, ind) :
        self._im_view.set_current_slice(ind)
        self.update_pix()
        self.fill_infos()

    def snapshot (self) :
        """write the current image
        """
        pix = self._im_view.pixmap()
        if pix is not None :
            pix.save("slice%.4d.png" % self._img_slider.value() )

    def wheelEvent (self, event) :
        inc = event.delta() / 8 / 15
        self._img_slider.setValue(self._img_slider.value() + inc)

    def rotate_left (self) :
        res=self._label._resolution
        self._label._resolution=res[1],res[0]
        self._im_view.rotate(-1)
        self.update_pix()

    def rotate_right (self) :
        res=self._label._resolution
        self._label._resolution=res[1],res[0]
        self._im_view.rotate(1)
        self.update_pix()

    def mouse_pressed (self, event) :
        self._last_mouse_x = event.x()
        self._last_mouse_y = event.y()
        self.fill_infos()