def __init__(self, parent=None, allow_adjust_size=True):
        QWidget.__init__(self, parent)
        self.setObjectName('heat_map_widget')
        self.allow_adjust_size = allow_adjust_size

        # Properties ----------------------------------------------------------

        # Signals -------------------------------------------------------------

        # Slots ---------------------------------------------------------------

        # Hardware objects ----------------------------------------------------
        self._beamline_setup_hwobj = None

        # Internal values -----------------------------------------------------
        self.__results = None
        self.__results_display = None
        self.__associated_grid = None
        self.__associated_data_collection = None
        self.__selected_x = 0
        self.__selected_y = 0
        self.__selected_image_serial = 0
        self.__score_key = "score"
        self.__max_value = 0
        self.__filter_min_value = 0
        self.__best_pos_list = None
        self.__label_im = None
        self.__heat_map_max_size = []
        self.__heatmap_clicked = False
        self.__enable_continues_image_display = True
        self.__tooltip_text = None

        # Graphic elements ----------------------------------------------------
        self._heat_map_gbox = QGroupBox('Heat map', self)
        self._heat_map_plot = TwoDimenisonalPlotWidget(self)
        self._heat_map_popup_menu = QMenu(self._heat_map_gbox)

        heat_map_info_widget = QWidget(self._heat_map_gbox)
        score_type_label = QLabel("Score type: ", heat_map_info_widget)
        self._score_type_cbox = QComboBox(heat_map_info_widget)
        self._image_info_label = QLabel("Image: #, value #",
                                        heat_map_info_widget)

        self._heat_map_tools_widget = QWidget(self._heat_map_gbox)

        _threshold_label = QLabel("Threshold: ", self._heat_map_tools_widget)
        self._threshold_slider = QSlider(Qt.Horizontal,
                                         self._heat_map_tools_widget)
        self._relaunch_processing_button = QPushButton(
            "Relaunch processing", self._heat_map_tools_widget)
        self._create_points_button = QPushButton("Create centring points",
                                                 self._heat_map_tools_widget)

        self._summary_gbox = QGroupBox("Summary", self)
        self._summary_textbrowser = QTextBrowser(self._summary_gbox)
        self._best_pos_gbox = QGroupBox("Best positions", self)
        self._best_pos_table = QTableWidget(self._best_pos_gbox)
        self._best_pos_popup_menu = QMenu(self._heat_map_gbox)
        self._best_pos_gbox.setHidden(True)

        # Layout --------------------------------------------------------------
        _heat_map_info_hlayout = QHBoxLayout(heat_map_info_widget)
        _heat_map_info_hlayout.addWidget(score_type_label)
        _heat_map_info_hlayout.addWidget(self._score_type_cbox)
        _heat_map_info_hlayout.addStretch(0)
        _heat_map_info_hlayout.addWidget(self._image_info_label)
        _heat_map_info_hlayout.setSpacing(2)
        _heat_map_info_hlayout.setContentsMargins(0, 0, 0, 0)

        _heat_map_tools_hlayout = QHBoxLayout(self._heat_map_tools_widget)
        _heat_map_tools_hlayout.addWidget(_threshold_label)
        _heat_map_tools_hlayout.addWidget(self._threshold_slider)
        _heat_map_tools_hlayout.addStretch(0)
        _heat_map_tools_hlayout.addWidget(self._relaunch_processing_button)
        _heat_map_tools_hlayout.addWidget(self._create_points_button)
        _heat_map_tools_hlayout.setSpacing(2)
        _heat_map_tools_hlayout.setContentsMargins(0, 0, 0, 0)

        _heat_map_gbox_vlayout = QVBoxLayout(self._heat_map_gbox)
        _heat_map_gbox_vlayout.addWidget(self._heat_map_plot)
        _heat_map_gbox_vlayout.addWidget(heat_map_info_widget)
        _heat_map_gbox_vlayout.addWidget(self._heat_map_tools_widget)
        _heat_map_gbox_vlayout.setSpacing(2)
        _heat_map_gbox_vlayout.setContentsMargins(0, 0, 0, 0)

        _summary_gbox_vlayout = QVBoxLayout(self._summary_gbox)
        _summary_gbox_vlayout.addWidget(self._summary_textbrowser)
        _summary_gbox_vlayout.setSpacing(2)
        _summary_gbox_vlayout.setContentsMargins(0, 0, 0, 0)

        _best_postition_gbox_vlayout = QVBoxLayout(self._best_pos_gbox)
        _best_postition_gbox_vlayout.addWidget(self._best_pos_table)
        _best_postition_gbox_vlayout.setSpacing(2)
        _best_postition_gbox_vlayout.setContentsMargins(0, 0, 0, 0)

        _main_hlayout = QVBoxLayout(self)
        _main_hlayout.addWidget(self._heat_map_gbox)
        _main_hlayout.addWidget(self._summary_gbox)
        _main_hlayout.addWidget(self._best_pos_gbox)
        _main_hlayout.setSpacing(2)
        _main_hlayout.setContentsMargins(2, 2, 2, 2)

        # SizePolicies --------------------------------------------------------
        self._image_info_label.setAlignment(Qt.AlignLeft)
        self._image_info_label.setSizePolicy(QSizePolicy.Expanding,
                                             QSizePolicy.Fixed)

        # Qt signals and slots ------------------------------------------------
        self._score_type_cbox.activated.connect(self.score_type_changed)
        self._threshold_slider.valueChanged.\
             connect(self.filter_min_slider_changed)
        self._relaunch_processing_button.clicked.\
             connect(self.relaunch_processing_clicked)
        self._create_points_button.clicked.\
             connect(self.create_points_clicked)
        self._heat_map_plot.mouseMovedSignal.\
             connect(self.mouse_moved)
        self._heat_map_plot.mouseClickedSignal.\
             connect(self.mouse_clicked)
        self._heat_map_plot.mouseDoubleClickedSignal.\
             connect(self.move_to_position_clicked)
        self._heat_map_plot.mouseLeftSignal.connect(\
             self.mouse_left_plot)

        # Other ---------------------------------------------------------------
        self.__tooltip_text = "Double click to move to the position. " + \
                              "Right click to open menu."
        self._heat_map_plot.setToolTip(self.__tooltip_text)
        self._heat_map_popup_menu.addSeparator()
        self._heat_map_popup_menu.addAction(\
             "Move to position",
             self.move_to_position_clicked)
        self._heat_map_popup_menu.addAction(\
             "Create centring point",
             self.create_centring_point_clicked)

        self._heat_map_popup_menu.addAction(\
             "Create helical line",
             self.create_helical_line_clicked)
        self._heat_map_popup_menu.addAction(\
             "Rotate 90 degrees and create helical line",
             self.rotate_and_create_helical_line_clicked)

        self._heat_map_popup_menu.addSeparator()
        self._heat_map_popup_menu.addAction(\
             "Open image in ADXV", self.display_image_clicked)
        self.continues_display_action = \
             self._heat_map_popup_menu.addAction(\
             "Continues image display in ADXV",
              self.toogle_continues_image_display)
        self.continues_display_action.setCheckable(True)
        self.continues_display_action.setChecked(True)

        self._heat_map_popup_menu.addSeparator()
        options_menu = self._heat_map_popup_menu.addMenu("Options")

        self._heat_map_plot.contextMenuEvent = self.open_heat_map_popup_menu

        score_types = ["Resolution", "Score", "Spots num"]
        for score_type in score_types:
            self._score_type_cbox.addItem(score_type)
        self._score_type_cbox.setMaximumWidth(200)
        self.__score_key = "spots_resolution"

        #self._threshold_slider.setTickmarks(QtGui.QSlider.Below)
        self._threshold_slider.setRange(0, 100)
        self._threshold_slider.setTickInterval(5)
        self._threshold_slider.setFixedWidth(200)
        self._threshold_slider.setTracking(False)

        font = self._best_pos_table.font()
        font.setPointSize(8)
        self._best_pos_table.setFont(font)
        self._best_pos_table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self._best_pos_table.setColumnCount(9)
        self._best_pos_table.setAlternatingRowColors(True)
        self._best_pos_table.setWordWrap(False)
        self._best_pos_table.horizontalHeader().setSortIndicatorShown(True)
        self._best_pos_table.setHorizontalHeaderItem(0, \
            QTableWidgetItem("No."))
        for score_type in enumerate(score_types):
            self._best_pos_table.setHorizontalHeaderItem(\
                 score_type[0] + 1, QTableWidgetItem(score_type[1]))

        self._best_pos_table.setHorizontalHeaderItem(5,
                                                     QTableWidgetItem("Path"))
        self._best_pos_table.setHorizontalHeaderItem(6,
                                                     QTableWidgetItem("Col"))
        self._best_pos_table.setHorizontalHeaderItem(7,
                                                     QTableWidgetItem("Row"))
        self._best_pos_table.setHorizontalHeaderItem(
            8, QTableWidgetItem("Motor positions"))

        self._best_pos_popup_menu.addAction(\
             "Move to position",
              self.move_to_best_position_clicked)
        self._best_pos_table.contextMenuEvent = self.open_best_pos_popup_menu
        #self._best_pos_table.setHidden(True)

        screenShape = QDesktopWidget().screenGeometry()
        self.__heat_map_max_size = (screenShape.width() / 2,
                                    screenShape.height() / 2)
Beispiel #2
0
class HeatMapWidget(QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.setObjectName('heat_map_widget')

        # Properties ----------------------------------------------------------

        # Signals -------------------------------------------------------------

        # Slots ---------------------------------------------------------------

        # Hardware objects ----------------------------------------------------
        self._beamline_setup_hwobj = None

        # Internal values -----------------------------------------------------
        self.__results = None
        self.__result_display = None
        self.__associated_grid = None
        self.__associated_data_collection = None
        self.__selected_x = 0
        self.__selected_y = 0
        self.__selected_image_serial = 0
        self.__is_map_plot = None
        self.__score_type_index = 0
        self.__max_value = 0
        self.__filter_min_value = 0
        self.__best_pos_list = None
        self.__heat_map_max_size = []

        # Graphic elements ----------------------------------------------------
        self._heat_map_gbox = QtGui.QGroupBox('Heat map', self)
        self._heat_map_plot = TwoDimenisonalPlotWidget(self)
        self._heat_map_popup_menu = QtGui.QMenu(self._heat_map_gbox)
        self._image_info_label = QtGui.QLabel("Image: #, value #",
                                              self._heat_map_gbox)

        self._heat_map_tools_widget = QtGui.QWidget(self._heat_map_gbox)
        score_type_label = QtGui.QLabel("Score type: ",
                                        self._heat_map_tools_widget)
        self._score_type_cbox = QtGui.QComboBox(self._heat_map_tools_widget)

        _threshold_label = QtGui.QLabel("Threshold: ",
                                        self._heat_map_tools_widget)
        self._threshold_slider = QtGui.QSlider(QtCore.Qt.Horizontal,
                                               self._heat_map_tools_widget)
        self._create_points_button = QtGui.QPushButton(
            "Create centring points", self._heat_map_tools_widget)

        self._summary_gbox = QtGui.QGroupBox("Summary", self)
        self._summary_textbrowser = QtGui.QTextBrowser(self._summary_gbox)
        self._best_pos_gbox = QtGui.QGroupBox("Best positions", self)
        self._best_pos_table = QtGui.QTableWidget(self._best_pos_gbox)
        self._best_pos_popup_menu = QtGui.QMenu(self._heat_map_gbox)

        # Layout --------------------------------------------------------------
        _heat_map_tools_hlayout = QtGui.QHBoxLayout(
            self._heat_map_tools_widget)
        _heat_map_tools_hlayout.addWidget(score_type_label)
        _heat_map_tools_hlayout.addWidget(self._score_type_cbox)
        _heat_map_tools_hlayout.addWidget(_threshold_label)
        _heat_map_tools_hlayout.addWidget(self._threshold_slider)
        _heat_map_tools_hlayout.addStretch(0)
        _heat_map_tools_hlayout.addWidget(self._create_points_button)
        _heat_map_tools_hlayout.setSpacing(2)
        _heat_map_tools_hlayout.setContentsMargins(2, 2, 2, 2)

        _heat_map_gbox_vlayout = QtGui.QVBoxLayout(self._heat_map_gbox)
        _heat_map_gbox_vlayout.addWidget(self._heat_map_plot)
        _heat_map_gbox_vlayout.addWidget(self._image_info_label)
        _heat_map_gbox_vlayout.addWidget(self._heat_map_tools_widget)
        _heat_map_gbox_vlayout.setSpacing(2)
        _heat_map_gbox_vlayout.setContentsMargins(2, 4, 2, 2)

        _summary_gbox_vlayout = QtGui.QVBoxLayout(self._summary_gbox)
        _summary_gbox_vlayout.addWidget(self._summary_textbrowser)
        _summary_gbox_vlayout.setSpacing(2)
        _summary_gbox_vlayout.setContentsMargins(2, 4, 2, 2)

        _best_postition_gbox_vlayout = QtGui.QVBoxLayout(self._best_pos_gbox)
        _best_postition_gbox_vlayout.addWidget(self._best_pos_table)
        _best_postition_gbox_vlayout.setSpacing(2)
        _best_postition_gbox_vlayout.setContentsMargins(2, 4, 2, 2)

        _main_hlayout = QtGui.QVBoxLayout(self)
        _main_hlayout.addWidget(self._heat_map_gbox)
        _main_hlayout.addWidget(self._summary_gbox)
        _main_hlayout.addWidget(self._best_pos_gbox)
        _main_hlayout.setSpacing(2)
        _main_hlayout.setContentsMargins(2, 2, 2, 2)

        # SizePolicies --------------------------------------------------------
        self._image_info_label.setAlignment(QtCore.Qt.AlignRight)
        self._image_info_label.setSizePolicy(QtGui.QSizePolicy.Expanding,
                                             QtGui.QSizePolicy.Fixed)

        # Qt signals and slots ------------------------------------------------
        self._score_type_cbox.activated.connect(self.score_type_changed)
        self._threshold_slider.valueChanged.connect(\
             self.filter_min_slider_changed)
        self._create_points_button.clicked.connect(\
             self.create_points_clicked)
        self._heat_map_plot.mouseClickedSignal.connect(self.mouse_clicked)
        self._heat_map_plot.mouseDoubleClickedSignal.connect(
            self.move_to_position_clicked)

        # Other ---------------------------------------------------------------
        tooltip_text = "Double click to move to the position. " + \
                       "Right click to open menu."
        self._heat_map_plot.setToolTip(tooltip_text)
        self._heat_map_popup_menu.addSeparator()
        self._heat_map_popup_menu.addAction(\
             "Move to position", self.move_to_position_clicked)
        self._heat_map_popup_menu.addAction(\
             "Create centring point", self.create_centring_point_clicked)
        self._heat_map_popup_menu.addSeparator()
        self._heat_map_popup_menu.addAction(\
             "Open image in ADXV", self.display_image_clicked)
        self._heat_map_plot.contextMenuEvent = self.open_heat_map_popup_menu

        score_types = ["Score", "Spots num", "Int aver.", "Resolution"]
        for score_type in score_types:
            self._score_type_cbox.addItem(score_type)
        self._score_type_cbox.setMaximumWidth(200)

        #self._threshold_slider.setTickmarks(QtGui.QSlider.Below)
        self._threshold_slider.setRange(0, 100)
        self._threshold_slider.setTickInterval(5)
        self._threshold_slider.setFixedWidth(200)
        self._threshold_slider.setTracking(False)

        font = self._best_pos_table.font()
        font.setPointSize(8)
        self._best_pos_table.setFont(font)
        self._best_pos_table.setEditTriggers(\
             QtGui.QAbstractItemView.NoEditTriggers)
        self._best_pos_table.setColumnCount(9)
        self._best_pos_table.setAlternatingRowColors(True)
        self._best_pos_table.setWordWrap(False)
        self._best_pos_table.horizontalHeader().setSortIndicatorShown(True)
        self._best_pos_table.setHorizontalHeaderItem(0, \
            QtGui.QTableWidgetItem("No."))
        for score_type in enumerate(score_types):
            self._best_pos_table.setHorizontalHeaderItem(\
                 score_type[0] + 1, QtGui.QTableWidgetItem(score_type[1]))

        self._best_pos_table.setHorizontalHeaderItem(
            5, QtGui.QTableWidgetItem("Path"))
        self._best_pos_table.setHorizontalHeaderItem(
            6, QtGui.QTableWidgetItem("Col"))
        self._best_pos_table.setHorizontalHeaderItem(
            7, QtGui.QTableWidgetItem("Row"))
        self._best_pos_table.setHorizontalHeaderItem(
            8, QtGui.QTableWidgetItem("Motor positions"))

        self._best_pos_popup_menu.addAction(\
             "Move to position",
              self.move_to_best_position_clicked)
        self._best_pos_table.contextMenuEvent = self.open_best_pos_popup_menu

        screenShape = QtGui.QDesktopWidget().screenGeometry()
        self.__heat_map_max_size = (screenShape.width() / 2 - 200,
                                    screenShape.height() / 2)

    def set_beamline_setup(self, beamline_setup_hwobj):
        self._beamline_setup_hwobj = beamline_setup_hwobj

    def set_associated_data_collection(self, data_collection):
        self.__associated_data_collection = data_collection

        #self._heat_map_plot.set_x_axis_limits((- 0.5, data_collection.\
        #      acquisitions[0].acquisition_parameters.num_images - 0.5))

    def set_associated_grid(self, grid):
        if grid is None:
            self.__is_map_plot = False
            #self._heat_map_plot.x1Label("Image num")
            #self._heat_map_plot.y1Label("Score")
        else:
            self.__is_map_plot = True
            self.__associated_grid = grid
            axis_range = self.__associated_grid.get_col_row_num()
            grid_size = self.__associated_grid.get_size_pix()

            width = grid_size[0] * 5
            height = grid_size[1] * 5
            ratio = float(width) / height

            if width > self.__heat_map_max_size[0]:
                width = self.__heat_map_max_size[0]
                height = width / ratio
            if height > self.__heat_map_max_size[1]:
                height = self.__heat_map_max_size[1]
                width = height * ratio

            self._heat_map_plot.setFixedWidth(width)
            self._heat_map_plot.setFixedHeight(height)

            #axis_range = self.__associated_grid.get_col_row_num()
            self._heat_map_plot.set_x_axis_limits((0, axis_range[0]))
            self._heat_map_plot.set_y_axis_limits((0, axis_range[1]))

    def main_gbox_toggled(self, toggle):
        self._heat_map_plot.setHidden(not toggle)
        self._heat_map_tools_widget.setHidden(not toggle)

    def open_heat_map_popup_menu(self, context_event):
        point = QtCore.QPoint(context_event.globalX(), context_event.globalY())
        self._heat_map_popup_menu.popup(point)

    def open_best_pos_popup_menu(self, context_event):
        if self._best_pos_table.rowCount() > 0:
            point = QtCore.QPoint(context_event.globalX(),
                                  context_event.globalY())
            self._best_pos_popup_menu.popup(point)

    def score_type_changed(self, score_type_index):
        self.__score_type_index = score_type_index
        #self._threshold_slider.setValue(0)
        self.refresh()

    def refresh(self):
        self._summary_textbrowser.clear()
        if self.__results is None:
            return

        self.__result_display = copy(self.__results["score"])
        if self.__score_type_index == 0:
            self.__result_display = copy(self.__results["score"])
        elif self.__score_type_index == 1:
            self.__result_display = copy(self.__results["spots_num"])
        elif self.__score_type_index == 2:
            self.__result_display = copy(self.__results["spots_int_aver"])
        elif self.__score_type_index == 3:
            self.__result_display = copy(self.__results["spots_resolution"])
        elif self.__score_type_index == 4:
            self.__result_display = copy(self.__results["image_num"])

        self.__filter_min_value = self.__result_display.max() * \
             self._threshold_slider.value() / 100.0
        self.__result_display[
            self.__result_display < self.__filter_min_value] = 0

        if len(self.__result_display.shape) == 1:
            x_data = numpy.arange(self.__result_display.shape[0])
            self._heat_map_plot.newcurve("Dozor result", x_data,
                                         self.__result_display)
        else:
            self._heat_map_plot.plot_result(self.__result_display)

        self._summary_textbrowser.append("<b>Mesh parameters</b>")
        grid_properties = self.__associated_grid.get_properties()
        self._summary_textbrowser.append("Number of columns: %d" % \
             grid_properties["steps_x"])
        self._summary_textbrowser.append("Number of rows: %d" % \
             grid_properties["steps_y"])
        self._summary_textbrowser.append("Horizontal spacing: %.1f %sm" % \
            (grid_properties["xOffset"], u"\u00B5"))
        self._summary_textbrowser.append("Vertical spacing: %.1f %sm" % \
            (grid_properties["yOffset"], u"\u00B5"))
        self._summary_textbrowser.append("Beam size : %.1f x %.1f %sm" % \
            (grid_properties["beam_x"], grid_properties["beam_y"], u"\u00B5"))
        self._summary_textbrowser.append("Scan range : %.1f x %.1f mm" % \
            (grid_properties["dx_mm"], grid_properties["dy_mm"]))

        self._summary_textbrowser.append("<b>Scan results</b>")
        self._summary_textbrowser.append("Scan lines: %d" % \
             grid_properties["num_lines"])
        self._summary_textbrowser.append("Images per line: %d" % \
             grid_properties["num_images_per_line"])
        self._summary_textbrowser.append("Number of diffraction spots: %d" % \
             (self.__results["score"] > 0).sum())

    def filter_min_slider_changed(self, value):
        self.refresh()

    def mouse_clicked(self, pos_x, pos_y):
        self.__selected_x = pos_x
        self.__selected_y = pos_y
        image, line, self.selected_image_serial, image_path = \
              self.get_image_parameters_from_coord()
        try:
            col, row = self.get_col_row_from_image_line(line, image)
            msg = "Image: %d, value: %.3f" % (self.selected_image_serial,
                                              self.__result_display[row][col])
        except:
            msg = "Image: %d" % self.selected_image_serial
        self._image_info_label.setText(msg)

    def plot_double_clicked(self, event):
        self.move_to_selected_position()

    def move_to_position_clicked(self):
        self.move_to_selected_position()

    def set_results(self, results, last_results=False):
        """
        Descript. : Displays results on the widget
        """
        self.__results = results
        self.refresh()
        if last_results:
            self.set_best_pos()
            self.setEnabled(True)

    def clean_result(self):
        self.setEnabled(False)
        self.__results = None
        self.__associated_grid = None
        self.__associated_data_collection = None
        self._heat_map_plot.clear()
        self._threshold_slider.setValue(0)
        self._summary_textbrowser.clear()
        self._best_pos_table.setRowCount(0)
        self._best_pos_table.setSortingEnabled(False)

    def create_centring_point_clicked(self):
        self.create_centring_point()

    def create_points_clicked(self):
        """
        Descript. : creates new centring points based on each image score.
                    All images are checked and if the value
                    is over the threshold then screen x and y coordinates
                    are estimated.
        """
        if self.__is_map_plot:
            result_display = numpy.transpose(self.__result_display)
            #step_x = pix_width / self.__result_display.shape[0]
            #step_y = pix_height / self.__result_display.shape[1]
            for col in range(result_display.shape[0]):
                for row in range(result_display.shape[1]):
                    if result_display[col][row] > 0:
                        #MD2
                        row = result_display.shape[1] - row - 1
                        self.create_centring_point(col + 0.5, row + 0.5)
        else:
            for col in range(self.__result_display.shape[0]):
                if self.__result_display[col] > 0:
                    self.create_centring_point(col + 0.5)
        self._beamline_setup_hwobj.shape_history_hwobj.select_all_points()

    def display_image_clicked(self):
        """
        Decript. : displays image in image tracker (by default adxv)
        """
        image, line, image_num, image_path = self.get_image_parameters_from_coord(
        )
        if self._beamline_setup_hwobj.image_tracking_hwobj is not None:
            self._beamline_setup_hwobj.image_tracking_hwobj.load_image(
                image_path)

    def get_image_parameters_from_coord(self, coord_x=None, coord_y=None):
        """
        Descript. : returns image parameters for selected heat map frame
        """
        if not coord_x:
            coord_x = self.__selected_x
        if not coord_y:
            coord_y = self.__selected_y

        if self.__is_map_plot:
            num_cols, num_rows = self.__associated_grid.get_col_row_num()
            if coord_x > num_cols:
                coord_x = num_cols
            if coord_y > num_rows:
                coord_y = num_rows

            image, line, image_num = self.__associated_grid.\
                  get_image_from_col_row(coord_x, coord_y)
        else:
            image = int(self.__selected_x)
            line = 1
            image_num = image + self.__associated_data_collection.\
                  acquisitions[0].acquisition_parameters.first_image
        image_path = self.__associated_data_collection.acquisitions[0].\
                      path_template.get_image_path()
        image_path = image_path % image_num
        return image, line, image_num, image_path

    def get_col_row_from_image_line(self, line, image):
        return self.__associated_grid.get_col_row_from_line_image(line, image)

    def create_centring_point(self, coord_x=None, coord_y=None):
        """
        Descript. : creates a new centring point for selected coordinate.
                    For mesh scan coord_x, and coord_y are grid coordinates in microns
                    For helical line coord_x represents frame number
        """
        if coord_x is None:
            coord_x = self.__selected_x
        if coord_y is None:
            coord_y = self.__selected_y
        num_images = self.__associated_data_collection.acquisitions[0].\
                          acquisition_parameters.num_images
        osc_start = self.__associated_data_collection.acquisitions[0].\
                         acquisition_parameters.osc_start
        osc_range = self.__associated_data_collection.acquisitions[0].\
                         acquisition_parameters.osc_range

        omega = None
        if self.__is_map_plot:
            self.__associated_grid.set_osc_range(osc_range)
            motor_pos_dict = self.__associated_grid.\
                 get_motor_pos_from_col_row(coord_x, coord_y)
        else:
            omega = osc_start + osc_range * float(coord_x) / num_images
            (point_one, point_two) = self.__associated_data_collection.\
                      get_centred_positions()
            motor_pos_dict = self._beamline_setup_hwobj.diffractometer_hwobj.\
                      get_point_from_line(point_one, point_two, coord_x, num_images)

        motor_pos_dict['phi'] = omega
        self._beamline_setup_hwobj.shape_history_hwobj.\
             create_centring_point(True, {"motors": motor_pos_dict})

    def move_to_selected_position(self):
        """
        Descript. : Moves to grid position
        Args.     : x and y are positions in micrometers starting from left 
                    top corner (as graphical coordinates)
        """
        osc_start = self.__associated_data_collection.acquisitions[0].\
                         acquisition_parameters.osc_start
        osc_range = self.__associated_data_collection.acquisitions[0].\
                         acquisition_parameters.osc_range
        if self.__is_map_plot:
            self.__associated_grid.set_osc_range(osc_range)
            motor_pos_dict = self.__associated_grid.\
                 get_motor_pos_from_col_row(self.__selected_x, self.__selected_y)
        else:
            num_images = self.__associated_data_collection.\
                      acquisitions[0].acquisition_parameters.num_images - 1
            (point_one, point_two) = self.__associated_data_collection.\
                      get_centred_positions()
            motor_pos_dict = self._beamline_setup_hwobj.diffractometer_hwobj.\
                      get_point_from_line(point_one, point_two,
                      int(self.__selected_x), num_images)

        self._beamline_setup_hwobj.diffractometer_hwobj.\
             move_to_motors_positions(motor_pos_dict)

    def set_best_pos(self):
        """
        Descript. : Displays 10 (if exists) best positions, estimated
                    by fast processing.
        """
        self._best_pos_table.setRowCount(len(self.__results["best_positions"]))
        for row in range(len(self.__results["best_positions"])):
            self._best_pos_table.setItem(row, 0, QtGui.QTableWidgetItem(\
                 str(self.__results["best_positions"][row].get("index") + 1)))
            self._best_pos_table.setItem(row, 1, QtGui.QTableWidgetItem(\
                 str(self.__results["best_positions"][row].get("score"))))
            self._best_pos_table.setItem(row, 2, QtGui.QTableWidgetItem(\
                 str(self.__results["best_positions"][row].get("spots_num"))))
            self._best_pos_table.setItem(row, 3, QtGui.QTableWidgetItem(\
                 str(self.__results["best_positions"][row].get("spots_int_aver"))))
            self._best_pos_table.setItem(row, 4, QtGui.QTableWidgetItem(\
                 str(self.__results["best_positions"][row].get("spots_resolution"))))
            self._best_pos_table.setItem(row, 5, QtGui.QTableWidgetItem(\
                 str(self.__results["best_positions"][row].get("filename"))))
            self._best_pos_table.setItem(row, 6, QtGui.QTableWidgetItem(\
                 str(self.__results["best_positions"][row].get("col"))))
            self._best_pos_table.setItem(row, 7, QtGui.QTableWidgetItem(\
                 str(self.__results["best_positions"][row].get("row"))))
            if self.__results["best_positions"][row]["cpos"]:
                self._best_pos_table.setItem(row, 8, QtGui.QTableWidgetItem(\
                   self.__results["best_positions"][row]["cpos"].as_str()))
        self._best_pos_table.setSortingEnabled(True)

    def move_to_best_position_clicked(self):
        if self._best_pos_table.currentRow() > -1:
            self._beamline_setup_hwobj.diffractometer_hwobj.\
                move_to_motors_positions(self.__results["best_positions"]\
                [self._best_pos_table.currentRow()].get("cpos").as_dict())

    def create_best_centring_point_clicked(self):
        if self._best_pos_table.currentRow() > -1:
            self._beamline_setup_hwobj.diffractometer_hwobj.\
                create_centring_point(self.__results["best_positions"]\
                [self._best_pos_table.currentRow()].get("cpos").as_dict())

    def display_best_image_clicked(self):
        if self._best_pos_table.currentRow() > -1:
            image_path = self.__results["best_positions"]\
               [self._best_pos_table.currentRow()].get("filename")
            self._beamline_setup_hwobj.image_tracking_hwobj.\
               load_image(image_path)
class HeatMapWidget(QWidget):
    def __init__(self, parent=None, allow_adjust_size=True):
        QWidget.__init__(self, parent)
        self.setObjectName('heat_map_widget')
        self.allow_adjust_size = allow_adjust_size

        # Properties ----------------------------------------------------------

        # Signals -------------------------------------------------------------

        # Slots ---------------------------------------------------------------

        # Hardware objects ----------------------------------------------------
        self._beamline_setup_hwobj = None

        # Internal values -----------------------------------------------------
        self.__results = None
        self.__results_display = None
        self.__associated_grid = None
        self.__associated_data_collection = None
        self.__selected_x = 0
        self.__selected_y = 0
        self.__selected_image_serial = 0
        self.__score_key = "score"
        self.__max_value = 0
        self.__filter_min_value = 0
        self.__best_pos_list = None
        self.__label_im = None
        self.__heat_map_max_size = []
        self.__heatmap_clicked = False
        self.__enable_continues_image_display = True
        self.__tooltip_text = None

        # Graphic elements ----------------------------------------------------
        self._heat_map_gbox = QGroupBox('Heat map', self)
        self._heat_map_plot = TwoDimenisonalPlotWidget(self)
        self._heat_map_popup_menu = QMenu(self._heat_map_gbox)

        heat_map_info_widget = QWidget(self._heat_map_gbox)
        score_type_label = QLabel("Score type: ", heat_map_info_widget)
        self._score_type_cbox = QComboBox(heat_map_info_widget)
        self._image_info_label = QLabel("Image: #, value #",
                                        heat_map_info_widget)

        self._heat_map_tools_widget = QWidget(self._heat_map_gbox)

        _threshold_label = QLabel("Threshold: ", self._heat_map_tools_widget)
        self._threshold_slider = QSlider(Qt.Horizontal,
                                         self._heat_map_tools_widget)
        self._relaunch_processing_button = QPushButton(
            "Relaunch processing", self._heat_map_tools_widget)
        self._create_points_button = QPushButton("Create centring points",
                                                 self._heat_map_tools_widget)

        self._summary_gbox = QGroupBox("Summary", self)
        self._summary_textbrowser = QTextBrowser(self._summary_gbox)
        self._best_pos_gbox = QGroupBox("Best positions", self)
        self._best_pos_table = QTableWidget(self._best_pos_gbox)
        self._best_pos_popup_menu = QMenu(self._heat_map_gbox)
        self._best_pos_gbox.setHidden(True)

        # Layout --------------------------------------------------------------
        _heat_map_info_hlayout = QHBoxLayout(heat_map_info_widget)
        _heat_map_info_hlayout.addWidget(score_type_label)
        _heat_map_info_hlayout.addWidget(self._score_type_cbox)
        _heat_map_info_hlayout.addStretch(0)
        _heat_map_info_hlayout.addWidget(self._image_info_label)
        _heat_map_info_hlayout.setSpacing(2)
        _heat_map_info_hlayout.setContentsMargins(0, 0, 0, 0)

        _heat_map_tools_hlayout = QHBoxLayout(self._heat_map_tools_widget)
        _heat_map_tools_hlayout.addWidget(_threshold_label)
        _heat_map_tools_hlayout.addWidget(self._threshold_slider)
        _heat_map_tools_hlayout.addStretch(0)
        _heat_map_tools_hlayout.addWidget(self._relaunch_processing_button)
        _heat_map_tools_hlayout.addWidget(self._create_points_button)
        _heat_map_tools_hlayout.setSpacing(2)
        _heat_map_tools_hlayout.setContentsMargins(0, 0, 0, 0)

        _heat_map_gbox_vlayout = QVBoxLayout(self._heat_map_gbox)
        _heat_map_gbox_vlayout.addWidget(self._heat_map_plot)
        _heat_map_gbox_vlayout.addWidget(heat_map_info_widget)
        _heat_map_gbox_vlayout.addWidget(self._heat_map_tools_widget)
        _heat_map_gbox_vlayout.setSpacing(2)
        _heat_map_gbox_vlayout.setContentsMargins(0, 0, 0, 0)

        _summary_gbox_vlayout = QVBoxLayout(self._summary_gbox)
        _summary_gbox_vlayout.addWidget(self._summary_textbrowser)
        _summary_gbox_vlayout.setSpacing(2)
        _summary_gbox_vlayout.setContentsMargins(0, 0, 0, 0)

        _best_postition_gbox_vlayout = QVBoxLayout(self._best_pos_gbox)
        _best_postition_gbox_vlayout.addWidget(self._best_pos_table)
        _best_postition_gbox_vlayout.setSpacing(2)
        _best_postition_gbox_vlayout.setContentsMargins(0, 0, 0, 0)

        _main_hlayout = QVBoxLayout(self)
        _main_hlayout.addWidget(self._heat_map_gbox)
        _main_hlayout.addWidget(self._summary_gbox)
        _main_hlayout.addWidget(self._best_pos_gbox)
        _main_hlayout.setSpacing(2)
        _main_hlayout.setContentsMargins(2, 2, 2, 2)

        # SizePolicies --------------------------------------------------------
        self._image_info_label.setAlignment(Qt.AlignLeft)
        self._image_info_label.setSizePolicy(QSizePolicy.Expanding,
                                             QSizePolicy.Fixed)

        # Qt signals and slots ------------------------------------------------
        self._score_type_cbox.activated.connect(self.score_type_changed)
        self._threshold_slider.valueChanged.\
             connect(self.filter_min_slider_changed)
        self._relaunch_processing_button.clicked.\
             connect(self.relaunch_processing_clicked)
        self._create_points_button.clicked.\
             connect(self.create_points_clicked)
        self._heat_map_plot.mouseMovedSignal.\
             connect(self.mouse_moved)
        self._heat_map_plot.mouseClickedSignal.\
             connect(self.mouse_clicked)
        self._heat_map_plot.mouseDoubleClickedSignal.\
             connect(self.move_to_position_clicked)
        self._heat_map_plot.mouseLeftSignal.connect(\
             self.mouse_left_plot)

        # Other ---------------------------------------------------------------
        self.__tooltip_text = "Double click to move to the position. " + \
                              "Right click to open menu."
        self._heat_map_plot.setToolTip(self.__tooltip_text)
        self._heat_map_popup_menu.addSeparator()
        self._heat_map_popup_menu.addAction(\
             "Move to position",
             self.move_to_position_clicked)
        self._heat_map_popup_menu.addAction(\
             "Create centring point",
             self.create_centring_point_clicked)

        self._heat_map_popup_menu.addAction(\
             "Create helical line",
             self.create_helical_line_clicked)
        self._heat_map_popup_menu.addAction(\
             "Rotate 90 degrees and create helical line",
             self.rotate_and_create_helical_line_clicked)

        self._heat_map_popup_menu.addSeparator()
        self._heat_map_popup_menu.addAction(\
             "Open image in ADXV", self.display_image_clicked)
        self.continues_display_action = \
             self._heat_map_popup_menu.addAction(\
             "Continues image display in ADXV",
              self.toogle_continues_image_display)
        self.continues_display_action.setCheckable(True)
        self.continues_display_action.setChecked(True)

        self._heat_map_popup_menu.addSeparator()
        options_menu = self._heat_map_popup_menu.addMenu("Options")

        self._heat_map_plot.contextMenuEvent = self.open_heat_map_popup_menu

        score_types = ["Resolution", "Score", "Spots num"]
        for score_type in score_types:
            self._score_type_cbox.addItem(score_type)
        self._score_type_cbox.setMaximumWidth(200)
        self.__score_key = "spots_resolution"

        #self._threshold_slider.setTickmarks(QtGui.QSlider.Below)
        self._threshold_slider.setRange(0, 100)
        self._threshold_slider.setTickInterval(5)
        self._threshold_slider.setFixedWidth(200)
        self._threshold_slider.setTracking(False)

        font = self._best_pos_table.font()
        font.setPointSize(8)
        self._best_pos_table.setFont(font)
        self._best_pos_table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self._best_pos_table.setColumnCount(9)
        self._best_pos_table.setAlternatingRowColors(True)
        self._best_pos_table.setWordWrap(False)
        self._best_pos_table.horizontalHeader().setSortIndicatorShown(True)
        self._best_pos_table.setHorizontalHeaderItem(0, \
            QTableWidgetItem("No."))
        for score_type in enumerate(score_types):
            self._best_pos_table.setHorizontalHeaderItem(\
                 score_type[0] + 1, QTableWidgetItem(score_type[1]))

        self._best_pos_table.setHorizontalHeaderItem(5,
                                                     QTableWidgetItem("Path"))
        self._best_pos_table.setHorizontalHeaderItem(6,
                                                     QTableWidgetItem("Col"))
        self._best_pos_table.setHorizontalHeaderItem(7,
                                                     QTableWidgetItem("Row"))
        self._best_pos_table.setHorizontalHeaderItem(
            8, QTableWidgetItem("Motor positions"))

        self._best_pos_popup_menu.addAction(\
             "Move to position",
              self.move_to_best_position_clicked)
        self._best_pos_table.contextMenuEvent = self.open_best_pos_popup_menu
        #self._best_pos_table.setHidden(True)

        screenShape = QDesktopWidget().screenGeometry()
        self.__heat_map_max_size = (screenShape.width() / 2,
                                    screenShape.height() / 2)

    def set_beamline_setup(self, beamline_setup_hwobj):
        self._beamline_setup_hwobj = beamline_setup_hwobj

    def set_associated_data_collection(self, data_collection):
        self.__associated_data_collection = data_collection
        self.__associated_grid = self.__associated_data_collection.grid
        acq_parameters = self.__associated_data_collection.acquisitions[0].\
                    acquisition_parameters

        if not data_collection.is_mesh():
            #x_array = numpy.linspace(0, acq_parameters.num_images, acq_parameters.num_images, dtype="int16")
            x_array = numpy.array([])
            y_array = numpy.array([])

            self._heat_map_plot.add_curve("spots_resolution",
                                          y_array,
                                          x_array,
                                          linestyle="None",
                                          label="Resolution",
                                          color="m",
                                          marker=".")
            self._heat_map_plot.add_curve("score",
                                          y_array,
                                          x_array,
                                          label="Total score",
                                          linestyle="None",
                                          color="b",
                                          marker=".")
            self._heat_map_plot.add_curve("spots_num",
                                          y_array,
                                          x_array,
                                          label="Number of spots",
                                          linestyle="None",
                                          color="b",
                                          marker=".")
            self._heat_map_plot.hide_all_curves()
            self._heat_map_plot.show_curve(self.__score_key)

            self.adjust_axes()
        else:
            if self.allow_adjust_size:
                grid_size = self.__associated_grid.get_size_pix()

                width = grid_size[0] * 5
                height = grid_size[1] * 5
                ratio = float(width) / height

                if width > self.__heat_map_max_size[0]:
                    width = self.__heat_map_max_size[0]
                    height = width / ratio
                if height > self.__heat_map_max_size[1]:
                    height = self.__heat_map_max_size[1]
                    width = height * ratio

                self._heat_map_plot.setFixedWidth(width)
                self._heat_map_plot.setFixedHeight(height)

            axis_range = self.__associated_grid.get_col_row_num()
            self._heat_map_plot.set_y_axis_limits((0, axis_range[1]))
            self._heat_map_plot.set_x_axis_limits((0, axis_range[0]))

            self._summary_textbrowser.append("<b>Mesh parameters</b>")
            grid_params = self.__associated_grid.get_properties()

            empty_array = numpy.zeros(acq_parameters.num_images).\
                reshape(grid_params["steps_x"], grid_params["steps_y"])

            self._heat_map_plot.plot_result(numpy.transpose(empty_array))

    def main_gbox_toggled(self, toggle):
        self._heat_map_plot.setHidden(not toggle)
        self._heat_map_tools_widget.setHidden(not toggle)

    def open_heat_map_popup_menu(self, context_event):
        point = QPoint(context_event.globalX(), context_event.globalY())
        self._heat_map_popup_menu.popup(point)

    def open_best_pos_popup_menu(self, context_event):
        if self._best_pos_table.rowCount() > 0:
            point = QPoint(context_event.globalX(), context_event.globalY())
            self._best_pos_popup_menu.popup(point)

    def score_type_changed(self, score_type_index):
        if score_type_index == 0:
            self.__score_key = "spots_resolution"
        elif score_type_index == 1:
            self.__score_key = "score"
        elif score_type_index == 2:
            self.__score_key = "spots_num"

        if self.__results is not None:
            if self.__results[self.__score_key].ndim == 1:
                self._heat_map_plot.hide_all_curves()
                self._heat_map_plot.show_curve(self.__score_key)
                self.adjust_axes()
            else:
                self._heat_map_plot.plot_result(
                    numpy.transpose(self.__results[self.__score_key]))

    def adjust_axes(self):
        #self._summary_textbrowser.clear()

        if self.__results:
            if self.__results[self.__score_key].ndim == 1:
                self._heat_map_plot.adjust_axes(self.__score_key)

                labels = []
                positions = numpy.linspace(
                    0, self.__results[self.__score_key].max(), 5)

                if self.__score_key == "spots_resolution":
                    labels.append('inf')
                    for item in positions[1:]:
                        labels.append("%.2f" % (1. / item))
                else:
                    for item in positions:
                        labels.append("%d" % item)

                self._heat_map_plot.set_yticks(positions)
                self._heat_map_plot.set_ytick_labels(labels)

    def filter_min_slider_changed(self, value):
        self.__results_display = deepcopy(self.__results)

        for key in self.__results_display.keys():
            if key != "best_positions":
                filter_value = self.__results_display[key].max(
                ) * value / 100.0
                self.__results_display[key][
                    self.__results_display[key] < filter_value] = 0

        if self.__results_display[self.__score_key].ndim == 1:
            self._heat_map_plot.update_curves(self.__results_display)
            self.adjust_axes()
        else:
            self._heat_map_plot.plot_result(
                numpy.transpose(self.__results_display[self.__score_key]))

    def mouse_moved(self, pos_x, pos_y):
        if self.__enable_continues_image_display and \
           self.__heatmap_clicked:
            if abs(int(self.__selected_x) - int(pos_x)) >= 1 or \
               abs(int(self.__selected_y) - int(pos_y)) >= 1:
                self.__selected_x = pos_x
                self.__selected_y = pos_y
                self.display_image_clicked()
                self.display_image_tooltip()

    def mouse_clicked(self, pos_x, pos_y):
        self.__heatmap_clicked = True
        self.__selected_x = pos_x
        self.__selected_y = pos_y

        if self.__associated_data_collection:
            msg = ""
            if self.__associated_grid:
                image, line, self.selected_image_serial, image_path = \
                      self.get_image_parameters_from_coord()
                col, row = self.get_col_row_from_image_line(line, image)
                if self.__results:
                    msg = "Image: %d, value: %.1f" % (
                        self.selected_image_serial,
                        self.__results[self.__score_key][col][row])
                else:
                    msg = "Image: %d" % self.selected_image_serial

                label_im = deepcopy(self.__label_im)
                label_im[label_im != label_im[col, row]] = 0
            else:
                msg = "Image: %d" % int(pos_x)
            self._image_info_label.setText(msg)

    def plot_double_clicked(self, event):
        self.move_to_selected_position()

    def mouse_left_plot(self):
        self.__heatmap_clicked = False
        self._heat_map_plot.setToolTip(self.__tooltip_text)

    def move_to_position_clicked(self):
        self.move_to_selected_position()

    def set_results(self, results, last_results=False):
        """
        Displays results on the widget
        """
        self.__results = results
        #self.__results_display = results

        if self.__results[self.__score_key].ndim == 1:
            self._heat_map_plot.update_curves(results)
            self.adjust_axes()
        else:
            self._heat_map_plot.plot_result(
                numpy.transpose(results[self.__score_key]))

        if last_results:
            self.__label_im, nb_labels = ndimage.label(
                self.__results['score'] > 0)
        #self.set_best_pos()

    def clean_result(self):
        """
        Method to clean heat map, summary log and table with best positions
        """
        #self.setEnabled(False)
        self.__results = None
        self.__associated_grid = None
        self.__associated_data_collection = None
        self._heat_map_plot.clear()
        self._threshold_slider.setValue(0)
        self._summary_textbrowser.clear()
        self._best_pos_table.setRowCount(0)
        self._best_pos_table.setSortingEnabled(False)

    def create_centring_point_clicked(self):
        """
        Creates a centring point based on the location on the location
        on heat map.
        """
        self.create_centring_point()

    def create_points_clicked(self):
        """
        Creates new centring points based on each image score.
        All images are checked and if the value is over the threshold
         then screen x and y coordinates are estimated.
        """
        if self.__results[self.__score_key].ndim == 1:
            for col in range(self.__result.shape[0]):
                if self.__result[col] > 0:
                    self.create_centring_point(col + 0.5)
        else:
            #result_display = numpy.transpose(self.__result_display[self.__score_key])
            result_display = self.__results[self.__score_key]
            #step_x = pix_width / self.__result_display.shape[0]
            #step_y = pix_height / self.__result_display.shape[1]
            for col in range(result_display.shape[0]):
                for row in range(result_display.shape[1]):
                    if result_display[col][row] > 0:
                        #MD2
                        row = result_display.shape[1] - row - 1
                        self.create_centring_point(col + 0.5, row + 0.5)
        self._beamline_setup_hwobj.shape_history_hwobj.select_all_points()

    def display_image_clicked(self):
        """
        Displays image in image tracker (by default adxv)
        """
        image, line, image_num, image_path = self.get_image_parameters_from_coord(
        )
        try:
            self._beamline_setup_hwobj.image_tracking_hwobj.load_image(
                image_path)
        except:
            pass

    def display_image_tooltip(self):
        image, line, self.selected_image_serial, image_path = \
              self.get_image_parameters_from_coord()
        tooltip_text = "Image no. %d" % self.selected_image_serial
        if self.__results is not None:
            try:
                col, row = self.get_col_row_from_image_line(line, image)
                tooltip_text += "\nTotal score: %.1f" %  \
                                self.__results['score'][col][row] +\
                                "\nNumber of spots: %d" % \
                                self.__results['spots_num'][col][row]
            except:
                pass
        self._heat_map_plot.setToolTip(tooltip_text)

    def toogle_continues_image_display(self):
        self.__enable_continues_image_display = \
            self.continues_display_action.isChecked()

    def get_image_parameters_from_coord(self, coord_x=None, coord_y=None):
        """
        returns image parameters for selected heat map frame
        """
        if not coord_x:
            coord_x = self.__selected_x
        if not coord_y:
            coord_y = self.__selected_y

        if self.__associated_grid:
            num_cols, num_rows = self.__associated_grid.get_col_row_num()
            if coord_x > num_cols:
                coord_x = num_cols
            if coord_y > num_rows:
                coord_y = num_rows

            image, line, image_num = self.__associated_grid.\
                  get_image_from_col_row(coord_x, coord_y)
        else:
            image = int(self.__selected_x)
            line = 1
            image_num = image + self.__associated_data_collection.\
                  acquisitions[0].acquisition_parameters.first_image
        image_path = self.__associated_data_collection.acquisitions[0].\
                      path_template.get_image_path()
        image_path = image_path % image_num
        return image, line, image_num, image_path

    def get_col_row_from_image_line(self, line, image):
        """
        Returns col and row from image and line
        """
        col, row = self.__associated_grid.get_col_row_from_line_image(
            line, image)
        ## TODO check if next line needs to be removed
        row = self.__results[self.__score_key].shape[1] - row - 1
        return col, row

    def create_centring_point(self, coord_x=None, coord_y=None):
        """
        Descript. : creates a new centring point for selected coordinate.
                    For mesh scan coord_x, and coord_y are grid coordinates in microns
                    For helical line coord_x represents frame number
        """
        if coord_x is None:
            coord_x = self.__selected_x
        if coord_y is None:
            coord_y = self.__selected_y
        num_images = self.__associated_data_collection.acquisitions[0].\
                          acquisition_parameters.num_images
        osc_start = self.__associated_data_collection.acquisitions[0].\
                         acquisition_parameters.osc_start
        osc_range = self.__associated_data_collection.acquisitions[0].\
                         acquisition_parameters.osc_range

        omega = None
        if self.__associated_grid:
            self.__associated_grid.set_osc_range(osc_range)
            motor_pos_dict = self.__associated_grid.\
                 get_motor_pos_from_col_row(coord_x, coord_y)
        else:
            omega = osc_start + osc_range * float(coord_x) / num_images
            (point_one, point_two) = self.__associated_data_collection.\
                      get_centred_positions()
            motor_pos_dict = self._beamline_setup_hwobj.diffractometer_hwobj.\
                      get_point_from_line(point_one, point_two, coord_x, num_images)
            motor_pos_dict['phi'] = omega
        self._beamline_setup_hwobj.shape_history_hwobj.\
             create_centring_point(True, {"motors": motor_pos_dict})

    def create_helical_line_clicked(self):
        motor_pos_dict = self.__associated_grid.\
              get_motor_pos_from_col_row(self.__selected_x, self.__selected_y)
        self._beamline_setup_hwobj.shape_history_hwobj.create_auto_line(
            motor_pos_dict)

    def rotate_and_create_helical_line_clicked(self):
        self.move_to_selected_position()
        self._beamline_setup_hwobj.diffractometer_hwobj.move_omega_relative(90)
        self._beamline_setup_hwobj.shape_history_hwobj.create_auto_line()

    def move_to_selected_position(self):
        """
        Descript. : Moves to grid position
        Args.     : x and y are positions in micrometers starting from left 
                    top corner (as graphical coordinates)
        """
        osc_start = self.__associated_data_collection.acquisitions[0].\
                         acquisition_parameters.osc_start
        osc_range = self.__associated_data_collection.acquisitions[0].\
                         acquisition_parameters.osc_range
        if self.__associated_grid:
            self.__associated_grid.set_osc_range(osc_range)
            motor_pos_dict = self.__associated_grid.\
                 get_motor_pos_from_col_row(self.__selected_x, self.__selected_y)
        else:
            num_images = self.__associated_data_collection.\
                      acquisitions[0].acquisition_parameters.num_images - 1
            (point_one, point_two) = self.__associated_data_collection.\
                      get_centred_positions()
            motor_pos_dict = self._beamline_setup_hwobj.diffractometer_hwobj.\
                      get_point_from_line(point_one, point_two,
                      int(self.__selected_x), num_images)

        self._beamline_setup_hwobj.diffractometer_hwobj.\
             move_to_motors_positions(motor_pos_dict, wait=True)

    def set_best_pos(self):
        """
        Descript. : Displays 10 (if exists) best positions, estimated
                    by fast processing.
        """
        self._best_pos_table.setRowCount(
            len(self.__results.get("best_positions", [])))
        for row, best_pos in enumerate(self.__results.get(
                "best_positions", [])):
            self._best_pos_table.setItem(row, 0, QTableWidgetItem("%d" \
                 % (best_pos.get("index") + 1)))
            self._best_pos_table.setItem(row, 1, QTableWidgetItem("%.2f"\
                 % (best_pos.get("score"))))
            self._best_pos_table.setItem(row, 2, QTableWidgetItem("%d"\
                 % (best_pos.get("spots_num"))))
            self._best_pos_table.setItem(row, 3, QTableWidgetItem("%.2f"\
                 % (best_pos.get("spots_int_aver"))))
            self._best_pos_table.setItem(row, 4, QTableWidgetItem("%.2f"\
                 % (best_pos.get("spots_resolution"))))
            self._best_pos_table.setItem(row, 5, QTableWidgetItem(\
                 str(best_pos.get("filename"))))
            self._best_pos_table.setItem(row, 6, QTableWidgetItem("%d" \
                 % (best_pos.get("col"))))
            self._best_pos_table.setItem(row, 7, QTableWidgetItem("%d"\
                 % (best_pos.get("row"))))
            if best_pos["cpos"]:
                self._best_pos_table.setItem(row, 8, QTableWidgetItem(\
                 str(best_pos["cpos"])))
        self._best_pos_table.setSortingEnabled(True)

    def move_to_best_position_clicked(self):
        """
        Moves diffractometer motors to the selected position
        """
        if self._best_pos_table.currentRow() > -1:
            self._beamline_setup_hwobj.diffractometer_hwobj.\
                move_to_motors_positions(self.__results["best_positions"]\
                [self._best_pos_table.currentRow()]["cpos"])

    def create_best_centring_point_clicked(self):
        """
        Creates a new centring point based on the selected point
        from the table of best positions.
        """
        if self._best_pos_table.currentRow() > -1:
            self._beamline_setup_hwobj.diffractometer_hwobj.\
                create_centring_point(self.__results["best_positions"]\
                [self._best_pos_table.currentRow()].get("cpos").as_dict())

    def display_best_image_clicked(self):
        """
        Displays image (clicked from best position table) in ADXV
        """
        if self._best_pos_table.currentRow() > -1:
            image_path = self.__results["best_positions"]\
               [self._best_pos_table.currentRow()].get("filename")
            self._beamline_setup_hwobj.image_tracking_hwobj.\
               load_image(image_path)

    def relaunch_processing_clicked(self):
        """
        Relaunches parallel processing
        """
        if self.__associated_data_collection and self.__associated_grid:
            self._beamline_setup_hwobj.parallel_processing_hwobj.\
                 run_processing(self.__associated_data_collection)
Beispiel #4
0
class HeatMapWidget(QtGui.QWidget):
    def __init__(self, parent = None):
        QtGui.QWidget.__init__(self, parent)
        self.setObjectName('heat_map_widget')

        # Properties ---------------------------------------------------------- 
        #self.__half_widget_size = 900

        # Signals -------------------------------------------------------------

        # Slots ---------------------------------------------------------------

        # Hardware objects ----------------------------------------------------
        self._beamline_setup_hwobj = None
        self._data_analysis_hwobj = None

        # Internal values -----------------------------------------------------
        self.__results = None
        self.__result_display = None
        self.__associated_grid = None
        self.__associated_data_collection = None
        self.__selected_x = 0
        self.__selected_y = 0
        self.__selected_image_serial = 0
        #self.__axis_x_range = None
        #self.__axis_y_range = None
        self.__is_map_plot = None
        self.__score_type_index = 0
        self.__max_value = 0
        self.__filter_min_value = 0
        self.__best_pos_list = None
        self.__heat_map_max_size = []

        # Graphic elements ----------------------------------------------------
        self._heat_map_gbox = QtGui.QGroupBox('Heat map', self)
        #self._heat_map_plot = QtBlissGraph(self._heat_map_gbox)
        self._heat_map_plot = TwoDimenisonalPlotWidget(self)
        self._heat_map_popup_menu = QtGui.QMenu(self._heat_map_gbox)
        self._image_info_label = QtGui.QLabel("Image: #, value #", self._heat_map_gbox)

        self._heat_map_tools_widget = QtGui.QWidget(self._heat_map_gbox)
        score_type_label = QtGui.QLabel("Score type: ", self._heat_map_tools_widget)
        self._score_type_cbox = QtGui.QComboBox(self._heat_map_tools_widget)

        _threshold_label = QtGui.QLabel("Threshold: ", self._heat_map_tools_widget)
        self._threshold_slider = QtGui.QSlider(QtCore.Qt.Horizontal, 
               self._heat_map_tools_widget)
        self._create_points_button = QtGui.QPushButton("Create centring points", 
             self._heat_map_tools_widget)

        self._best_pos_gbox = QtGui.QGroupBox("Best positions", self)
        self._best_pos_table = QtGui.QTableWidget(self._best_pos_gbox)

        # Layout --------------------------------------------------------------
        _heat_map_tools_hlayout = QtGui.QHBoxLayout(self._heat_map_tools_widget)
        _heat_map_tools_hlayout.addWidget(score_type_label)
        _heat_map_tools_hlayout.addWidget(self._score_type_cbox)
        _heat_map_tools_hlayout.addWidget(_threshold_label)
        _heat_map_tools_hlayout.addWidget(self._threshold_slider)
        _heat_map_tools_hlayout.addStretch(0)
        _heat_map_tools_hlayout.addWidget(self._create_points_button)
        _heat_map_tools_hlayout.setSpacing(2)
        _heat_map_tools_hlayout.setContentsMargins(0, 0, 0, 0)

        _heat_map_gbox_vlayout = QtGui.QVBoxLayout(self._heat_map_gbox)
        _heat_map_gbox_vlayout.addWidget(self._heat_map_plot)
        _heat_map_gbox_vlayout.addWidget(self._image_info_label)
        _heat_map_gbox_vlayout.addWidget(self._heat_map_tools_widget)
        _heat_map_gbox_vlayout.setSpacing(2)
        _heat_map_gbox_vlayout.setContentsMargins(0, 4, 0, 0)
        
        _best_postition_gbox_vlayout = QtGui.QVBoxLayout(self._best_pos_gbox)
        _best_postition_gbox_vlayout.addWidget(self._best_pos_table)
        _best_postition_gbox_vlayout.setSpacing(2)
        _best_postition_gbox_vlayout.setContentsMargins(0, 4, 0, 0)

        _main_hlayout = QtGui.QVBoxLayout(self)
        _main_hlayout.addWidget(self._heat_map_gbox)
        _main_hlayout.addWidget(self._best_pos_gbox)
        _main_hlayout.setSpacing(2)
        _main_hlayout.setContentsMargins(0, 0, 0, 0)

        # SizePolicies --------------------------------------------------------
        self._image_info_label.setAlignment(QtCore.Qt.AlignRight)
        self._image_info_label.setSizePolicy(QtGui.QSizePolicy.Expanding, 
                                             QtGui.QSizePolicy.Fixed)

        # Qt signal/slot connections ------------------------------------------
        self._heat_map_plot.mouseClickedSignal.connect(self.mouse_clicked)
        self._score_type_cbox.activated.connect(self.score_type_changed)
        self._threshold_slider.valueChanged.connect(\
             self.filter_min_slider_changed)
        self._create_points_button.clicked.connect(\
             self.create_points_clicked)

        # Other ----------------------------------------------------------------
        #self._heat_map_plot.canvas().setMouseTracking(False)
        #Qt4_widget_colors.set_widget_color(self._heat_map_plot, QtCore.Qt.white)
        #self._heat_map_plot.mouseDoubleClickEvent = self.plot_double_clicked
        #self._heat_map_plot.setAxisAutoScale(False)
        #self._heat_map_plot.enableZoom(True)
        #self._heat_map_plot.showGrid()
        tooltip_text = "Double click to move to the position. " + \
                       "Right click to open menu."
        self._heat_map_plot.setToolTip(tooltip_text) 

        #self._heat_map_popup_menu.addAction(\
        #     "Reset zoom", self._heat_map_plot.zoomReset)
        self._heat_map_popup_menu.addSeparator()
        self._heat_map_popup_menu.addAction(\
             "Move to position", self.move_to_position_clicked)
        self._heat_map_popup_menu.addAction(\
             "Create centring point", self.create_centring_point_clicked)
        self._heat_map_popup_menu.addSeparator()
        self._heat_map_popup_menu.addAction(\
             "Open image in ADXV", self.display_image_clicked)
        self._heat_map_plot.contextMenuEvent = self.open_heat_map_popup_menu

        score_types = ["Score", "Spots num", "Int aver.", "Resolution"]
        for score_type in score_types:
            self._score_type_cbox.addItem(score_type)
        self._score_type_cbox.setMaximumWidth(200)

        #self._threshold_slider.setTickmarks(QtGui.QSlider.Below)
        self._threshold_slider.setRange(0, 100)
        self._threshold_slider.setTickInterval(5)
        self._threshold_slider.setFixedWidth(200)
        self._threshold_slider.setTracking(False)

        font = self._best_pos_table.font()
        font.setPointSize(8)
        self._best_pos_table.setFont(font)
        self._best_pos_table.setEditTriggers(\
             QtGui.QAbstractItemView.NoEditTriggers)
        self._best_pos_table.setColumnCount(9)
        self._best_pos_table.horizontalHeader().setStretchLastSection(True)
     
        self._best_pos_table.setHorizontalHeaderItem(0, \
            QtGui.QTableWidgetItem("No."))
        for score_type in enumerate(score_types):
            self._best_pos_table.setHorizontalHeaderItem(\
                 score_type[0] + 1, QtGui.QTableWidgetItem(score_type[1]))

        self._best_pos_table.setHorizontalHeaderItem(5,
             QtGui.QTableWidgetItem("Path"))
        self._best_pos_table.setHorizontalHeaderItem(6,
             QtGui.QTableWidgetItem("Col"))
        self._best_pos_table.setHorizontalHeaderItem(7,
             QtGui.QTableWidgetItem("Row"))
        self._best_pos_table.setHorizontalHeaderItem(8,
             QtGui.QTableWidgetItem("Motor positions"))

        screenShape = QtGui.QDesktopWidget().screenGeometry()
        self.__heat_map_max_size = (screenShape.width() / 2 - 200,
                                    screenShape.height() / 2)

    def set_beamline_setup(self, beamline_setup_hwobj):
        self._beamline_setup_hwobj = beamline_setup_hwobj
        self._data_analysis_hwobj = self._beamline_setup_hwobj.data_analysis_hwobj 

    def set_associated_data_collection(self, data_collection):
        self.__associated_data_collection = data_collection
        
        #self._heat_map_plot.set_x_axis_limits((- 0.5, data_collection.\
        #      acquisitions[0].acquisition_parameters.num_images - 0.5))

    def set_associated_grid(self, grid):
        if grid is None:
            self.__is_map_plot = False
            #self._heat_map_plot.x1Label("Image num")
            #self._heat_map_plot.y1Label("Score")
        else:
            self.__is_map_plot = True
            self.__associated_grid = grid
            axis_range = self.__associated_grid.get_col_row_num()
            grid_size = self.__associated_grid.get_size_pix()

            width = grid_size[0] * 5
            height = grid_size[1] * 5
            ratio = float(width) / height

            if width > self.__heat_map_max_size[0]:
                width = self.__heat_map_max_size[0]
                height = width / ratio
            if height > self.__heat_map_max_size[1]:
                height = self.__heat_map_max_size[1]
                width = height * ratio

            #self._heat_map_plot.setFixedWidth(width)
            #self._heat_map_plot.setFixedHeight(height)

            #axis_range = self.__associated_grid.get_col_row_num()
            #self._heat_map_plot.set_x_axis_limits((- 0.5, axis_range[0] - 0.5))
            #self._heat_map_plot.set_y_axis_limits((- 0.5, axis_range[1] - 0.5))

    def main_gbox_toggled(self, toggle):
        self._heat_map_plot.setHidden(not toggle)
        self._heat_map_tools_widget.setHidden(not toggle)
            
    def open_heat_map_popup_menu(self, context_event):
        point = QtCore.QPoint(context_event.globalX(), 
                          context_event.globalY())
        self._heat_map_popup_menu.popup(point)

    def open_best_pos_popup_menu(self, context_event):
        point = QtCore.QPoint(context_event.globalX(), 
                          context_event.globalY())
        self._best_pos_popup_menu.popup(point)  

    def score_type_changed(self, score_type_index):
        self.__score_type_index = score_type_index
        #self._threshold_slider.setValue(0)
        self.refresh()         

    def refresh(self):
        if self.__results is None:
            return         

        self.__result_display = copy(self.__results["score"])
        if self.__score_type_index == 0:
            self.__result_display = copy(self.__results["score"])
        elif self.__score_type_index == 1:    
            self.__result_display = copy(self.__results["spots_num"])
        elif self.__score_type_index == 2:
            self.__result_display = copy(self.__results["spots_int_aver"])
        elif self.__score_type_index == 3:
            self.__result_display = copy(self.__results["spots_resolution"])
        elif self.__score_type_index == 4:
            self.__result_display = copy(self.__results["image_num"])

        #self.__max_value = self.__result_display.max()
        self.__filter_min_value = self.__result_display.max() * \
             self._threshold_slider.value() / 100.0
        self.__result_display[self.__result_display < self.__filter_min_value] = 0
      
        if len(self.__result_display.shape) == 1:
            #Displaying results as a line
            x_data = numpy.arange(self.__result_display.shape[0])
            #self.__axis_x_range = [0, self.__result_display.shape[0] - 1]
            #self.__axis_y_range = [self.__result_display.min(), 
            #                       self.__result_display.max()]
            #self._heat_map_plot.clearcurves()
            #self._heat_map_plot.setx1timescale(False)
            #self._heat_map_plot.setY1AxisLimits(self.__result_display.min(),
            #                                    self.__result_display.max())
            self._heat_map_plot.newcurve("Dozor result", x_data, self.__result_display)
        else:
            #2D plot
            #self._heat_map_plot.imagePlot(self.__result_display, ymirror=False)
            #self._heat_map_plot.plotImage.show()
            self._heat_map_plot.plot_result(self.__result_display)
        #self._heat_map_plot.setX1AxisLimits(0, self.__axis_x_range[1])
        #self._heat_map_plot.setY1AxisLimits(0, self.__axis_y_range[1])
        #self._heat_map_plot.replot() 

    def filter_min_slider_changed(self, value):
        self.refresh()

    def mouse_clicked(self, pos_x, pos_y):
        self.__selected_x = pos_x
        self.__selected_y = pos_y
        image, line, self.selected_image_serial, image_path = \
              self.get_image_parameters_from_coord()
        try:
           col, row = self.get_col_row_from_image_line(line, image)
           msg = "Image: %d, value: %.3f" %(self.selected_image_serial,
                 self.__result_display[row][col])
        except:
           msg = "Image: %d" % self.selected_image_serial
        self._image_info_label.setText(msg)

    def plot_double_clicked(self, event):
        self.move_to_selected_position()

    def move_to_position_clicked(self):
        self.move_to_selected_position()

    def set_results(self, results, last_results=False):
        """
        Descript. : Displays results on the widget
        """
        self._heat_map_gbox.setEnabled(True)
        self.__results = results
        self.refresh()
        if last_results:
            self.set_best_pos()

    def clean_result(self):
        self.__results = None
        #self.__axis_x_range = None
        #self.__axis_y_range = None
        self.__associated_grid = None
        self.__associated_data_collection = None
        self._threshold_slider.setValue(0)

        #if self._heat_map_plot.plotImage is not None:
        #    self._heat_map_plot.plotImage.hide()
        #self._heat_map_plot.clearcurves()
        #self._heat_map_plot.setTitle("")
        self._best_pos_table.setRowCount(0)

    def create_centring_point_clicked(self):
        self.create_centring_point()

    def create_points_clicked(self):
        """
        Descript. : creates new centring points based on each image score.
                    All images are checked and if the value
                    is over the threshold then screen x and y coordinates
                    are estimated.
        """
        if self.__is_map_plot:
            result_display = numpy.transpose(self.__result_display)
            #step_x = pix_width / self.__result_display.shape[0]
            #step_y = pix_height / self.__result_display.shape[1]
            for col in range(result_display.shape[0]):
                for row in range(result_display.shape[1]):
                    if result_display[col][row] > 0:
                        #MD2
                        row = result_display.shape[1] - row - 1
                        self.create_centring_point(col + 0.5, row + 0.5)
        else:
            for col in range(self.__result_display.shape[0]):
                if self.__result_display[col] > 0:
                    self.create_centring_point(col + 0.5)
        self._beamline_setup_hwobj.shape_history_hwobj.select_all_cpos()
  
    def display_image_clicked(self):
        """
        Decript. : displays image in image tracker (by default adxv)
        """
        image, line, image_num, image_path = self.get_image_parameters_from_coord()
        if self._beamline_setup_hwobj.image_tracking_hwobj is not None:
            self._beamline_setup_hwobj.image_tracking_hwobj.load_image(image_path)

    def get_image_parameters_from_coord(self, coord_x=None, coord_y=None):
        """
        Descript. : returns image parameters for selected heat map frame
        """
        if not coord_x:
            coord_x = self.__selected_x
        if not coord_y:
            coord_y = self.__selected_y
         

        if self.__is_map_plot:
            num_cols, num_rows = self.__associated_grid.get_col_row_num()
            if coord_x > num_cols:
                coord_x = num_cols
            if coord_y > num_rows:
                coord_y = num_rows
            image, line, image_num = self.__associated_grid.\
                  get_image_from_col_row(coord_x, coord_y)
        else:
            image = int(self.__selected_x)
            line = 1
            image_num = image + self.__associated_data_collection.\
                  acquisitions[0].acquisition_parameters.first_image
        image_path = self.__associated_data_collection.acquisitions[0].\
                      path_template.get_image_path()
        image_path = image_path % image_num  
        return image, line, image_num, image_path

    def get_col_row_from_image_line(self, line, image):
        if self._data_analysis_hwobj is not None:
           return self._data_analysis_hwobj.get_col_row_from_line_image(line, image) 
        else:
           return None, None

    def create_centring_point(self, coord_x=None, coord_y=None):
        """
        Descript. : creates a new centring point for selected coordinate.
                    For mesh scan coord_x, and coord_y are grid coordinates in microns
                    For helical line coord_x represents frame number
        """ 
        if coord_x is None:
            coord_x = self.__selected_x
        if coord_y is None:
            coord_y = self.__selected_y 
        num_images = self.__associated_data_collection.acquisitions[0].\
                          acquisition_parameters.num_images
        osc_start = self.__associated_data_collection.acquisitions[0].\
                         acquisition_parameters.osc_start
        osc_range = self.__associated_data_collection.acquisitions[0].\
                         acquisition_parameters.osc_range

        omega = None
        if self.__is_map_plot:
            self.__associated_grid.set_osc_range(osc_range)
            motor_pos_dict = self.__associated_grid.\
                 get_motor_pos_from_col_row(coord_x, coord_y)
        else:
            omega = osc_start + osc_range * float(coord_x) / num_images
            (point_one, point_two) = self.__associated_data_collection.\
                      get_centred_positions()
            motor_pos_dict = self._beamline_setup_hwobj.diffractometer_hwobj.\
                      get_point_from_line(point_one, point_two, coord_x, num_images)
        self._beamline_setup_hwobj.diffractometer_hwobj.\
             create_centring_point(motor_pos_dict, omega)

    def move_to_selected_position(self):
        """
        Descript. : Moves to grid position
        Args.     : x and y are positions in micrometers starting from left 
                    top corner (as graphical coordinates)
        """
        osc_start = self.__associated_data_collection.acquisitions[0].\
                         acquisition_parameters.osc_start
        osc_range = self.__associated_data_collection.acquisitions[0].\
                         acquisition_parameters.osc_range
        if self.__is_map_plot:
            self.__associated_grid.set_osc_range(osc_range)
            motor_pos_dict = self.__associated_grid.\
                 get_motor_pos_from_col_row(self.__selected_x, self.__selected_y)
        else:
            num_images = self.__associated_data_collection.\
                      acquisitions[0].acquisition_parameters.num_images - 1
            (point_one, point_two) = self.__associated_data_collection.\
                      get_centred_positions()
            motor_pos_dict = self._beamline_setup_hwobj.diffractometer_hwobj.\
                      get_point_from_line(point_one, point_two, 
                      int(self.__selected_x), num_images)

        self._beamline_setup_hwobj.diffractometer_hwobj.\
             move_to_motors_positions(motor_pos_dict)

    def set_best_pos(self):
        """
        Descript. : Displays 10 (if exists) best positions, estimated
                    by fast processing.
        """
        self._best_pos_table.setRowCount(len(self.__results["best_positions"]))
        for row in range(len(self.__results["best_positions"])):
            self._best_pos_table.setItem(row, 0, QtGui.QTableWidgetItem(\
                 str(self.__results["best_positions"][row].get("index") + 1)))  
            self._best_pos_table.setItem(row, 1, QtGui.QTableWidgetItem(\
                 str(self.__results["best_positions"][row].get("score"))))
            self._best_pos_table.setItem(row, 2, QtGui.QTableWidgetItem(\
                 str(self.__results["best_positions"][row].get("spots_num"))))
            self._best_pos_table.setItem(row, 3, QtGui.QTableWidgetItem(\
                 str(self.__results["best_positions"][row].get("spots_int_aver"))))
            self._best_pos_table.setItem(row, 4, QtGui.QTableWidgetItem(\
                 str(self.__results["best_positions"][row].get("spots_resolution"))))
            self._best_pos_table.setItem(row, 5, QtGui.QTableWidgetItem(\
                 str(self.__results["best_positions"][row].get("filename"))))
            self._best_pos_table.setItem(row, 6, QtGui.QTableWidgetItem(\
                 str(self.__results["best_positions"][row].get("col"))))
            self._best_pos_table.setItem(row, 7, QtGui.QTableWidgetItem(\
                 str(self.__results["best_positions"][row].get("row"))))
            if self.__results["best_positions"][row]["cpos"]:
                self._best_pos_table.setItem(row, 8, QtGui.QTableWidgetItem(\
                   self.__results["best_positions"][row]["cpos"].as_str()))

    def move_to_best_position_clicked(self):
        if self._best_pos_table.currentRow() > -1:
            self._beamline_setup_hwobj.diffractometer_hwobj.move_to_motors_positions(\
                self.__results["best_positions"][self._best_pos_table.currentRow()].get("cpos").as_dict())

    def create_best_centring_point_clicked(self):
        if self._best_pos_table.currentRow() > -1:
            self._beamline_setup_hwobj.diffractometer_hwobj.create_centring_point(\
                self.__results["best_positions"][self._best_pos_table.currentRow()].get("cpos").as_dict())   

    def display_best_image_clicked(self):
        if self._best_pos_table.currentRow() > -1:
            image_path = self.__results["best_positions"][self._best_pos_table.currentRow()].get("filename")
            self._beamline_setup_hwobj.image_tracking_hwobj.load_image(image_path)
Beispiel #5
0
    def __init__(self, parent = None):
        QtGui.QWidget.__init__(self, parent)
        self.setObjectName('heat_map_widget')

        # Properties ---------------------------------------------------------- 
        #self.__half_widget_size = 900

        # Signals -------------------------------------------------------------

        # Slots ---------------------------------------------------------------

        # Hardware objects ----------------------------------------------------
        self._beamline_setup_hwobj = None
        self._data_analysis_hwobj = None

        # Internal values -----------------------------------------------------
        self.__results = None
        self.__result_display = None
        self.__associated_grid = None
        self.__associated_data_collection = None
        self.__selected_x = 0
        self.__selected_y = 0
        self.__selected_image_serial = 0
        #self.__axis_x_range = None
        #self.__axis_y_range = None
        self.__is_map_plot = None
        self.__score_type_index = 0
        self.__max_value = 0
        self.__filter_min_value = 0
        self.__best_pos_list = None
        self.__heat_map_max_size = []

        # Graphic elements ----------------------------------------------------
        self._heat_map_gbox = QtGui.QGroupBox('Heat map', self)
        #self._heat_map_plot = QtBlissGraph(self._heat_map_gbox)
        self._heat_map_plot = TwoDimenisonalPlotWidget(self)
        self._heat_map_popup_menu = QtGui.QMenu(self._heat_map_gbox)
        self._image_info_label = QtGui.QLabel("Image: #, value #", self._heat_map_gbox)

        self._heat_map_tools_widget = QtGui.QWidget(self._heat_map_gbox)
        score_type_label = QtGui.QLabel("Score type: ", self._heat_map_tools_widget)
        self._score_type_cbox = QtGui.QComboBox(self._heat_map_tools_widget)

        _threshold_label = QtGui.QLabel("Threshold: ", self._heat_map_tools_widget)
        self._threshold_slider = QtGui.QSlider(QtCore.Qt.Horizontal, 
               self._heat_map_tools_widget)
        self._create_points_button = QtGui.QPushButton("Create centring points", 
             self._heat_map_tools_widget)

        self._best_pos_gbox = QtGui.QGroupBox("Best positions", self)
        self._best_pos_table = QtGui.QTableWidget(self._best_pos_gbox)

        # Layout --------------------------------------------------------------
        _heat_map_tools_hlayout = QtGui.QHBoxLayout(self._heat_map_tools_widget)
        _heat_map_tools_hlayout.addWidget(score_type_label)
        _heat_map_tools_hlayout.addWidget(self._score_type_cbox)
        _heat_map_tools_hlayout.addWidget(_threshold_label)
        _heat_map_tools_hlayout.addWidget(self._threshold_slider)
        _heat_map_tools_hlayout.addStretch(0)
        _heat_map_tools_hlayout.addWidget(self._create_points_button)
        _heat_map_tools_hlayout.setSpacing(2)
        _heat_map_tools_hlayout.setContentsMargins(0, 0, 0, 0)

        _heat_map_gbox_vlayout = QtGui.QVBoxLayout(self._heat_map_gbox)
        _heat_map_gbox_vlayout.addWidget(self._heat_map_plot)
        _heat_map_gbox_vlayout.addWidget(self._image_info_label)
        _heat_map_gbox_vlayout.addWidget(self._heat_map_tools_widget)
        _heat_map_gbox_vlayout.setSpacing(2)
        _heat_map_gbox_vlayout.setContentsMargins(0, 4, 0, 0)
        
        _best_postition_gbox_vlayout = QtGui.QVBoxLayout(self._best_pos_gbox)
        _best_postition_gbox_vlayout.addWidget(self._best_pos_table)
        _best_postition_gbox_vlayout.setSpacing(2)
        _best_postition_gbox_vlayout.setContentsMargins(0, 4, 0, 0)

        _main_hlayout = QtGui.QVBoxLayout(self)
        _main_hlayout.addWidget(self._heat_map_gbox)
        _main_hlayout.addWidget(self._best_pos_gbox)
        _main_hlayout.setSpacing(2)
        _main_hlayout.setContentsMargins(0, 0, 0, 0)

        # SizePolicies --------------------------------------------------------
        self._image_info_label.setAlignment(QtCore.Qt.AlignRight)
        self._image_info_label.setSizePolicy(QtGui.QSizePolicy.Expanding, 
                                             QtGui.QSizePolicy.Fixed)

        # Qt signal/slot connections ------------------------------------------
        self._heat_map_plot.mouseClickedSignal.connect(self.mouse_clicked)
        self._score_type_cbox.activated.connect(self.score_type_changed)
        self._threshold_slider.valueChanged.connect(\
             self.filter_min_slider_changed)
        self._create_points_button.clicked.connect(\
             self.create_points_clicked)

        # Other ----------------------------------------------------------------
        #self._heat_map_plot.canvas().setMouseTracking(False)
        #Qt4_widget_colors.set_widget_color(self._heat_map_plot, QtCore.Qt.white)
        #self._heat_map_plot.mouseDoubleClickEvent = self.plot_double_clicked
        #self._heat_map_plot.setAxisAutoScale(False)
        #self._heat_map_plot.enableZoom(True)
        #self._heat_map_plot.showGrid()
        tooltip_text = "Double click to move to the position. " + \
                       "Right click to open menu."
        self._heat_map_plot.setToolTip(tooltip_text) 

        #self._heat_map_popup_menu.addAction(\
        #     "Reset zoom", self._heat_map_plot.zoomReset)
        self._heat_map_popup_menu.addSeparator()
        self._heat_map_popup_menu.addAction(\
             "Move to position", self.move_to_position_clicked)
        self._heat_map_popup_menu.addAction(\
             "Create centring point", self.create_centring_point_clicked)
        self._heat_map_popup_menu.addSeparator()
        self._heat_map_popup_menu.addAction(\
             "Open image in ADXV", self.display_image_clicked)
        self._heat_map_plot.contextMenuEvent = self.open_heat_map_popup_menu

        score_types = ["Score", "Spots num", "Int aver.", "Resolution"]
        for score_type in score_types:
            self._score_type_cbox.addItem(score_type)
        self._score_type_cbox.setMaximumWidth(200)

        #self._threshold_slider.setTickmarks(QtGui.QSlider.Below)
        self._threshold_slider.setRange(0, 100)
        self._threshold_slider.setTickInterval(5)
        self._threshold_slider.setFixedWidth(200)
        self._threshold_slider.setTracking(False)

        font = self._best_pos_table.font()
        font.setPointSize(8)
        self._best_pos_table.setFont(font)
        self._best_pos_table.setEditTriggers(\
             QtGui.QAbstractItemView.NoEditTriggers)
        self._best_pos_table.setColumnCount(9)
        self._best_pos_table.horizontalHeader().setStretchLastSection(True)
     
        self._best_pos_table.setHorizontalHeaderItem(0, \
            QtGui.QTableWidgetItem("No."))
        for score_type in enumerate(score_types):
            self._best_pos_table.setHorizontalHeaderItem(\
                 score_type[0] + 1, QtGui.QTableWidgetItem(score_type[1]))

        self._best_pos_table.setHorizontalHeaderItem(5,
             QtGui.QTableWidgetItem("Path"))
        self._best_pos_table.setHorizontalHeaderItem(6,
             QtGui.QTableWidgetItem("Col"))
        self._best_pos_table.setHorizontalHeaderItem(7,
             QtGui.QTableWidgetItem("Row"))
        self._best_pos_table.setHorizontalHeaderItem(8,
             QtGui.QTableWidgetItem("Motor positions"))

        screenShape = QtGui.QDesktopWidget().screenGeometry()
        self.__heat_map_max_size = (screenShape.width() / 2 - 200,
                                    screenShape.height() / 2)
    def __init__(self, *args):
        BlissWidget.__init__(self, *args)
	
        # Hardware objects ----------------------------------------------------
        self.beamline_setup_hwobj = None
        self.parallel_processing_hwobj = None

        # Internal values -----------------------------------------------------
        self.grid_properties = None
        self.info_dict = {'grid_cell': -1,
                          'comp_cell': -1}
        self.params_dict = None
        self.results = None
        self.score_type = "score"
        self.score_type_list = ("score", "spots_resolution", "spots_num")
        self.comp_table_item_fixed = False

        # Properties ----------------------------------------------------------
        self.addProperty('cell_size', 'integer', 22)
        self.addProperty('hwobj_beamline_setup', 'string', '/beamline-setup')
        #self.addProperty('hwobj_parallel_processing', 'string', '/parallel-processing')

        # Signals ------------------------------------------------------------

        # Slots ---------------------------------------------------------------

        # Graphic elements ----------------------------------------------------
        self.grid_widget = QWidget(self)
        self.grid_table = QTableWidget(self.grid_widget)
        self.grid_cell_label = QLabel("Selected grid cell: A1", self.grid_widget)
        self.grid_properties_combo = QComboBox(self)

        self.inverted_rows_cbox = QCheckBox("Inverted rows", self.grid_widget)
        self.image_tracking_cbox = QCheckBox("Life update", self.grid_widget)
        self.score_type_combo = QComboBox(self.grid_widget)
        self.save_hit_plot_button = QPushButton("Save hit plot", self.grid_widget)

        self.comp_widget = QWidget(self)
        self.comp_cell_label = QLabel("Selected compartment cell: A1", self.comp_widget)
        self.comp_table = QTableWidget(self.comp_widget)
        self.hit_map_plot = TwoDimenisonalPlotWidget(self.comp_widget)

        # Layout --------------------------------------------------------------
        _grid_vlayout = QVBoxLayout(self.grid_widget)
        _grid_vlayout.addWidget(self.grid_cell_label)
        _grid_vlayout.addWidget(self.grid_table)
        _grid_vlayout.addStretch()
        _grid_vlayout.addWidget(self.grid_properties_combo)
        _grid_vlayout.addWidget(self.inverted_rows_cbox)
        _grid_vlayout.addWidget(self.image_tracking_cbox)
        _grid_vlayout.addWidget(self.score_type_combo)
        _grid_vlayout.addWidget(self.save_hit_plot_button)
        _grid_vlayout.setSpacing(2)
        _grid_vlayout.setContentsMargins(2, 2, 2, 2)

        _comp_vlayout = QVBoxLayout(self.comp_widget)
        _comp_vlayout.addWidget(self.comp_cell_label)
        _comp_vlayout.addWidget(self.comp_table)
        _comp_vlayout.addWidget(self.hit_map_plot)
        _comp_vlayout.setSpacing(2)
        _comp_vlayout.setContentsMargins(2, 2, 2, 2)

        _main_vlayout = QHBoxLayout(self)
        _main_vlayout.addWidget(self.grid_widget)
        _main_vlayout.addWidget(self.comp_widget)
        _main_vlayout.setSpacing(2)
        _main_vlayout.setContentsMargins(2, 2, 2, 2)

        # SizePolicies --------------------------------------------------------

        # Qt signal/slot connections ------------------------------------------
        self.grid_table.cellClicked.connect(self.grid_cell_clicked)
        self.comp_table.cellClicked.connect(self.comp_cell_clicked)
        self.comp_table.cellEntered.connect(self.comp_cell_entered)
        self.grid_properties_combo.activated.connect(self.grid_properties_combo_changed)
        self.score_type_combo.activated.connect(self.score_type_changed)
        self.save_hit_plot_button.clicked.connect(self.save_hit_plot)
        self.hit_map_plot.mouseMovedSignal.connect(self.hit_map_mouse_moved)

        # Other ---------------------------------------------------------------
        self.grid_table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.grid_table.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.grid_table.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.grid_table.setMouseTracking(True)

        self.comp_table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.comp_table.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.comp_table.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.comp_table.setMouseTracking(True)

        for score_type in ("Score", "Resolution", "Number of spots"):
            self.score_type_combo.addItem(score_type)
class Qt4_StillCollectionPreviewBrick(BlissWidget):

    def __init__(self, *args):
        BlissWidget.__init__(self, *args)
	
        # Hardware objects ----------------------------------------------------
        self.beamline_setup_hwobj = None
        self.parallel_processing_hwobj = None

        # Internal values -----------------------------------------------------
        self.grid_properties = None
        self.info_dict = {'grid_cell': -1,
                          'comp_cell': -1}
        self.params_dict = None
        self.results = None
        self.score_type = "score"
        self.score_type_list = ("score", "spots_resolution", "spots_num")
        self.comp_table_item_fixed = False

        # Properties ----------------------------------------------------------
        self.addProperty('cell_size', 'integer', 22)
        self.addProperty('hwobj_beamline_setup', 'string', '/beamline-setup')
        #self.addProperty('hwobj_parallel_processing', 'string', '/parallel-processing')

        # Signals ------------------------------------------------------------

        # Slots ---------------------------------------------------------------

        # Graphic elements ----------------------------------------------------
        self.grid_widget = QWidget(self)
        self.grid_table = QTableWidget(self.grid_widget)
        self.grid_cell_label = QLabel("Selected grid cell: A1", self.grid_widget)
        self.grid_properties_combo = QComboBox(self)

        self.inverted_rows_cbox = QCheckBox("Inverted rows", self.grid_widget)
        self.image_tracking_cbox = QCheckBox("Life update", self.grid_widget)
        self.score_type_combo = QComboBox(self.grid_widget)
        self.save_hit_plot_button = QPushButton("Save hit plot", self.grid_widget)

        self.comp_widget = QWidget(self)
        self.comp_cell_label = QLabel("Selected compartment cell: A1", self.comp_widget)
        self.comp_table = QTableWidget(self.comp_widget)
        self.hit_map_plot = TwoDimenisonalPlotWidget(self.comp_widget)

        # Layout --------------------------------------------------------------
        _grid_vlayout = QVBoxLayout(self.grid_widget)
        _grid_vlayout.addWidget(self.grid_cell_label)
        _grid_vlayout.addWidget(self.grid_table)
        _grid_vlayout.addStretch()
        _grid_vlayout.addWidget(self.grid_properties_combo)
        _grid_vlayout.addWidget(self.inverted_rows_cbox)
        _grid_vlayout.addWidget(self.image_tracking_cbox)
        _grid_vlayout.addWidget(self.score_type_combo)
        _grid_vlayout.addWidget(self.save_hit_plot_button)
        _grid_vlayout.setSpacing(2)
        _grid_vlayout.setContentsMargins(2, 2, 2, 2)

        _comp_vlayout = QVBoxLayout(self.comp_widget)
        _comp_vlayout.addWidget(self.comp_cell_label)
        _comp_vlayout.addWidget(self.comp_table)
        _comp_vlayout.addWidget(self.hit_map_plot)
        _comp_vlayout.setSpacing(2)
        _comp_vlayout.setContentsMargins(2, 2, 2, 2)

        _main_vlayout = QHBoxLayout(self)
        _main_vlayout.addWidget(self.grid_widget)
        _main_vlayout.addWidget(self.comp_widget)
        _main_vlayout.setSpacing(2)
        _main_vlayout.setContentsMargins(2, 2, 2, 2)

        # SizePolicies --------------------------------------------------------

        # Qt signal/slot connections ------------------------------------------
        self.grid_table.cellClicked.connect(self.grid_cell_clicked)
        self.comp_table.cellClicked.connect(self.comp_cell_clicked)
        self.comp_table.cellEntered.connect(self.comp_cell_entered)
        self.grid_properties_combo.activated.connect(self.grid_properties_combo_changed)
        self.score_type_combo.activated.connect(self.score_type_changed)
        self.save_hit_plot_button.clicked.connect(self.save_hit_plot)
        self.hit_map_plot.mouseMovedSignal.connect(self.hit_map_mouse_moved)

        # Other ---------------------------------------------------------------
        self.grid_table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.grid_table.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.grid_table.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.grid_table.setMouseTracking(True)

        self.comp_table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.comp_table.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.comp_table.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.comp_table.setMouseTracking(True)

        for score_type in ("Score", "Resolution", "Number of spots"):
            self.score_type_combo.addItem(score_type)

    def propertyChanged(self, property_name, old_value, new_value):
        if property_name == 'hwobj_beamline_setup':
            if self.parallel_processing_hwobj is not None:
                self.parallel_processing_hwobj.disconnect("processingFinished",
                                                          self.processing_finished)
                self.parallel_processing_hwobj.disconnect("processingFailed",
                                                          self.processing_failed)
                self.parallel_processing_hwobj.disconnect("processingFrame",
                                                          self.processing_frame_changed)
                self.parallel_processing_hwobj.disconnect("paralleProcessingResults",
                                                          self.set_results)

            self.beamline_setup_hwobj = self.getHardwareObject(new_value)
            self.parallel_processing_hwobj = self.beamline_setup_hwobj.parallel_processing_hwobj

            if self.parallel_processing_hwobj is not None:
                self.parallel_processing_hwobj.connect("processingFinished",
                                                       self.processing_finished)
                self.parallel_processing_hwobj.connect("processingFailed",
                                                       self.processing_failed)
                self.parallel_processing_hwobj.connect("processingFrame",
                                                       self.processing_frame_changed)
                self.parallel_processing_hwobj.connect("paralleProcessingResults",
                                                       self.set_results)

                for grid_property in self.parallel_processing_hwobj.get_available_grid_properties():
                    self.grid_properties_combo.addItem(str(grid_property))
                self.grid_properties_combo.blockSignals(True)
                self.grid_properties_combo.setCurrentIndex(0)
                self.grid_properties_combo.blockSignals(False)
                self.init_gui()
        else:
            BlissWidget.propertyChanged(self, property_name, old_value, new_value)

    def init_gui(self):
        self.image_tracking_cbox.setChecked(True)

        self.grid_properties = self.parallel_processing_hwobj.get_current_grid_properties()

        self.inverted_rows_cbox.setChecked(self.grid_properties["inverted_rows"])
        self.grid_table.setColumnCount(self.grid_properties["grid_num_col"])
        self.grid_table.setRowCount(self.grid_properties["grid_num_row"])

        for col in range(self.grid_properties["grid_num_col"]):
            temp_header_item = QTableWidgetItem("%d" % (col + 1))
            self.grid_table.setHorizontalHeaderItem(col, temp_header_item)
            self.grid_table.setColumnWidth(col, self['cell_size'])

        for row in range(self.grid_properties["grid_num_row"]):
            temp_header_item = QTableWidgetItem(chr(65 + row))
            self.grid_table.setVerticalHeaderItem(row, temp_header_item)
            self.grid_table.setRowHeight(row, self['cell_size'])

        for col in range(self.grid_properties["grid_num_col"]):
            for row in range(self.grid_properties["grid_num_row"]):
                temp_item = QTableWidgetItem()
                self.grid_table.setItem(row, col, temp_item) 

        table_width = self['cell_size'] * (self.grid_properties["grid_num_col"] + 1) + 5
        table_height = self['cell_size'] * (self.grid_properties["grid_num_row"] + 1) + 5
        self.grid_table.setFixedWidth(table_width)
        self.grid_table.setFixedHeight(table_height)

        self.comp_table.setColumnCount(self.grid_properties["comp_num_col"])
        self.comp_table.setRowCount(self.grid_properties["comp_num_row"])
 
        for col in range(self.grid_properties["comp_num_col"]):
            temp_header_item = QTableWidgetItem("%d" % (col + 1))
            self.comp_table.setHorizontalHeaderItem(col, temp_header_item)
            self.comp_table.setColumnWidth(col, self['cell_size'])

        for row in range(self.grid_properties["comp_num_row"]):
            temp_header_item = QTableWidgetItem(chr(65 + row))
            self.comp_table.setVerticalHeaderItem(row, temp_header_item)
            self.comp_table.setRowHeight(row, self['cell_size'])

        for col in range(self.grid_properties["comp_num_col"]):
            for row in range(self.grid_properties["comp_num_row"]):
                temp_item = QTableWidgetItem()
                self.comp_table.setItem(row, col, temp_item)

        table_width = self['cell_size'] * (self.grid_properties["comp_num_col"] + 1) + 5 
        table_height = self['cell_size'] * (self.grid_properties["comp_num_row"] + 1) + 5
        self.comp_table.setFixedWidth(table_width)
        self.comp_table.setFixedHeight(table_height)

        for score_type in self.score_type_list:
            self.hit_map_plot.add_curve(score_type,
                                        np.array([]),
                                        np.array([]),
                                        linestyle="None",
                                        label=score_type,
                                        color="m",
                                        marker="s")
        self.hit_map_plot.hide_all_curves()
        self.hit_map_plot.show_curve(self.score_type)

    def save_hit_plot(self):
        file_types = "PNG (*.png)"
        
        filename = str(QFileDialog.getSaveFileName(\
            self, "Choose a filename to save under",
            os.path.expanduser("~"), file_types))
        #defaultSuffix

        if len(filename):
            gevent.spawn(self.parallel_processing_hwobj.plot_processing_results_task,
                         self.score_type, filename)
            #self.parallel_processing_hwobj.plot_processing_results(self.score_type, filename)

    def grid_cell_clicked(self, row, col):
        self.info_dict["grid_cell"] = row * self.grid_properties["grid_num_row"] + col
        self.grid_cell_label.setText("Current grid cell: %s%d" % (chr(65 + row), col + 1))
        #self.update_grid_table()
        self.update_comp_table() 

    def comp_cell_clicked(self, row, col):
        self.comp_table_item_fixed != self.comp_table_item_fixed

    def comp_cell_entered(self, row, col):
        if not self.comp_table_item_fixed:
            self.comp_cell_label.setText("Current compartment cell: %s%d" % \
                                         (chr(65 + row), col + 1))
        
            if self.params_dict is not None:  
                start_index = (self.info_dict["grid_cell"] * \
                               self.grid_properties["comp_num_col"] * \
                               self.grid_properties["comp_num_row"] +
                               row * self.grid_properties["comp_num_row"] + \
                               col) * \
                              self.params_dict["num_images_per_trigger"]
                end_index = min(start_index + self.params_dict["num_images_per_trigger"],
                                self.results[self.score_type].size)
 
                if self.results is not None:
                    if start_index < self.results[self.score_type].size:
                        data = {self.score_type: self.results[self.score_type][start_index:end_index],
                                "x_array": np.linspace(start_index, end_index, end_index - start_index, dtype=np.int32)}
                        self.hit_map_plot.update_curves(data)
                        self.hit_map_plot.set_x_axis_limits((start_index - 0.5, end_index + 0.5))
                        self.hit_map_plot.adjust_axes(self.score_type)

    def grid_properties_combo_changed(self, index):
        self.parallel_processing_hwobj.set_current_grid_index(index)
        self.init_gui()

    def score_type_changed(self, index):
        self.score_type = self.score_type_list[index]

    def hit_map_mouse_moved(self, pos_x, pos_y):
        if self.params_dict is not None:
            filename = self.params_dict['template'] % (self.params_dict['run_number'], int(pos_x))
            try:
                self.beamline_setup_hwobj.image_tracking_hwobj.load_image(filename)
            except:
                pass 

    def processing_finished(self):
        #self.info_dict["grid_cell"] = -1
        self.info_dict["comp_cell"] = -1
        self.update_grid_table() 

    def processing_failed(self):
        pass

    def set_results(self, results, params_dict, last_result):
        self.params_dict = params_dict
        self.results = results
        self.hit_map_plot.set_x_axis_limits((0, self.params_dict["num_images_per_trigger"]))

    def processing_frame_changed(self, frame_num):
        if not self.image_tracking_cbox.isChecked():
            return

        self.info_dict["frame_num"] = frame_num
        self.info_dict["comp_num"] = frame_num / self.params_dict["num_images_per_trigger"]

        grid_cell = self.info_dict["comp_num"] / \
                    self.grid_properties["comp_num_col"] / \
                    self.grid_properties["comp_num_row"]

        if self.info_dict["grid_cell"] != grid_cell:
            self.info_dict["grid_cell"] = grid_cell
            self.info_dict["comp_cell"] = -1
            self.update_grid_table()

        comp_cell = (frame_num - grid_cell * \
                     self.grid_properties["comp_num_col"] * \
                     self.grid_properties["comp_num_row"] * \
                     self.params_dict["num_images_per_trigger"]) / \
                     self.params_dict["num_images_per_trigger"]

        if self.info_dict["comp_cell"] != comp_cell:
            self.info_dict["comp_cell"] = comp_cell
            self.update_comp_table()

    def update_grid_table(self):
        if self.params_dict is None:
            return

        for row in range(self.grid_properties["grid_num_row"]):
            for col in range(self.grid_properties["grid_num_col"]):
                grid_table_item = self.grid_table.item(row, col)
                grid_cell = row * self.grid_properties["grid_num_row"] + col

                start_index = grid_cell  * \
                              self.grid_properties["comp_num_col"] * \
                              self.grid_properties["comp_num_row"] * \
                              self.params_dict["num_images_per_trigger"]
                end_index = min(start_index + \
                                self.grid_properties["comp_num_col"] * \
                                self.grid_properties["comp_num_row"] * \
                                self.params_dict["num_images_per_trigger"],
                                self.results[self.score_type].size -1)

                color = Qt4_widget_colors.LIGHT_GRAY
                if grid_cell == self.info_dict["grid_cell"]:
                    color = Qt4_widget_colors.DARK_GREEN
                elif start_index < self.results[self.score_type].size:
                     if self.results[self.score_type][start_index:end_index].max() > 0:
                         color = Qt4_widget_colors.LIGHT_BLUE
                     else:
                         color = Qt4_widget_colors.WHITE
                grid_table_item.setBackground(color)

    def update_comp_table(self):
        if self.params_dict is None: 
            return

        for row in range(self.grid_properties["comp_num_row"]):
            for col in range(self.grid_properties["comp_num_col"]):

                if self.inverted_rows_cbox.isChecked() and row % 2:
                    table_col = self.grid_properties["comp_num_col"] - col -1
                else:
                    table_col = col

                comp_table_item = self.comp_table.item(row, table_col)
                start_index = self.info_dict["grid_cell"] * \
                              self.grid_properties["comp_num_col"] * \
                              self.grid_properties["comp_num_row"] * \
                              self.params_dict["num_images_per_trigger"] + \
                              (row * self.grid_properties["comp_num_row"] + col) * \
                              self.params_dict["num_images_per_trigger"]
                              #self.grid_properties["comp_num_col"]
                end_index = min(start_index + self.params_dict["num_images_per_trigger"],
                                self.results[self.score_type].size -1)
                color = Qt4_widget_colors.LIGHT_GRAY
                if self.info_dict["comp_cell"] == row * self.grid_properties["comp_num_row"] + col:
                    color = Qt4_widget_colors.DARK_GREEN
                elif start_index < self.results[self.score_type].size:
                     if self.results[self.score_type][start_index:end_index].max() > 0:
                         color = Qt4_widget_colors.LIGHT_BLUE
                     else:
                         color = Qt4_widget_colors.WHITE
                comp_table_item.setBackground(color)
class HeatMapWidget(QtGui.QWidget):
    def __init__(self, parent = None):
        QtGui.QWidget.__init__(self, parent)
        self.setObjectName('heat_map_widget')

        # Properties ---------------------------------------------------------- 

        # Signals -------------------------------------------------------------

        # Slots ---------------------------------------------------------------

        # Hardware objects ----------------------------------------------------
        self._beamline_setup_hwobj = None

        # Internal values -----------------------------------------------------
        self.__results = None
        self.__result_display = None
        self.__associated_grid = None
        self.__associated_data_collection = None
        self.__selected_x = 0
        self.__selected_y = 0
        self.__selected_image_serial = 0
        self.__is_map_plot = None
        self.__score_type_index = 0
        self.__max_value = 0
        self.__filter_min_value = 0
        self.__best_pos_list = None
        self.__heat_map_max_size = []

        # Graphic elements ----------------------------------------------------
        self._heat_map_gbox = QtGui.QGroupBox('Heat map', self)
        self._heat_map_plot = TwoDimenisonalPlotWidget(self)
        self._heat_map_popup_menu = QtGui.QMenu(self._heat_map_gbox)
        self._image_info_label = QtGui.QLabel("Image: #, value #", self._heat_map_gbox)

        self._heat_map_tools_widget = QtGui.QWidget(self._heat_map_gbox)
        score_type_label = QtGui.QLabel("Score type: ", self._heat_map_tools_widget)
        self._score_type_cbox = QtGui.QComboBox(self._heat_map_tools_widget)

        _threshold_label = QtGui.QLabel("Threshold: ", self._heat_map_tools_widget)
        self._threshold_slider = QtGui.QSlider(QtCore.Qt.Horizontal, 
               self._heat_map_tools_widget)
        self._relaunch_processing_button = QtGui.QPushButton("Relaunch processing",
             self._heat_map_tools_widget)
        self._create_points_button = QtGui.QPushButton("Create centring points", 
             self._heat_map_tools_widget)

        self._summary_gbox = QtGui.QGroupBox("Summary", self)
        self._summary_textbrowser = QtGui.QTextBrowser(self._summary_gbox)
        self._best_pos_gbox = QtGui.QGroupBox("Best positions", self)
        self._best_pos_table = QtGui.QTableWidget(self._best_pos_gbox)
        self._best_pos_popup_menu = QtGui.QMenu(self._heat_map_gbox)

        # Layout --------------------------------------------------------------
        _heat_map_tools_hlayout = QtGui.QHBoxLayout(self._heat_map_tools_widget)
        _heat_map_tools_hlayout.addWidget(score_type_label)
        _heat_map_tools_hlayout.addWidget(self._score_type_cbox)
        _heat_map_tools_hlayout.addWidget(_threshold_label)
        _heat_map_tools_hlayout.addWidget(self._threshold_slider)
        _heat_map_tools_hlayout.addStretch(0)
        _heat_map_tools_hlayout.addWidget(self._relaunch_processing_button)
        _heat_map_tools_hlayout.addWidget(self._create_points_button)
        _heat_map_tools_hlayout.setSpacing(2)
        _heat_map_tools_hlayout.setContentsMargins(2, 2, 2, 2)

        _heat_map_gbox_vlayout = QtGui.QVBoxLayout(self._heat_map_gbox)
        _heat_map_gbox_vlayout.addWidget(self._heat_map_plot)
        _heat_map_gbox_vlayout.addWidget(self._image_info_label)
        _heat_map_gbox_vlayout.addWidget(self._heat_map_tools_widget)
        _heat_map_gbox_vlayout.setSpacing(2)
        _heat_map_gbox_vlayout.setContentsMargins(2, 4, 2, 2)
        
        _summary_gbox_vlayout = QtGui.QVBoxLayout(self._summary_gbox)
        _summary_gbox_vlayout.addWidget(self._summary_textbrowser)
        _summary_gbox_vlayout.setSpacing(2)
        _summary_gbox_vlayout.setContentsMargins(2, 4, 2, 2)

        _best_postition_gbox_vlayout = QtGui.QVBoxLayout(self._best_pos_gbox)
        _best_postition_gbox_vlayout.addWidget(self._best_pos_table)
        _best_postition_gbox_vlayout.setSpacing(2)
        _best_postition_gbox_vlayout.setContentsMargins(2, 4, 2, 2)

        _main_hlayout = QtGui.QVBoxLayout(self)
        _main_hlayout.addWidget(self._heat_map_gbox)
        _main_hlayout.addWidget(self._summary_gbox)
        _main_hlayout.addWidget(self._best_pos_gbox)
        _main_hlayout.setSpacing(2)
        _main_hlayout.setContentsMargins(2, 2, 2, 2)

        # SizePolicies --------------------------------------------------------
        self._image_info_label.setAlignment(QtCore.Qt.AlignRight)
        self._image_info_label.setSizePolicy(QtGui.QSizePolicy.Expanding, 
                                             QtGui.QSizePolicy.Fixed)

        # Qt signals and slots ------------------------------------------------
        self._score_type_cbox.activated.connect(self.score_type_changed)
        self._threshold_slider.valueChanged.\
             connect(self.filter_min_slider_changed)
        self._relaunch_processing_button.clicked.\
             connect(self.relaunch_processing_clicked)
        self._create_points_button.clicked.\
             connect(self.create_points_clicked)
        self._heat_map_plot.mouseClickedSignal.\
             connect(self.mouse_clicked)
        self._heat_map_plot.mouseDoubleClickedSignal.\
             connect(self.move_to_position_clicked)

        # Other ---------------------------------------------------------------
        tooltip_text = "Double click to move to the position. " + \
                       "Right click to open menu."
        self._heat_map_plot.setToolTip(tooltip_text) 
        self._heat_map_popup_menu.addSeparator()
        self._heat_map_popup_menu.addAction(\
             "Move to position", self.move_to_position_clicked)
        self._heat_map_popup_menu.addAction(\
             "Create centring point", self.create_centring_point_clicked)
        self._heat_map_popup_menu.addSeparator()
        self._heat_map_popup_menu.addAction(\
             "Open image in ADXV", self.display_image_clicked)
        self._heat_map_plot.contextMenuEvent = self.open_heat_map_popup_menu

        score_types = ["Score", "Spots num", "Int aver.", "Resolution"]
        for score_type in score_types:
            self._score_type_cbox.addItem(score_type)
        self._score_type_cbox.setMaximumWidth(200)

        #self._threshold_slider.setTickmarks(QtGui.QSlider.Below)
        self._threshold_slider.setRange(0, 100)
        self._threshold_slider.setTickInterval(5)
        self._threshold_slider.setFixedWidth(200)
        self._threshold_slider.setTracking(False)

        font = self._best_pos_table.font()
        font.setPointSize(8)
        self._best_pos_table.setFont(font)
        self._best_pos_table.setEditTriggers(\
             QtGui.QAbstractItemView.NoEditTriggers)
        self._best_pos_table.setColumnCount(9)
        self._best_pos_table.setAlternatingRowColors(True)
        self._best_pos_table.setWordWrap(False)
        self._best_pos_table.horizontalHeader().setSortIndicatorShown(True)
        self._best_pos_table.setHorizontalHeaderItem(0, \
            QtGui.QTableWidgetItem("No."))
        for score_type in enumerate(score_types):
            self._best_pos_table.setHorizontalHeaderItem(\
                 score_type[0] + 1, QtGui.QTableWidgetItem(score_type[1]))

        self._best_pos_table.setHorizontalHeaderItem(5,
             QtGui.QTableWidgetItem("Path"))
        self._best_pos_table.setHorizontalHeaderItem(6,
             QtGui.QTableWidgetItem("Col"))
        self._best_pos_table.setHorizontalHeaderItem(7,
             QtGui.QTableWidgetItem("Row"))
        self._best_pos_table.setHorizontalHeaderItem(8,
             QtGui.QTableWidgetItem("Motor positions"))

        self._best_pos_popup_menu.addAction(\
             "Move to position",
              self.move_to_best_position_clicked)
        self._best_pos_table.contextMenuEvent = self.open_best_pos_popup_menu

        screenShape = QtGui.QDesktopWidget().screenGeometry()
        self.__heat_map_max_size = (screenShape.width() / 2 - 200,
                                    screenShape.height() / 2)

    def set_beamline_setup(self, beamline_setup_hwobj):
        self._beamline_setup_hwobj = beamline_setup_hwobj

    def set_associated_data_collection(self, data_collection):
        self.__associated_data_collection = data_collection
        self.__associated_grid = self.__associated_data_collection.grid

        if self.__associated_grid is None:
            self.__is_map_plot = False
        else:
            self.__is_map_plot = True
            axis_range = self.__associated_grid.get_col_row_num()
            grid_size = self.__associated_grid.get_size_pix()

            width = grid_size[0] * 5
            height = grid_size[1] * 5
            ratio = float(width) / height

            if width > self.__heat_map_max_size[0]:
                width = self.__heat_map_max_size[0]
                height = width / ratio
            if height > self.__heat_map_max_size[1]:
                height = self.__heat_map_max_size[1]
                width = height * ratio

            self._heat_map_plot.setFixedWidth(width)
            self._heat_map_plot.setFixedHeight(height)

            #axis_range = self.__associated_grid.get_col_row_num()
            self._heat_map_plot.set_x_axis_limits((0, axis_range[0]))
            self._heat_map_plot.set_y_axis_limits((0, axis_range[1]))

    def main_gbox_toggled(self, toggle):
        self._heat_map_plot.setHidden(not toggle)
        self._heat_map_tools_widget.setHidden(not toggle)
            
    def open_heat_map_popup_menu(self, context_event):
        point = QtCore.QPoint(context_event.globalX(), 
                              context_event.globalY())
        self._heat_map_popup_menu.popup(point)

    def open_best_pos_popup_menu(self, context_event):
        if self._best_pos_table.rowCount() > 0:
            point = QtCore.QPoint(context_event.globalX(), 
                                  context_event.globalY())
            self._best_pos_popup_menu.popup(point)  

    def score_type_changed(self, score_type_index):
        self.__score_type_index = score_type_index
        #self._threshold_slider.setValue(0)
        self.refresh()         

    def refresh(self):
        self._summary_textbrowser.clear()
        if self.__results is None:
            return         

        self.__result_display = copy(self.__results["score"])
        if self.__score_type_index == 0:
            self.__result_display = copy(self.__results["score"])
        elif self.__score_type_index == 1:    
            self.__result_display = copy(self.__results["spots_num"])
        elif self.__score_type_index == 2:
            self.__result_display = copy(self.__results["spots_int_aver"])
        elif self.__score_type_index == 3:
            self.__result_display = copy(self.__results["spots_resolution"])
        elif self.__score_type_index == 4:
            self.__result_display = copy(self.__results["image_num"])

        self.__filter_min_value = self.__result_display.max() * \
             self._threshold_slider.value() / 100.0
        self.__result_display[self.__result_display < self.__filter_min_value] = 0
      
        if len(self.__result_display.shape) == 1:
            x_data = numpy.arange(self.__result_display.shape[0])
            self._heat_map_plot.clear()
            self._heat_map_plot.add_curve(self.__result_display, x_data, "Dozor result")
            #self._heat_map_plot.newcurve("Dozor result", x_data, self.__result_display)
        else:
            self._heat_map_plot.plot_result(self.__result_display)

            if self.__associated_grid: 
                self._summary_textbrowser.append("<b>Mesh parameters</b>")
                grid_properties = self.__associated_grid.get_properties()
                self._summary_textbrowser.append("Number of columns: %d" % \
                     grid_properties["steps_x"])
                self._summary_textbrowser.append("Number of rows: %d" % \
                     grid_properties["steps_y"])
                self._summary_textbrowser.append("Horizontal spacing: %.1f %sm" % \
                    (grid_properties["xOffset"], u"\u00B5"))
                self._summary_textbrowser.append("Vertical spacing: %.1f %sm" % \
                    (grid_properties["yOffset"], u"\u00B5"))
                self._summary_textbrowser.append("Beam size : %.1f x %.1f %sm" % \
                    (grid_properties["beam_x_mm"], grid_properties["beam_y_mm"], u"\u00B5"))
                self._summary_textbrowser.append("Scan range : %.1f x %.1f mm" % \
                    (grid_properties["dx_mm"], grid_properties["dy_mm"]))

                self._summary_textbrowser.append("<b>Scan results</b>")
                self._summary_textbrowser.append("Scan lines: %d" % \
                     grid_properties["num_lines"])
                self._summary_textbrowser.append("Images per line: %d" % \
                     grid_properties["num_images_per_line"])
        self._summary_textbrowser.append("Number of diffraction spots: %d" % \
             (self.__results["score"] > 0).sum())

    def filter_min_slider_changed(self, value):
        self.refresh()

    def mouse_clicked(self, pos_x, pos_y):
        self.__selected_x = pos_x
        self.__selected_y = pos_y
        image, line, self.selected_image_serial, image_path = \
              self.get_image_parameters_from_coord()
        try:
           col, row = self.get_col_row_from_image_line(line, image)
           msg = "Image: %d, value: %.3f" %(self.selected_image_serial,
                 self.__result_display[row][col])
        except:
           msg = "Image: %d" % self.selected_image_serial
        self._image_info_label.setText(msg)

    def plot_double_clicked(self, event):
        self.move_to_selected_position()

    def move_to_position_clicked(self):
        self.move_to_selected_position()

    def set_results(self, results, last_results=False):
        """
        Displays results on the widget
        """
        self.__results = results
        self.refresh()
        if last_results:
            self.set_best_pos()
            self.setEnabled(True)

    def clean_result(self):
        """
        Method to clean heat map, summary log and table with best positions
        """
        #self.setEnabled(False)
        self.__results = None
        self.__associated_grid = None
        self.__associated_data_collection = None
        self._heat_map_plot.clear()
        self._threshold_slider.setValue(0)
        self._summary_textbrowser.clear()
        self._best_pos_table.setRowCount(0)
        self._best_pos_table.setSortingEnabled(False)

    def create_centring_point_clicked(self):
        """
        Creates a centring point based on the location on the location
        on heat map.
        """
        self.create_centring_point()

    def create_points_clicked(self):
        """
        Creates new centring points based on each image score.
        All images are checked and if the value is over the threshold
         then screen x and y coordinates are estimated.
        """
        if self.__is_map_plot:
            result_display = numpy.transpose(self.__result_display)
            #step_x = pix_width / self.__result_display.shape[0]
            #step_y = pix_height / self.__result_display.shape[1]
            for col in range(result_display.shape[0]):
                for row in range(result_display.shape[1]):
                    if result_display[col][row] > 0:
                        #MD2
                        row = result_display.shape[1] - row - 1
                        self.create_centring_point(col + 0.5, row + 0.5)
        else:
            for col in range(self.__result_display.shape[0]):
                if self.__result_display[col] > 0:
                    self.create_centring_point(col + 0.5)
        self._beamline_setup_hwobj.shape_history_hwobj.select_all_points()
  
    def display_image_clicked(self):
        """
        Displays image in image tracker (by default adxv)
        """
        image, line, image_num, image_path = self.get_image_parameters_from_coord()
        if self._beamline_setup_hwobj.image_tracking_hwobj is not None:
            self._beamline_setup_hwobj.image_tracking_hwobj.load_image(image_path)

    def get_image_parameters_from_coord(self, coord_x=None, coord_y=None):
        """
        returns image parameters for selected heat map frame
        """
        if not coord_x:
            coord_x = self.__selected_x
        if not coord_y:
            coord_y = self.__selected_y
         

        if self.__is_map_plot:
            num_cols, num_rows = self.__associated_grid.get_col_row_num()
            if coord_x > num_cols:
                coord_x = num_cols
            if coord_y > num_rows:
                coord_y = num_rows

            image, line, image_num = self.__associated_grid.\
                  get_image_from_col_row(coord_x, coord_y)
        else:
            image = int(self.__selected_x)
            line = 1
            image_num = image + self.__associated_data_collection.\
                  acquisitions[0].acquisition_parameters.first_image
        image_path = self.__associated_data_collection.acquisitions[0].\
                      path_template.get_image_path()
        image_path = image_path % image_num  
        return image, line, image_num, image_path

    def get_col_row_from_image_line(self, line, image):
        """
        Returns col and row from image and line
        """
        return self.__associated_grid.get_col_row_from_line_image(line, image)

    def create_centring_point(self, coord_x=None, coord_y=None):
        """
        Descript. : creates a new centring point for selected coordinate.
                    For mesh scan coord_x, and coord_y are grid coordinates in microns
                    For helical line coord_x represents frame number
        """ 
        if coord_x is None:
            coord_x = self.__selected_x
        if coord_y is None:
            coord_y = self.__selected_y 
        num_images = self.__associated_data_collection.acquisitions[0].\
                          acquisition_parameters.num_images
        osc_start = self.__associated_data_collection.acquisitions[0].\
                         acquisition_parameters.osc_start
        osc_range = self.__associated_data_collection.acquisitions[0].\
                         acquisition_parameters.osc_range

        omega = None
        if self.__is_map_plot:
            self.__associated_grid.set_osc_range(osc_range)
            motor_pos_dict = self.__associated_grid.\
                 get_motor_pos_from_col_row(coord_x, coord_y)
        else:
            omega = osc_start + osc_range * float(coord_x) / num_images
            (point_one, point_two) = self.__associated_data_collection.\
                      get_centred_positions()
            motor_pos_dict = self._beamline_setup_hwobj.diffractometer_hwobj.\
                      get_point_from_line(point_one, point_two, coord_x, num_images)
            motor_pos_dict['phi'] = omega
        self._beamline_setup_hwobj.shape_history_hwobj.\
             create_centring_point(True, {"motors": motor_pos_dict})

    def move_to_selected_position(self):
        """
        Descript. : Moves to grid position
        Args.     : x and y are positions in micrometers starting from left 
                    top corner (as graphical coordinates)
        """
        osc_start = self.__associated_data_collection.acquisitions[0].\
                         acquisition_parameters.osc_start
        osc_range = self.__associated_data_collection.acquisitions[0].\
                         acquisition_parameters.osc_range
        if self.__associated_grid:
            self.__associated_grid.set_osc_range(osc_range)
            motor_pos_dict = self.__associated_grid.\
                 get_motor_pos_from_col_row(self.__selected_x, self.__selected_y)
        else:
            num_images = self.__associated_data_collection.\
                      acquisitions[0].acquisition_parameters.num_images - 1
            (point_one, point_two) = self.__associated_data_collection.\
                      get_centred_positions()
            motor_pos_dict = self._beamline_setup_hwobj.diffractometer_hwobj.\
                      get_point_from_line(point_one, point_two, 
                      int(self.__selected_x), num_images)

        self._beamline_setup_hwobj.diffractometer_hwobj.\
             move_to_motors_positions(motor_pos_dict)

    def set_best_pos(self):
        """
        Descript. : Displays 10 (if exists) best positions, estimated
                    by fast processing.
        """
        self._best_pos_table.setRowCount(len(self.__results["best_positions"]))
        for row in range(len(self.__results["best_positions"])):
            self._best_pos_table.setItem(row, 0, QtGui.QTableWidgetItem(\
                 str(self.__results["best_positions"][row].get("index") + 1)))  
            self._best_pos_table.setItem(row, 1, QtGui.QTableWidgetItem(\
                 str(self.__results["best_positions"][row].get("score"))))
            self._best_pos_table.setItem(row, 2, QtGui.QTableWidgetItem(\
                 str(self.__results["best_positions"][row].get("spots_num"))))
            self._best_pos_table.setItem(row, 3, QtGui.QTableWidgetItem(\
                 str(self.__results["best_positions"][row].get("spots_int_aver"))))
            self._best_pos_table.setItem(row, 4, QtGui.QTableWidgetItem(\
                 str(self.__results["best_positions"][row].get("spots_resolution"))))
            self._best_pos_table.setItem(row, 5, QtGui.QTableWidgetItem(\
                 str(self.__results["best_positions"][row].get("filename"))))
            self._best_pos_table.setItem(row, 6, QtGui.QTableWidgetItem(\
                 str(self.__results["best_positions"][row].get("col"))))
            self._best_pos_table.setItem(row, 7, QtGui.QTableWidgetItem(\
                 str(self.__results["best_positions"][row].get("row"))))
            if self.__results["best_positions"][row]["cpos"]:
                self._best_pos_table.setItem(row, 8, QtGui.QTableWidgetItem(\
                   self.__results["best_positions"][row]["cpos"].as_str()))
        self._best_pos_table.setSortingEnabled(True)

    def move_to_best_position_clicked(self):
        """
        Moves diffractometer motors to the selected position
        """
        if self._best_pos_table.currentRow() > -1:
            self._beamline_setup_hwobj.diffractometer_hwobj.\
                move_to_motors_positions(self.__results["best_positions"]\
                [self._best_pos_table.currentRow()].get("cpos").as_dict())

    def create_best_centring_point_clicked(self):
        """
        Creates a new centring point based on the selected point
        from the table of best positions.
        """
        if self._best_pos_table.currentRow() > -1:
            self._beamline_setup_hwobj.diffractometer_hwobj.\
                create_centring_point(self.__results["best_positions"]\
                [self._best_pos_table.currentRow()].get("cpos").as_dict())   

    def display_best_image_clicked(self):
        """
        Displays image (clicked from best position table) in ADXV
        """
        if self._best_pos_table.currentRow() > -1:
            image_path = self.__results["best_positions"]\
               [self._best_pos_table.currentRow()].get("filename")
            self._beamline_setup_hwobj.image_tracking_hwobj.\
               load_image(image_path)

    def relaunch_processing_clicked(self):
        """
        Relaunches parallel processing
        """
        if self.__associated_data_collection and self.__associated_grid:
            self._beamline_setup_hwobj.parallel_processing_hwobj.\
                 run_processing(self.__associated_data_collection, 
                                self.__associated_grid) 
    def __init__(self, parent=None, allow_adjust_size=True):
        QWidget.__init__(self, parent)
        self.setObjectName('heat_map_widget')
        self.allow_adjust_size = allow_adjust_size

        # Properties ---------------------------------------------------------- 

        # Signals -------------------------------------------------------------

        # Slots ---------------------------------------------------------------

        # Hardware objects ----------------------------------------------------
        self._beamline_setup_hwobj = None

        # Internal values -----------------------------------------------------
        self.__results = None
        self.__results_display = None
        self.__associated_grid = None
        self.__associated_data_collection = None
        self.__selected_x = 0
        self.__selected_y = 0
        self.__selected_image_serial = 0
        self.__score_key = "score"
        self.__max_value = 0
        self.__filter_min_value = 0
        self.__best_pos_list = None
        self.__label_im = None
        self.__heat_map_max_size = []
        self.__heatmap_clicked = False
        self.__enable_continues_image_display = True
        self.__tooltip_text = None

        # Graphic elements ----------------------------------------------------
        self._heat_map_gbox = QGroupBox('Heat map', self)
        self._heat_map_plot = TwoDimenisonalPlotWidget(self)
        self._heat_map_popup_menu = QMenu(self._heat_map_gbox)

        heat_map_info_widget = QWidget(self._heat_map_gbox)
        score_type_label = QLabel("Score type: ", heat_map_info_widget)
        self._score_type_cbox = QComboBox(heat_map_info_widget)
        self._image_info_label = QLabel("Image: #, value #", heat_map_info_widget)

        self._heat_map_tools_widget = QWidget(self._heat_map_gbox)

        _threshold_label = QLabel("Threshold: ", self._heat_map_tools_widget)
        self._threshold_slider = QSlider(Qt.Horizontal, 
               self._heat_map_tools_widget)
        self._relaunch_processing_button = QPushButton("Relaunch processing",
             self._heat_map_tools_widget)
        self._create_points_button = QPushButton("Create centring points", 
             self._heat_map_tools_widget)

        self._summary_gbox = QGroupBox("Summary", self)
        self._summary_textbrowser = QTextBrowser(self._summary_gbox)
        self._best_pos_gbox = QGroupBox("Best positions", self)
        self._best_pos_table = QTableWidget(self._best_pos_gbox)
        self._best_pos_popup_menu = QMenu(self._heat_map_gbox)
        self._best_pos_gbox.setHidden(True)

        # Layout --------------------------------------------------------------
        _heat_map_info_hlayout = QHBoxLayout(heat_map_info_widget)
        _heat_map_info_hlayout.addWidget(score_type_label)
        _heat_map_info_hlayout.addWidget(self._score_type_cbox)
        _heat_map_info_hlayout.addStretch(0)
        _heat_map_info_hlayout.addWidget(self._image_info_label)
        _heat_map_info_hlayout.setSpacing(2)
        _heat_map_info_hlayout.setContentsMargins(0, 0, 0, 0)

        _heat_map_tools_hlayout = QHBoxLayout(self._heat_map_tools_widget)
        _heat_map_tools_hlayout.addWidget(_threshold_label)
        _heat_map_tools_hlayout.addWidget(self._threshold_slider)
        _heat_map_tools_hlayout.addStretch(0)
        _heat_map_tools_hlayout.addWidget(self._relaunch_processing_button)
        _heat_map_tools_hlayout.addWidget(self._create_points_button)
        _heat_map_tools_hlayout.setSpacing(2)
        _heat_map_tools_hlayout.setContentsMargins(0, 0, 0, 0)

        _heat_map_gbox_vlayout = QVBoxLayout(self._heat_map_gbox)
        _heat_map_gbox_vlayout.addWidget(self._heat_map_plot)
        _heat_map_gbox_vlayout.addWidget(heat_map_info_widget)
        _heat_map_gbox_vlayout.addWidget(self._heat_map_tools_widget)
        _heat_map_gbox_vlayout.setSpacing(2)
        _heat_map_gbox_vlayout.setContentsMargins(0, 0, 0, 0)
        
        _summary_gbox_vlayout = QVBoxLayout(self._summary_gbox)
        _summary_gbox_vlayout.addWidget(self._summary_textbrowser)
        _summary_gbox_vlayout.setSpacing(2)
        _summary_gbox_vlayout.setContentsMargins(0, 0, 0, 0)

        _best_postition_gbox_vlayout = QVBoxLayout(self._best_pos_gbox)
        _best_postition_gbox_vlayout.addWidget(self._best_pos_table)
        _best_postition_gbox_vlayout.setSpacing(2)
        _best_postition_gbox_vlayout.setContentsMargins(0, 0, 0, 0)

        _main_hlayout = QVBoxLayout(self)
        _main_hlayout.addWidget(self._heat_map_gbox)
        _main_hlayout.addWidget(self._summary_gbox)
        _main_hlayout.addWidget(self._best_pos_gbox)
        _main_hlayout.setSpacing(2)
        _main_hlayout.setContentsMargins(2, 2, 2, 2)

        # SizePolicies --------------------------------------------------------
        self._image_info_label.setAlignment(Qt.AlignLeft)
        self._image_info_label.setSizePolicy(QSizePolicy.Expanding, 
                                             QSizePolicy.Fixed)

        # Qt signals and slots ------------------------------------------------
        self._score_type_cbox.activated.connect(self.score_type_changed)
        self._threshold_slider.valueChanged.\
             connect(self.filter_min_slider_changed)
        self._relaunch_processing_button.clicked.\
             connect(self.relaunch_processing_clicked)
        self._create_points_button.clicked.\
             connect(self.create_points_clicked)
        self._heat_map_plot.mouseMovedSignal.\
             connect(self.mouse_moved)
        self._heat_map_plot.mouseClickedSignal.\
             connect(self.mouse_clicked)
        self._heat_map_plot.mouseDoubleClickedSignal.\
             connect(self.move_to_position_clicked)
        self._heat_map_plot.mouseLeftSignal.connect(\
             self.mouse_left_plot)
             

        # Other ---------------------------------------------------------------
        self.__tooltip_text = "Double click to move to the position. " + \
                              "Right click to open menu."
        self._heat_map_plot.setToolTip(self.__tooltip_text) 
        self._heat_map_popup_menu.addSeparator()
        self._heat_map_popup_menu.addAction(\
             "Move to position",
             self.move_to_position_clicked)
        self._heat_map_popup_menu.addAction(\
             "Create centring point",
             self.create_centring_point_clicked)

        self._heat_map_popup_menu.addAction(\
             "Create helical line",
             self.create_helical_line_clicked)
        self._heat_map_popup_menu.addAction(\
             "Rotate 90 degrees and create helical line",
             self.rotate_and_create_helical_line_clicked)
        
        self._heat_map_popup_menu.addSeparator()
        self._heat_map_popup_menu.addAction(\
             "Open image in ADXV", self.display_image_clicked)
        self.continues_display_action = \
             self._heat_map_popup_menu.addAction(\
             "Continues image display in ADXV",
              self.toogle_continues_image_display)
        self.continues_display_action.setCheckable(True)
        self.continues_display_action.setChecked(True)

        self._heat_map_popup_menu.addSeparator()
        options_menu = self._heat_map_popup_menu.addMenu("Options")

        self._heat_map_plot.contextMenuEvent = self.open_heat_map_popup_menu

        score_types = ["Resolution", "Score", "Spots num"]
        for score_type in score_types:
            self._score_type_cbox.addItem(score_type)
        self._score_type_cbox.setMaximumWidth(200)
        self.__score_key = "spots_resolution"

        #self._threshold_slider.setTickmarks(QtGui.QSlider.Below)
        self._threshold_slider.setRange(0, 100)
        self._threshold_slider.setTickInterval(5)
        self._threshold_slider.setFixedWidth(200)
        self._threshold_slider.setTracking(False)

        font = self._best_pos_table.font()
        font.setPointSize(8)
        self._best_pos_table.setFont(font)
        self._best_pos_table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self._best_pos_table.setColumnCount(9)
        self._best_pos_table.setAlternatingRowColors(True)
        self._best_pos_table.setWordWrap(False)
        self._best_pos_table.horizontalHeader().setSortIndicatorShown(True)
        self._best_pos_table.setHorizontalHeaderItem(0, \
            QTableWidgetItem("No."))
        for score_type in enumerate(score_types):
            self._best_pos_table.setHorizontalHeaderItem(\
                 score_type[0] + 1, QTableWidgetItem(score_type[1]))

        self._best_pos_table.setHorizontalHeaderItem(5,
             QTableWidgetItem("Path"))
        self._best_pos_table.setHorizontalHeaderItem(6,
             QTableWidgetItem("Col"))
        self._best_pos_table.setHorizontalHeaderItem(7,
             QTableWidgetItem("Row"))
        self._best_pos_table.setHorizontalHeaderItem(8,
             QTableWidgetItem("Motor positions"))

        self._best_pos_popup_menu.addAction(\
             "Move to position",
              self.move_to_best_position_clicked)
        self._best_pos_table.contextMenuEvent = self.open_best_pos_popup_menu
        #self._best_pos_table.setHidden(True)

        screenShape = QDesktopWidget().screenGeometry()
        self.__heat_map_max_size = (screenShape.width() / 2,
                                    screenShape.height() / 2)
class HeatMapWidget(QWidget):
    def __init__(self, parent=None, allow_adjust_size=True):
        QWidget.__init__(self, parent)
        self.setObjectName('heat_map_widget')
        self.allow_adjust_size = allow_adjust_size

        # Properties ---------------------------------------------------------- 

        # Signals -------------------------------------------------------------

        # Slots ---------------------------------------------------------------

        # Hardware objects ----------------------------------------------------
        self._beamline_setup_hwobj = None

        # Internal values -----------------------------------------------------
        self.__results = None
        self.__results_display = None
        self.__associated_grid = None
        self.__associated_data_collection = None
        self.__selected_x = 0
        self.__selected_y = 0
        self.__selected_image_serial = 0
        self.__score_key = "score"
        self.__max_value = 0
        self.__filter_min_value = 0
        self.__best_pos_list = None
        self.__label_im = None
        self.__heat_map_max_size = []
        self.__heatmap_clicked = False
        self.__enable_continues_image_display = True
        self.__tooltip_text = None

        # Graphic elements ----------------------------------------------------
        self._heat_map_gbox = QGroupBox('Heat map', self)
        self._heat_map_plot = TwoDimenisonalPlotWidget(self)
        self._heat_map_popup_menu = QMenu(self._heat_map_gbox)

        heat_map_info_widget = QWidget(self._heat_map_gbox)
        score_type_label = QLabel("Score type: ", heat_map_info_widget)
        self._score_type_cbox = QComboBox(heat_map_info_widget)
        self._image_info_label = QLabel("Image: #, value #", heat_map_info_widget)

        self._heat_map_tools_widget = QWidget(self._heat_map_gbox)

        _threshold_label = QLabel("Threshold: ", self._heat_map_tools_widget)
        self._threshold_slider = QSlider(Qt.Horizontal, 
               self._heat_map_tools_widget)
        self._relaunch_processing_button = QPushButton("Relaunch processing",
             self._heat_map_tools_widget)
        self._create_points_button = QPushButton("Create centring points", 
             self._heat_map_tools_widget)

        self._summary_gbox = QGroupBox("Summary", self)
        self._summary_textbrowser = QTextBrowser(self._summary_gbox)
        self._best_pos_gbox = QGroupBox("Best positions", self)
        self._best_pos_table = QTableWidget(self._best_pos_gbox)
        self._best_pos_popup_menu = QMenu(self._heat_map_gbox)
        self._best_pos_gbox.setHidden(True)

        # Layout --------------------------------------------------------------
        _heat_map_info_hlayout = QHBoxLayout(heat_map_info_widget)
        _heat_map_info_hlayout.addWidget(score_type_label)
        _heat_map_info_hlayout.addWidget(self._score_type_cbox)
        _heat_map_info_hlayout.addStretch(0)
        _heat_map_info_hlayout.addWidget(self._image_info_label)
        _heat_map_info_hlayout.setSpacing(2)
        _heat_map_info_hlayout.setContentsMargins(0, 0, 0, 0)

        _heat_map_tools_hlayout = QHBoxLayout(self._heat_map_tools_widget)
        _heat_map_tools_hlayout.addWidget(_threshold_label)
        _heat_map_tools_hlayout.addWidget(self._threshold_slider)
        _heat_map_tools_hlayout.addStretch(0)
        _heat_map_tools_hlayout.addWidget(self._relaunch_processing_button)
        _heat_map_tools_hlayout.addWidget(self._create_points_button)
        _heat_map_tools_hlayout.setSpacing(2)
        _heat_map_tools_hlayout.setContentsMargins(0, 0, 0, 0)

        _heat_map_gbox_vlayout = QVBoxLayout(self._heat_map_gbox)
        _heat_map_gbox_vlayout.addWidget(self._heat_map_plot)
        _heat_map_gbox_vlayout.addWidget(heat_map_info_widget)
        _heat_map_gbox_vlayout.addWidget(self._heat_map_tools_widget)
        _heat_map_gbox_vlayout.setSpacing(2)
        _heat_map_gbox_vlayout.setContentsMargins(0, 0, 0, 0)
        
        _summary_gbox_vlayout = QVBoxLayout(self._summary_gbox)
        _summary_gbox_vlayout.addWidget(self._summary_textbrowser)
        _summary_gbox_vlayout.setSpacing(2)
        _summary_gbox_vlayout.setContentsMargins(0, 0, 0, 0)

        _best_postition_gbox_vlayout = QVBoxLayout(self._best_pos_gbox)
        _best_postition_gbox_vlayout.addWidget(self._best_pos_table)
        _best_postition_gbox_vlayout.setSpacing(2)
        _best_postition_gbox_vlayout.setContentsMargins(0, 0, 0, 0)

        _main_hlayout = QVBoxLayout(self)
        _main_hlayout.addWidget(self._heat_map_gbox)
        _main_hlayout.addWidget(self._summary_gbox)
        _main_hlayout.addWidget(self._best_pos_gbox)
        _main_hlayout.setSpacing(2)
        _main_hlayout.setContentsMargins(2, 2, 2, 2)

        # SizePolicies --------------------------------------------------------
        self._image_info_label.setAlignment(Qt.AlignLeft)
        self._image_info_label.setSizePolicy(QSizePolicy.Expanding, 
                                             QSizePolicy.Fixed)

        # Qt signals and slots ------------------------------------------------
        self._score_type_cbox.activated.connect(self.score_type_changed)
        self._threshold_slider.valueChanged.\
             connect(self.filter_min_slider_changed)
        self._relaunch_processing_button.clicked.\
             connect(self.relaunch_processing_clicked)
        self._create_points_button.clicked.\
             connect(self.create_points_clicked)
        self._heat_map_plot.mouseMovedSignal.\
             connect(self.mouse_moved)
        self._heat_map_plot.mouseClickedSignal.\
             connect(self.mouse_clicked)
        self._heat_map_plot.mouseDoubleClickedSignal.\
             connect(self.move_to_position_clicked)
        self._heat_map_plot.mouseLeftSignal.connect(\
             self.mouse_left_plot)
             

        # Other ---------------------------------------------------------------
        self.__tooltip_text = "Double click to move to the position. " + \
                              "Right click to open menu."
        self._heat_map_plot.setToolTip(self.__tooltip_text) 
        self._heat_map_popup_menu.addSeparator()
        self._heat_map_popup_menu.addAction(\
             "Move to position",
             self.move_to_position_clicked)
        self._heat_map_popup_menu.addAction(\
             "Create centring point",
             self.create_centring_point_clicked)

        self._heat_map_popup_menu.addAction(\
             "Create helical line",
             self.create_helical_line_clicked)
        self._heat_map_popup_menu.addAction(\
             "Rotate 90 degrees and create helical line",
             self.rotate_and_create_helical_line_clicked)
        
        self._heat_map_popup_menu.addSeparator()
        self._heat_map_popup_menu.addAction(\
             "Open image in ADXV", self.display_image_clicked)
        self.continues_display_action = \
             self._heat_map_popup_menu.addAction(\
             "Continues image display in ADXV",
              self.toogle_continues_image_display)
        self.continues_display_action.setCheckable(True)
        self.continues_display_action.setChecked(True)

        self._heat_map_popup_menu.addSeparator()
        options_menu = self._heat_map_popup_menu.addMenu("Options")

        self._heat_map_plot.contextMenuEvent = self.open_heat_map_popup_menu

        score_types = ["Resolution", "Score", "Spots num"]
        for score_type in score_types:
            self._score_type_cbox.addItem(score_type)
        self._score_type_cbox.setMaximumWidth(200)
        self.__score_key = "spots_resolution"

        #self._threshold_slider.setTickmarks(QtGui.QSlider.Below)
        self._threshold_slider.setRange(0, 100)
        self._threshold_slider.setTickInterval(5)
        self._threshold_slider.setFixedWidth(200)
        self._threshold_slider.setTracking(False)

        font = self._best_pos_table.font()
        font.setPointSize(8)
        self._best_pos_table.setFont(font)
        self._best_pos_table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self._best_pos_table.setColumnCount(9)
        self._best_pos_table.setAlternatingRowColors(True)
        self._best_pos_table.setWordWrap(False)
        self._best_pos_table.horizontalHeader().setSortIndicatorShown(True)
        self._best_pos_table.setHorizontalHeaderItem(0, \
            QTableWidgetItem("No."))
        for score_type in enumerate(score_types):
            self._best_pos_table.setHorizontalHeaderItem(\
                 score_type[0] + 1, QTableWidgetItem(score_type[1]))

        self._best_pos_table.setHorizontalHeaderItem(5,
             QTableWidgetItem("Path"))
        self._best_pos_table.setHorizontalHeaderItem(6,
             QTableWidgetItem("Col"))
        self._best_pos_table.setHorizontalHeaderItem(7,
             QTableWidgetItem("Row"))
        self._best_pos_table.setHorizontalHeaderItem(8,
             QTableWidgetItem("Motor positions"))

        self._best_pos_popup_menu.addAction(\
             "Move to position",
              self.move_to_best_position_clicked)
        self._best_pos_table.contextMenuEvent = self.open_best_pos_popup_menu
        #self._best_pos_table.setHidden(True)

        screenShape = QDesktopWidget().screenGeometry()
        self.__heat_map_max_size = (screenShape.width() / 2,
                                    screenShape.height() / 2)

    def set_beamline_setup(self, beamline_setup_hwobj):
        self._beamline_setup_hwobj = beamline_setup_hwobj

    def set_associated_data_collection(self, data_collection):
        self.__associated_data_collection = data_collection
        self.__associated_grid = self.__associated_data_collection.grid
        acq_parameters = self.__associated_data_collection.acquisitions[0].\
                    acquisition_parameters

        if not data_collection.is_mesh():
            #x_array = numpy.linspace(0, acq_parameters.num_images, acq_parameters.num_images, dtype="int16")
            x_array = numpy.array([])
            y_array = numpy.array([])

            self._heat_map_plot.add_curve("spots_resolution",
                                          y_array,
                                          x_array,
                                          linestyle="None",
                                          label="Resolution",
                                          color="m",
                                          marker=".")
            self._heat_map_plot.add_curve("score",
                                          y_array,
                                          x_array,
                                          label="Total score",
                                          linestyle="None",
                                          color="b",
                                          marker=".")
            self._heat_map_plot.add_curve("spots_num",
                                          y_array,
                                          x_array,
                                          label="Number of spots",
                                          linestyle="None",
                                          color="b",
                                          marker=".")
            self._heat_map_plot.hide_all_curves()
            self._heat_map_plot.show_curve(self.__score_key)

            self.adjust_axes()
        else:
            if self.allow_adjust_size:
                grid_size = self.__associated_grid.get_size_pix()

                width = grid_size[0] * 5
                height = grid_size[1] * 5
                ratio = float(width) / height

                if width > self.__heat_map_max_size[0]:
                    width = self.__heat_map_max_size[0]
                    height = width / ratio
                if height > self.__heat_map_max_size[1]:
                    height = self.__heat_map_max_size[1]
                    width = height * ratio

                self._heat_map_plot.setFixedWidth(width)
                self._heat_map_plot.setFixedHeight(height)

            axis_range = self.__associated_grid.get_col_row_num()
            self._heat_map_plot.set_y_axis_limits((0, axis_range[1]))
            self._heat_map_plot.set_x_axis_limits((0, axis_range[0]))

            self._summary_textbrowser.append("<b>Mesh parameters</b>")
            grid_params = self.__associated_grid.get_properties()

            empty_array = numpy.zeros(acq_parameters.num_images).\
                reshape(grid_params["steps_x"], grid_params["steps_y"])
                                                                  
            self._heat_map_plot.plot_result(numpy.transpose(empty_array))

    def main_gbox_toggled(self, toggle):
        self._heat_map_plot.setHidden(not toggle)
        self._heat_map_tools_widget.setHidden(not toggle)
            
    def open_heat_map_popup_menu(self, context_event):
        point = QPoint(context_event.globalX(), 
                       context_event.globalY())
        self._heat_map_popup_menu.popup(point)

    def open_best_pos_popup_menu(self, context_event):
        if self._best_pos_table.rowCount() > 0:
            point = QPoint(context_event.globalX(), 
                           context_event.globalY())
            self._best_pos_popup_menu.popup(point)  

    def score_type_changed(self, score_type_index):
        if score_type_index == 0:
            self.__score_key = "spots_resolution"
        elif score_type_index == 1:
            self.__score_key = "score"
        elif score_type_index == 2:
            self.__score_key = "spots_num"

        if self.__results is not None:
            if self.__results[self.__score_key].ndim == 1:
                self._heat_map_plot.hide_all_curves()
                self._heat_map_plot.show_curve(self.__score_key)
                self.adjust_axes()
            else:
                self._heat_map_plot.plot_result(numpy.transpose(self.__results[self.__score_key]))

    def adjust_axes(self):
        #self._summary_textbrowser.clear()

        if self.__results:
            if self.__results[self.__score_key].ndim == 1:
                self._heat_map_plot.adjust_axes(self.__score_key)

                labels = []
                positions = numpy.linspace(0, self.__results[self.__score_key].max(), 5)

                if self.__score_key == "spots_resolution":
                    labels.append('inf')
                    for item in positions[1:]:  
                        labels.append("%.2f"%(1./item))
                else:
                    for item in positions:
                        labels.append("%d"% item)

                self._heat_map_plot.set_yticks(positions)
                self._heat_map_plot.set_ytick_labels(labels)

    def filter_min_slider_changed(self, value):
        self.__results_display = deepcopy(self.__results)

        for key in self.__results_display.keys():
            if key != "best_positions":
                filter_value = self.__results_display[key].max() * value / 100.0
                self.__results_display[key][self.__results_display[key] < filter_value] = 0

        if self.__results_display[self.__score_key].ndim == 1:
            self._heat_map_plot.update_curves(self.__results_display)
            self.adjust_axes()
        else:
            self._heat_map_plot.plot_result(numpy.transpose(self.__results_display[self.__score_key]))

    def mouse_moved(self, pos_x, pos_y):
        if self.__enable_continues_image_display and \
           self.__heatmap_clicked:
            if abs(int(self.__selected_x) - int(pos_x)) >= 1 or \
               abs(int(self.__selected_y) - int(pos_y)) >= 1:
                self.__selected_x = pos_x
                self.__selected_y = pos_y
                self.display_image_clicked()
                self.display_image_tooltip()

    def mouse_clicked(self, pos_x, pos_y):
        self.__heatmap_clicked = True
        self.__selected_x = pos_x
        self.__selected_y = pos_y

        if self.__associated_data_collection:
            msg = ""
            if self.__associated_grid: 
                image, line, self.selected_image_serial, image_path = \
                      self.get_image_parameters_from_coord()
                col, row = self.get_col_row_from_image_line(line, image)
                if self.__results:
                    msg = "Image: %d, value: %.1f" %(self.selected_image_serial,
                             self.__results[self.__score_key][col][row])
                else: 
                    msg = "Image: %d" % self.selected_image_serial

                label_im = deepcopy(self.__label_im)
                label_im[label_im != label_im[col, row]] = 0
            else:
                msg = "Image: %d" % int(pos_x) 
            self._image_info_label.setText(msg)

    def plot_double_clicked(self, event):
        self.move_to_selected_position()

    def mouse_left_plot(self):
        self.__heatmap_clicked = False
        self._heat_map_plot.setToolTip(self.__tooltip_text)

    def move_to_position_clicked(self):
        self.move_to_selected_position()

    def set_results(self, results, last_results=False):
        """
        Displays results on the widget
        """
        self.__results = results
        #self.__results_display = results

        if self.__results[self.__score_key].ndim == 1:
            self._heat_map_plot.update_curves(results)
            self.adjust_axes()
        else:
            self._heat_map_plot.plot_result(numpy.transpose(results[self.__score_key]))
        
        if last_results:
            self.__label_im, nb_labels = ndimage.label(self.__results['score'] > 0)
        #self.set_best_pos()

    def clean_result(self):
        """
        Method to clean heat map, summary log and table with best positions
        """
        #self.setEnabled(False)
        self.__results = None
        self.__associated_grid = None
        self.__associated_data_collection = None
        self._heat_map_plot.clear()
        self._threshold_slider.setValue(0)
        self._summary_textbrowser.clear()
        self._best_pos_table.setRowCount(0)
        self._best_pos_table.setSortingEnabled(False)

    def create_centring_point_clicked(self):
        """
        Creates a centring point based on the location on the location
        on heat map.
        """
        self.create_centring_point()

    def create_points_clicked(self):
        """
        Creates new centring points based on each image score.
        All images are checked and if the value is over the threshold
         then screen x and y coordinates are estimated.
        """
        if self.__results[self.__score_key].ndim == 1:
            for col in range(self.__result.shape[0]):
                if self.__result[col] > 0:
                    self.create_centring_point(col + 0.5)
        else:
            #result_display = numpy.transpose(self.__result_display[self.__score_key])
            result_display = self.__results[self.__score_key]
            #step_x = pix_width / self.__result_display.shape[0]
            #step_y = pix_height / self.__result_display.shape[1]
            for col in range(result_display.shape[0]):
                for row in range(result_display.shape[1]):
                    if result_display[col][row] > 0:
                        #MD2
                        row = result_display.shape[1] - row - 1
                        self.create_centring_point(col + 0.5, row + 0.5)
        self._beamline_setup_hwobj.shape_history_hwobj.select_all_points()
  
    def display_image_clicked(self):
        """
        Displays image in image tracker (by default adxv)
        """
        image, line, image_num, image_path = self.get_image_parameters_from_coord()
        try:
            self._beamline_setup_hwobj.image_tracking_hwobj.load_image(image_path)
        except:
            pass

    def display_image_tooltip(self):
        image, line, self.selected_image_serial, image_path = \
              self.get_image_parameters_from_coord()
        tooltip_text = "Image no. %d" % self.selected_image_serial
        if self.__results is not None:
            try:
                col, row = self.get_col_row_from_image_line(line, image)
                tooltip_text += "\nTotal score: %.1f" %  \
                                self.__results['score'][col][row] +\
                                "\nNumber of spots: %d" % \
                                self.__results['spots_num'][col][row]
            except:
                pass
        self._heat_map_plot.setToolTip(tooltip_text)

    def toogle_continues_image_display(self):
        self.__enable_continues_image_display = \
            self.continues_display_action.isChecked()

    def get_image_parameters_from_coord(self, coord_x=None, coord_y=None):
        """
        returns image parameters for selected heat map frame
        """
        if not coord_x:
            coord_x = self.__selected_x
        if not coord_y:
            coord_y = self.__selected_y
         

        if self.__associated_grid:
            num_cols, num_rows = self.__associated_grid.get_col_row_num()
            if coord_x > num_cols:
                coord_x = num_cols
            if coord_y > num_rows:
                coord_y = num_rows

            image, line, image_num = self.__associated_grid.\
                  get_image_from_col_row(coord_x, coord_y)
        else:
            image = int(self.__selected_x)
            line = 1
            image_num = image + self.__associated_data_collection.\
                  acquisitions[0].acquisition_parameters.first_image
        image_path = self.__associated_data_collection.acquisitions[0].\
                      path_template.get_image_path()
        image_path = image_path % image_num  
        return image, line, image_num, image_path

    def get_col_row_from_image_line(self, line, image):
        """
        Returns col and row from image and line
        """
        col, row = self.__associated_grid.get_col_row_from_line_image(line, image)
        ## TODO check if next line needs to be removed
        row = self.__results[self.__score_key].shape[1] - row - 1
        return col, row

    def create_centring_point(self, coord_x=None, coord_y=None):
        """
        Descript. : creates a new centring point for selected coordinate.
                    For mesh scan coord_x, and coord_y are grid coordinates in microns
                    For helical line coord_x represents frame number
        """ 
        if coord_x is None:
            coord_x = self.__selected_x
        if coord_y is None:
            coord_y = self.__selected_y 
        num_images = self.__associated_data_collection.acquisitions[0].\
                          acquisition_parameters.num_images
        osc_start = self.__associated_data_collection.acquisitions[0].\
                         acquisition_parameters.osc_start
        osc_range = self.__associated_data_collection.acquisitions[0].\
                         acquisition_parameters.osc_range

        omega = None
        if self.__associated_grid:
            self.__associated_grid.set_osc_range(osc_range)
            motor_pos_dict = self.__associated_grid.\
                 get_motor_pos_from_col_row(coord_x, coord_y)
        else:
            omega = osc_start + osc_range * float(coord_x) / num_images
            (point_one, point_two) = self.__associated_data_collection.\
                      get_centred_positions()
            motor_pos_dict = self._beamline_setup_hwobj.diffractometer_hwobj.\
                      get_point_from_line(point_one, point_two, coord_x, num_images)
            motor_pos_dict['phi'] = omega
        self._beamline_setup_hwobj.shape_history_hwobj.\
             create_centring_point(True, {"motors": motor_pos_dict})

    def create_helical_line_clicked(self):
        motor_pos_dict = self.__associated_grid.\
              get_motor_pos_from_col_row(self.__selected_x, self.__selected_y)
        self._beamline_setup_hwobj.shape_history_hwobj.create_auto_line(motor_pos_dict)

    def rotate_and_create_helical_line_clicked(self):
        self.move_to_selected_position()
        self._beamline_setup_hwobj.diffractometer_hwobj.move_omega_relative(90)
        self._beamline_setup_hwobj.shape_history_hwobj.create_auto_line()

    def move_to_selected_position(self):
        """
        Descript. : Moves to grid position
        Args.     : x and y are positions in micrometers starting from left 
                    top corner (as graphical coordinates)
        """
        osc_start = self.__associated_data_collection.acquisitions[0].\
                         acquisition_parameters.osc_start
        osc_range = self.__associated_data_collection.acquisitions[0].\
                         acquisition_parameters.osc_range
        if self.__associated_grid:
            self.__associated_grid.set_osc_range(osc_range)
            motor_pos_dict = self.__associated_grid.\
                 get_motor_pos_from_col_row(self.__selected_x, self.__selected_y)
        else:
            num_images = self.__associated_data_collection.\
                      acquisitions[0].acquisition_parameters.num_images - 1
            (point_one, point_two) = self.__associated_data_collection.\
                      get_centred_positions()
            motor_pos_dict = self._beamline_setup_hwobj.diffractometer_hwobj.\
                      get_point_from_line(point_one, point_two, 
                      int(self.__selected_x), num_images)

        self._beamline_setup_hwobj.diffractometer_hwobj.\
             move_to_motors_positions(motor_pos_dict, wait=True)

    def set_best_pos(self):
        """
        Descript. : Displays 10 (if exists) best positions, estimated
                    by fast processing.
        """
        self._best_pos_table.setRowCount(len(self.__results.get("best_positions", [])))
        for row, best_pos in enumerate(self.__results.get("best_positions", [])):
            self._best_pos_table.setItem(row, 0, QTableWidgetItem("%d" \
                 % (best_pos.get("index") + 1)))  
            self._best_pos_table.setItem(row, 1, QTableWidgetItem("%.2f"\
                 % (best_pos.get("score"))))
            self._best_pos_table.setItem(row, 2, QTableWidgetItem("%d"\
                 % (best_pos.get("spots_num"))))
            self._best_pos_table.setItem(row, 3, QTableWidgetItem("%.2f"\
                 % (best_pos.get("spots_int_aver"))))
            self._best_pos_table.setItem(row, 4, QTableWidgetItem("%.2f"\
                 % (best_pos.get("spots_resolution"))))
            self._best_pos_table.setItem(row, 5, QTableWidgetItem(\
                 str(best_pos.get("filename"))))
            self._best_pos_table.setItem(row, 6, QTableWidgetItem("%d" \
                 % (best_pos.get("col"))))
            self._best_pos_table.setItem(row, 7, QTableWidgetItem("%d"\
                 % (best_pos.get("row"))))
            if best_pos["cpos"]:
                self._best_pos_table.setItem(row, 8, QTableWidgetItem(\
                 str(best_pos["cpos"])))
        self._best_pos_table.setSortingEnabled(True)

    def move_to_best_position_clicked(self):
        """
        Moves diffractometer motors to the selected position
        """
        if self._best_pos_table.currentRow() > -1:
            self._beamline_setup_hwobj.diffractometer_hwobj.\
                move_to_motors_positions(self.__results["best_positions"]\
                [self._best_pos_table.currentRow()]["cpos"])

    def create_best_centring_point_clicked(self):
        """
        Creates a new centring point based on the selected point
        from the table of best positions.
        """
        if self._best_pos_table.currentRow() > -1:
            self._beamline_setup_hwobj.diffractometer_hwobj.\
                create_centring_point(self.__results["best_positions"]\
                [self._best_pos_table.currentRow()].get("cpos").as_dict())   

    def display_best_image_clicked(self):
        """
        Displays image (clicked from best position table) in ADXV
        """
        if self._best_pos_table.currentRow() > -1:
            image_path = self.__results["best_positions"]\
               [self._best_pos_table.currentRow()].get("filename")
            self._beamline_setup_hwobj.image_tracking_hwobj.\
               load_image(image_path)

    def relaunch_processing_clicked(self):
        """
        Relaunches parallel processing
        """
        if self.__associated_data_collection and self.__associated_grid:
            self._beamline_setup_hwobj.parallel_processing_hwobj.\
                 run_processing(self.__associated_data_collection)