Esempio n. 1
0
class MainWindow(QtGui.QMainWindow):
    """ Class of Main Window (top)
    """
    def __init__(self, parent=None):
        """ Initialization and set up
        """
        # Base class
        QtGui.QMainWindow.__init__(self, parent)

        # UI Window (from Qt Designer)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        # Make UI scrollable
        self._scrollbars = MantidQt.API.WidgetScrollbarDecorator(self)
        self._scrollbars.setEnabled(True)  # Must follow after setupUi(self)!

        # Mantid configuration
        self._instrument = str(self.ui.comboBox_instrument.currentText())
        # config = ConfigService.Instance()
        # self._instrument = config["default.instrument"]

        # Event handling definitions
        # Top
        self.connect(self.ui.pushButton_setExp, QtCore.SIGNAL('clicked()'),
                     self.do_set_experiment)

        # Tab 'Data Access'
        self.connect(self.ui.pushButton_applySetup, QtCore.SIGNAL('clicked()'),
                     self.do_apply_setup)
        self.connect(self.ui.pushButton_browseLocalDataDir,
                     QtCore.SIGNAL('clicked()'),
                     self.do_browse_local_spice_data)
        self.connect(self.ui.pushButton_testURLs, QtCore.SIGNAL('clicked()'),
                     self.do_test_url)
        self.connect(self.ui.pushButton_ListScans, QtCore.SIGNAL('clicked()'),
                     self.do_list_scans)
        self.connect(self.ui.pushButton_downloadExpData,
                     QtCore.SIGNAL('clicked()'), self.do_download_spice_data)
        self.connect(self.ui.comboBox_mode,
                     QtCore.SIGNAL('currentIndexChanged(int)'),
                     self.change_data_access_mode)

        # Tab 'View Raw Data'
        self.connect(self.ui.pushButton_setScanInfo,
                     QtCore.SIGNAL('clicked()'), self.do_load_scan_info)
        self.connect(self.ui.pushButton_plotRawPt, QtCore.SIGNAL('clicked()'),
                     self.do_plot_pt_raw)
        self.connect(self.ui.pushButton_prevPtNumber,
                     QtCore.SIGNAL('clicked()'), self.do_plot_prev_pt_raw)
        self.connect(self.ui.pushButton_nextPtNumber,
                     QtCore.SIGNAL('clicked()'), self.do_plot_next_pt_raw)
        self.connect(self.ui.pushButton_showPtList, QtCore.SIGNAL('clicked()'),
                     self.show_scan_pt_list)
        self.connect(self.ui.pushButton_usePt4UB, QtCore.SIGNAL('clicked()'),
                     self.do_add_peak_to_find)

        # Tab 'calculate ub matrix'
        self.connect(self.ui.pushButton_findPeak, QtCore.SIGNAL('clicked()'),
                     self.do_find_peak)
        self.connect(self.ui.pushButton_addPeakToCalUB,
                     QtCore.SIGNAL('clicked()'), self.do_add_ub_peak)
        self.connect(self.ui.pushButton_calUB, QtCore.SIGNAL('clicked()'),
                     self.do_cal_ub_matrix)
        self.connect(self.ui.pushButton_acceptUB, QtCore.SIGNAL('clicked()'),
                     self.doAcceptCalUB)
        self.connect(self.ui.pushButton_indexUBPeaks,
                     QtCore.SIGNAL('clicked()'), self.do_index_ub_peaks)
        self.connect(self.ui.pushButton_deleteUBPeak,
                     QtCore.SIGNAL('clicked()'), self.do_del_ub_peaks)
        self.connect(self.ui.pushButton_clearUBPeakTable,
                     QtCore.SIGNAL('clicked()'), self.do_clear_ub_peaks)
        self.connect(self.ui.pushButton_resetPeakHKLs,
                     QtCore.SIGNAL('clicked()'), self.do_reset_ub_peaks_hkl)

        # Tab 'Slice View'
        self.connect(self.ui.pushButton_setUBSliceView,
                     QtCore.SIGNAL('clicked()'), self.do_set_ub_sv)
        self.connect(self.ui.pushButton_process4SliceView,
                     QtCore.SIGNAL('clicked()'), self.do_merge_scans)

        # Tab 'Advanced'
        self.connect(self.ui.pushButton_useDefaultDir,
                     QtCore.SIGNAL('clicked()'), self.do_setup_dir_default)
        self.connect(self.ui.pushButton_browseLocalCache,
                     QtCore.SIGNAL('clicked()'),
                     self.do_browse_local_cache_dir)
        self.connect(self.ui.pushButton_browseWorkDir,
                     QtCore.SIGNAL('clicked()'), self.do_browse_working_dir)
        self.connect(self.ui.comboBox_instrument,
                     QtCore.SIGNAL('currentIndexChanged(int)'),
                     self.change_instrument_name)

        # Refine UB matrix
        self.connect(self.ui.pushButton_addToRefine,
                     QtCore.SIGNAL('clicked()'), self.do_refine_ub)
        self.connect(self.ui.pushButton_addAllRefineUB,
                     QtCore.SIGNAL('clicked()'), self.do_refine_ub)
        self.connect(self.ui.pushButton_acceptRefinedUB,
                     QtCore.SIGNAL('clicked()'), self.do_refine_ub)
        self.connect(self.ui.pushButton_resetRefinedUB,
                     QtCore.SIGNAL('clicked()'), self.do_refine_ub)

        # Tab 'Integrate Peaks'
        self.connect(self.ui.pushButton_integratePeak,
                     QtCore.SIGNAL('clicked()'), self.do_integrate_peaks)

        # Menu
        self.connect(self.ui.actionExit, QtCore.SIGNAL('triggered()'),
                     self.menu_quit)

        self.connect(self.ui.actionSave_Session, QtCore.SIGNAL('triggered()'),
                     self.save_current_session)
        self.connect(self.ui.actionLoad_Session, QtCore.SIGNAL('triggered()'),
                     self.load_session)

        # Event handling for tab 'refine ub matrix'
        self.connect(self.ui.pushButton_addToRefine,
                     QtCore.SIGNAL('clicked()'), self.doAddScanPtToRefineUB)

        # Validator ... (NEXT)

        # Declaration of class variable
        # some configuration
        self._homeSrcDir = os.getcwd()
        self._homeDir = os.getcwd()

        # Control
        self._myControl = r4c.CWSCDReductionControl(self._instrument)
        self._allowDownload = True
        self._dataAccessMode = 'Download'

        # Initial setup
        self.ui.tabWidget.setCurrentIndex(0)
        self.ui.tabWidget.setTabEnabled(4, False)
        self.ui.tabWidget.setTabEnabled(5, False)
        self._init_ub_table()
        self.ui.radioButton_ubFromTab1.setChecked(True)

        # Tab 'Access'
        self.ui.lineEdit_url.setText('http://neutron.ornl.gov/user_data/hb3a/')
        self.ui.comboBox_mode.setCurrentIndex(0)
        self.ui.lineEdit_localSpiceDir.setEnabled(True)
        self.ui.pushButton_browseLocalDataDir.setEnabled(True)

        return

    def do_integrate_peaks(self):
        """

        :return:
        """
        raise RuntimeError('ASAP')

    def do_refine_ub(self):
        """

        :return:
        """
        raise RuntimeError('Next Release')

    def _init_ub_table(self):
        """ DOC
        :return:
        """
        # UB-peak table
        # NOTE: have to call this because pyqt set column and row to 0 after __init__
        #       thus a 2-step initialization has to been adopted
        self.ui.tableWidget_peaksCalUB.setup()

        self.ui.tableWidget_ubMatrix.setup()
        self.ui.tableWidget_ubSiceView.setup()
        self.ui.tableWidget_refinedUB.setup()

        self.ui.tableWidget_sliceViewProgress.setup()

        return

    def change_data_access_mode(self):
        """ Change data access mode between downloading from server and local
        Event handling methods
        :return:
        """
        new_mode = str(self.ui.comboBox_mode.currentText())
        self._dataAccessMode = new_mode

        if new_mode.startswith('Local') is True:
            self.ui.lineEdit_localSpiceDir.setEnabled(True)
            self.ui.pushButton_browseLocalDataDir.setEnabled(True)
            self.ui.lineEdit_url.setEnabled(False)
            self.ui.lineEdit_localSrcDir.setEnabled(False)
            self.ui.pushButton_browseLocalCache.setEnabled(False)
            self._allowDownload = False
        else:
            self.ui.lineEdit_localSpiceDir.setEnabled(False)
            self.ui.pushButton_browseLocalDataDir.setEnabled(False)
            self.ui.lineEdit_url.setEnabled(True)
            self.ui.lineEdit_localSrcDir.setEnabled(True)
            self.ui.pushButton_browseLocalCache.setEnabled(True)
            self._allowDownload = True

        return

    def change_instrument_name(self):
        """ Handing the event as the instrument name is changed
        :return:
        """
        new_instrument = str(self.ui.comboBox_instrument.currentText())
        self.pop_one_button_dialog(
            'Change of instrument during data processing is dangerous.')
        status, error_message = self._myControl.set_instrument_name(
            new_instrument)
        if status is False:
            self.pop_one_button_dialog(error_message)

        return

    def do_add_ub_peak(self):
        """ Add current to ub peaks
        :return:
        """
        # Add peak
        status, int_list = gutil.parse_integers_editors([
            self.ui.lineEdit_exp, self.ui.lineEdit_scanNumber,
            self.ui.lineEdit_ptNumber
        ])
        if status is False:
            self.pop_one_button_dialog(int_list)
        exp_no, scan_no, pt_no = int_list

        # Get HKL from GUI
        status, float_list = gutil.parse_float_editors(
            [self.ui.lineEdit_H, self.ui.lineEdit_K, self.ui.lineEdit_L])
        if status is False:
            err_msg = float_list
            self.pop_one_button_dialog(err_msg)
            return
        h, k, l = float_list

        status, peak_info_obj = self._myControl.get_peak_info(
            exp_no, scan_no, pt_no)
        if status is False:
            error_message = peak_info_obj
            self.pop_one_button_dialog(error_message)
            return
        assert isinstance(peak_info_obj, r4c.PeakInfo)

        if self.ui.checkBox_roundHKLInt.isChecked():
            h = math.copysign(1, h) * int(abs(h) + 0.5)
            k = math.copysign(1, k) * int(abs(k) + 0.5)
            l = math.copysign(1, l) * int(abs(l) + 0.5)
        peak_info_obj.set_user_hkl(h, k, l)
        self.set_ub_peak_table(peak_info_obj)

        # Clear
        self.ui.lineEdit_scanNumber.setText('')
        self.ui.lineEdit_ptNumber.setText('')

        self.ui.lineEdit_sampleQx.setText('')
        self.ui.lineEdit_sampleQy.setText('')
        self.ui.lineEdit_sampleQz.setText('')

        self.ui.lineEdit_H.setText('')
        self.ui.lineEdit_K.setText('')
        self.ui.lineEdit_L.setText('')

        return

    def doAcceptCalUB(self):
        """ Accept the calculated UB matrix
        """
        raise RuntimeError('ASAP')
        return

    def doAddScanPtToRefineUB(self):
        """ Add scan/pt numbers to the list of data points for refining ub matrix

        And the added scan number and pt numbers will be reflected in the (left sidebar)

        """
        raise RuntimeError("ASAP")

    def do_add_peak_to_find(self):
        """
        Add the scan/pt to the next
        :return:
        """
        scan_no = self.ui.lineEdit_run.text()
        pt_no = self.ui.lineEdit_rawDataPtNo.text()

        self.ui.lineEdit_scanNumber.setText(scan_no)
        self.ui.lineEdit_ptNumber.setText(pt_no)

        self.ui.tabWidget.setCurrentIndex(2)

    def do_browse_local_cache_dir(self):
        """ Browse local cache directory
        :return:
        """
        local_cache_dir = str(
            QtGui.QFileDialog.getExistingDirectory(
                self, 'Get Local Cache Directory', self._homeSrcDir))

        # Set local directory to control
        status, error_message = self._myControl.set_local_data_dir(
            local_cache_dir)
        if status is False:
            self.pop_one_button_dialog(error_message)
            return

        # Synchronize to local data/spice directory and local cache directory
        if str(self.ui.lineEdit_localSpiceDir.text()) != '':
            prev_dir = str(self.ui.lineEdit_localSrcDir.text())
            self.pop_one_button_dialog(
                'Local data directory was set up as %s' % prev_dir)
        self.ui.lineEdit_localSrcDir.setText(local_cache_dir)
        self.ui.lineEdit_localSpiceDir.setText(local_cache_dir)

        return

    def do_browse_local_spice_data(self):
        """ Browse local source SPICE data directory
        """
        src_spice_dir = str(
            QtGui.QFileDialog.getExistingDirectory(self, 'Get Directory',
                                                   self._homeSrcDir))
        # Set local data directory to controller
        status, error_message = self._myControl.set_local_data_dir(
            src_spice_dir)
        if status is False:
            self.pop_one_button_dialog(error_message)
            return

        self._homeSrcDir = src_spice_dir
        self.ui.lineEdit_localSpiceDir.setText(src_spice_dir)

        return

    def do_browse_working_dir(self):
        """
        Browse and set up working directory
        :return:
        """
        work_dir = str(
            QtGui.QFileDialog.getExistingDirectory(self,
                                                   'Get Working Directory',
                                                   self._homeDir))
        status, error_message = self._myControl.set_working_directory(work_dir)
        if status is False:
            self.pop_one_button_dialog(error_message)
        else:
            self.ui.lineEdit_workDir.setText(work_dir)

        return

    def do_cal_ub_matrix(self):
        """ Calculate UB matrix by 2 or 3 reflections
        """
        # Get reflections
        num_rows = self.ui.tableWidget_peaksCalUB.rowCount()
        peak_info_list = list()
        status, exp_number = gutil.parse_integers_editors(self.ui.lineEdit_exp)
        for i_row in xrange(num_rows):
            if self.ui.tableWidget_peaksCalUB.is_selected(i_row) is True:
                scan_num, pt_num = self.ui.tableWidget_peaksCalUB.get_exp_info(
                    i_row)
                status, peak_info = self._myControl.get_peak_info(
                    exp_number, scan_num, pt_num)
                peak_info.set_peak_ws_hkl_from_user()
                if status is False:
                    self.pop_one_button_dialog(peak_info)
                    return
                assert isinstance(peak_info, r4c.PeakInfo)
                peak_info_list.append(peak_info)
        # END-FOR

        # Get lattice
        status, ret_obj = self._get_lattice_parameters()
        if status is True:
            a, b, c, alpha, beta, gamma = ret_obj
        else:
            err_msg = ret_obj
            self.pop_one_button_dialog(err_msg)
            return

        # Calculate UB matrix
        status, ub_matrix = self._myControl.calculate_ub_matrix(
            peak_info_list, a, b, c, alpha, beta, gamma)

        # Deal with result
        if status is True:
            self._show_ub_matrix(ub_matrix)
        else:
            err_msg = ub_matrix
            self.pop_one_button_dialog(err_msg)

        return

    def do_clear_ub_peaks(self):
        """
        Clear all peaks in UB-Peak table
        :return:
        """
        self.ui.tableWidget_peaksCalUB.clear()

        return

    def do_del_ub_peaks(self):
        """
        Delete a peak in UB-Peak table
        :return:
        """
        # Find out the lines to get deleted
        row_num_list = self.ui.tableWidget_peaksCalUB.get_selected_rows()
        print '[DB] Row %s are selected' % str(row_num_list)

        # Delete
        self.ui.tableWidget_peaksCalUB.delete_rows(row_num_list)

        return

    def do_download_spice_data(self):
        """ Download SPICE data
        :return:
        """
        # Check scans to download
        scan_list_str = str(self.ui.lineEdit_downloadScans.text())
        if len(scan_list_str) > 0:
            # user specifies scans to download
            valid, scan_list = fcutil.parse_int_array(scan_list_str)
            if valid is False:
                error_message = scan_list
                self.pop_one_button_dialog(error_message)
        else:
            # Get all scans
            status, ret_obj = gutil.parse_integers_editors(
                [self.ui.lineEdit_exp])
            if status is False:
                self.pop_one_button_dialog(ret_obj)
                return
            exp_no = ret_obj
            assert isinstance(exp_no, int)
            server_url = str(self.ui.lineEdit_url.text())
            scan_list = fcutil.get_scans_list(server_url,
                                              exp_no,
                                              return_list=True)
        self.pop_one_button_dialog('Going to download scans %s.' %
                                   str(scan_list))

        # Check location
        destination_dir = str(self.ui.lineEdit_localSrcDir.text())
        status, error_message = self._myControl.set_local_data_dir(
            destination_dir)
        if status is False:
            self.pop_one_button_dialog(error_message)
        else:
            self.pop_one_button_dialog(
                'Spice files will be downloaded to %s.' % destination_dir)

        # Set up myControl for downloading data
        exp_no = int(self.ui.lineEdit_exp.text())
        self._myControl.set_exp_number(exp_no)

        server_url = str(self.ui.lineEdit_url.text())
        status, error_message = self._myControl.set_server_url(server_url)
        if status is False:
            self.pop_one_button_dialog(error_message)
            return

        # Download
        self._myControl.download_data_set(scan_list)

        return

    def do_find_peak(self):
        """ Find peak in a given scan/pt and record it
        """
        # Get experiment, scan and pt
        status, ret_obj = gutil.parse_integers_editors([
            self.ui.lineEdit_exp, self.ui.lineEdit_scanNumber,
            self.ui.lineEdit_ptNumber
        ])
        if status is True:
            exp_no, scan_no, pt_no = ret_obj
        else:
            self.pop_one_button_dialog(ret_obj)
            return

        # Find peak
        status, err_msg = self._myControl.find_peak(exp_no, scan_no, pt_no)
        if status is False:
            self.pop_one_button_dialog(ret_obj)
            return
        if self.ui.checkBox_loadHKLfromFile.isChecked() is True:
            # This is the first time that in the workflow to get HKL from MD workspace
            status, err_msg = self._myControl.set_hkl_to_peak(
                exp_no, scan_no, pt_no)
            if status is False:
                self.pop_one_button_dialog(
                    'Unable to locate peak info due to %s.' % err_msg)

        # Set up correct values to table tableWidget_peaksCalUB
        self._myControl.add_peak_info(exp_no, scan_no, pt_no)
        status, peak_info = self._myControl.get_peak_info(
            exp_no, scan_no, pt_no)
        if status is False:
            err_msg = peak_info
            raise KeyError(err_msg)
        assert isinstance(peak_info, r4c.PeakInfo)

        # Set the HKL value from PeakInfo directly
        # BAD PROGRAMMING! THERE ARE TOO MANY WAYS TO ACCESS STORED HKL
        h, k, l = peak_info.get_peak_ws_hkl()
        self.ui.lineEdit_H.setText('%.2f' % h)
        self.ui.lineEdit_K.setText('%.2f' % k)
        self.ui.lineEdit_L.setText('%.2f' % l)

        q_sample = peak_info.getQSample()
        self.ui.lineEdit_sampleQx.setText('%.5E' % q_sample[0])
        self.ui.lineEdit_sampleQy.setText('%.5E' % q_sample[1])
        self.ui.lineEdit_sampleQz.setText('%.5E' % q_sample[2])

        # self.set_ub_peak_table(peak_info)

        return

    def do_index_ub_peaks(self):
        """ Index the peaks in the UB matrix peak table
        :return:
        """
        # Get UB matrix
        ub_matrix = self.ui.tableWidget_ubMatrix.get_matrix()
        print '[DB] Get UB matrix ', ub_matrix

        # Do it for each peak
        num_peaks = self.ui.tableWidget_peaksCalUB.rowCount()
        err_msg = ''
        for i_peak in xrange(num_peaks):
            scan_no, pt_no = self.ui.tableWidget_peaksCalUB.get_exp_info(
                i_peak)
            status, ret_obj = self._myControl.index_peak(ub_matrix,
                                                         scan_number=scan_no,
                                                         pt_number=pt_no)
            if status is True:
                new_hkl = ret_obj[0]
                error = ret_obj[1]
                self.ui.tableWidget_peaksCalUB.set_hkl(i_peak, new_hkl, error)
            else:
                err_msg += ret_obj + '\n'
        # END-FOR

        if len(err_msg) > 0:
            self.pop_one_button_dialog(err_msg)

        return

    def do_list_scans(self):
        """ List all scans available
        :return:
        """
        # Experiment number
        exp_no = int(self.ui.lineEdit_exp.text())

        access_mode = str(self.ui.comboBox_mode.currentText())
        if access_mode == 'Local':
            spice_dir = str(self.ui.lineEdit_localSpiceDir.text())
            message = fcutil.get_scans_list_local_disk(spice_dir, exp_no)
        else:
            url = str(self.ui.lineEdit_url.text())
            message = fcutil.get_scans_list(url, exp_no)

        self.pop_one_button_dialog(message)

        return

    def do_load_scan_info(self):
        """ Load SIICE's scan file
        :return:
        """
        # Get scan number
        status, ret_obj = gutil.parse_integers_editors([self.ui.lineEdit_run])
        if status is True:
            scan_no = ret_obj[0]
        else:
            err_msg = ret_obj
            self.pop_one_button_dialog(
                'Unable to get scan number in raw data tab due to %s.' %
                err_msg)
            return

        status, err_msg = self._myControl.load_spice_scan_file(exp_no=None,
                                                               scan_no=scan_no)
        if status is False:
            self.pop_one_button_dialog(err_msg)

        return

    def do_plot_pt_raw(self):
        """ Plot the Pt.
        """
        # Get measurement pt and the file number
        status, ret_obj = gutil.parse_integers_editors([
            self.ui.lineEdit_exp, self.ui.lineEdit_run,
            self.ui.lineEdit_rawDataPtNo
        ])
        if status is True:
            exp_no = ret_obj[0]
            scan_no = ret_obj[1]
            pt_no = ret_obj[2]
        else:
            self.pop_one_button_dialog(ret_obj)
            return

        # Call to plot 2D
        self._plot_raw_xml_2d(exp_no, scan_no, pt_no)

        return

    def do_plot_prev_pt_raw(self):
        """ Plot the Pt.
        """
        # Get measurement pt and the file number
        status, ret_obj = gutil.parse_integers_editors([
            self.ui.lineEdit_exp, self.ui.lineEdit_run,
            self.ui.lineEdit_rawDataPtNo
        ])
        if status is True:
            exp_no = ret_obj[0]
            scan_no = ret_obj[1]
            pt_no = ret_obj[2]
        else:
            self.pop_one_button_dialog(ret_obj)
            return

        # Previous one
        pt_no -= 1
        if pt_no <= 0:
            self.pop_one_button_dialog('Pt. = 1 is the first one.')
            return
        else:
            self.ui.lineEdit_rawDataPtNo.setText('%d' % pt_no)

        # Plot
        self._plot_raw_xml_2d(exp_no, scan_no, pt_no)

        return

    def do_plot_next_pt_raw(self):
        """ Plot the Pt.
        """
        # Get measurement pt and the file number
        status, ret_obj = gutil.parse_integers_editors([
            self.ui.lineEdit_exp, self.ui.lineEdit_run,
            self.ui.lineEdit_rawDataPtNo
        ])
        if status is True:
            exp_no = ret_obj[0]
            scan_no = ret_obj[1]
            pt_no = ret_obj[2]
        else:
            self.pop_one_button_dialog(ret_obj)
            return

        # Previous one
        pt_no += 1
        # get last Pt. number
        status, last_pt_no = self._myControl.get_pt_numbers(exp_no, scan_no)
        if status is False:
            error_message = last_pt_no
            self.pop_one_button_dialog(
                'Unable to access Spice table for scan %d. Reason" %s.' %
                (scan_no, error_message))
        if pt_no > last_pt_no:
            self.pop_one_button_dialog('Pt. = %d is the last one of scan %d.' %
                                       (pt_no, scan_no))
            return
        else:
            self.ui.lineEdit_rawDataPtNo.setText('%d' % pt_no)

        # Plot
        self._plot_raw_xml_2d(exp_no, scan_no, pt_no)

        return

    def do_merge_scans(self):
        """ Process data for slicing view
        :return:
        """
        # Get UB matrix
        ub_matrix = self.ui.tableWidget_ubSiceView.get_matrix()
        self._myControl.set_ub_matrix(exp_number=None, ub_matrix=ub_matrix)

        # Get list of scans
        scan_list = gutil.parse_integer_list(
            str(self.ui.lineEdit_listScansSliceView.text()))
        if len(scan_list) == 0:
            self.pop_one_button_dialog('Scan list is empty.')

        # Set table
        self.ui.tableWidget_sliceViewProgress.append_scans(scans=scan_list)

        # Warning
        self.pop_one_button_dialog('Data processing is long. Be patient!')

        # Process
        base_name = str(self.ui.lineEdit_baseMergeMDName.text())
        scan_list.sort()
        frame = str(self.ui.comboBox_mergeScanFrame.currentText())
        for scan_no in scan_list:
            # Download/check SPICE file
            self._myControl.download_spice_file(None,
                                                scan_no,
                                                over_write=False)

            # Get some information
            status, pt_list = self._myControl.get_pt_numbers(
                None, scan_no, load_spice_scan=True)
            if status is False:
                err_msg = pt_list
                self.pop_one_button_dialog('Failed to get Pt. number: %s' %
                                           err_msg)
                return
            else:
                # Set information to table
                err_msg = self.ui.tableWidget_sliceViewProgress.set_scan_pt(
                    scan_no, pt_list)
                if len(err_msg) > 0:
                    self.pop_one_button_dialog(err_msg)

            out_ws_name = base_name + '%04d' % scan_no
            self.ui.tableWidget_sliceViewProgress.set_scan_pt(
                scan_no, 'In Processing')
            try:
                ret_tup = self._myControl.merge_pts_in_scan(
                    exp_no=None,
                    scan_no=scan_no,
                    target_ws_name=out_ws_name,
                    target_frame=frame)
                merge_status = 'Done'
                merged_name = ret_tup[0]
                group_name = ret_tup[1]
            except RuntimeError as e:
                merge_status = 'Failed. Reason: %s' % str(e)
                merged_name = ''
                group_name = ''
            finally:
                self.ui.tableWidget_sliceViewProgress.set_status(
                    scan_no, merge_status)
                self.ui.tableWidget_sliceViewProgress.set_ws_names(
                    scan_no, merged_name, group_name)

            # Sleep for a while
            time.sleep(0.1)
        # END-FOR

        return

    def do_reset_ub_peaks_hkl(self):
        """
        Reset user specified HKL value to peak table
        :return:
        """
        num_rows = self.ui.tableWidget_peaksCalUB.rowCount()
        for i_row in xrange(num_rows):
            print '[DB] Update row %d' % (i_row)
            scan, pt = self.ui.tableWidget_peaksCalUB.get_scan_pt(i_row)
            status, peak_info = self._myControl.get_peak_info(None, scan, pt)
            if status is False:
                error_message = peak_info
                raise RuntimeError(error_message)
            h, k, l = peak_info.get_user_hkl()
            self.ui.tableWidget_peaksCalUB.update_hkl(i_row, h, k, l)
        # END-FOR

        return

    def do_set_experiment(self):
        """ Set experiment
        :return:
        """
        status, ret_obj = gutil.parse_integers_editors([self.ui.lineEdit_exp])
        if status is True:
            exp_number = ret_obj[0]
            curr_exp_number = self._myControl.get_experiment()
            if curr_exp_number is not None and exp_number != curr_exp_number:
                self.pop_one_button_dialog(
                    'Changing experiment to %d.  Clean previous experiment %d\'s result'
                    ' in Mantid manually.' % (exp_number, curr_exp_number))
            self._myControl.set_exp_number(exp_number)
            self.ui.lineEdit_exp.setStyleSheet('color: black')
        else:
            err_msg = ret_obj
            self.pop_one_button_dialog('Unable to set experiment as %s' %
                                       err_msg)
            self.ui.lineEdit_exp.setStyleSheet('color: red')

        self.ui.tabWidget.setCurrentIndex(0)

        return

    def do_set_ub_sv(self):
        """ Set UB matrix in Slice view
        :return:
        """
        if self.ui.radioButton_ubFromTab1.isChecked():
            self.ui.tableWidget_ubSiceView.set_from_matrix(
                self.ui.tableWidget_ubMatrix.get_matrix())
        elif self.ui.radioButton_ubFromTab3.isChecked():
            self.ui.tableWidget_ubSiceView.set_from_matrix(
                self.ui.tableWidget_refinedUB.get_matrix())
        elif self.ui.radioButton_ubFromList.isChecked():
            status, ret_obj = gutil.parse_float_array(
                str(self.ui.plainTextEdit_ubInput.toPlainText()))
            if status is False:
                self.pop_one_button_dialog(ret_obj)
            elif len(ret_obj) != 9:
                self.pop_one_button_dialog(
                    'Requiring 9 floats for UB matrix.  Only %d are given.' %
                    len(ret_obj))
            else:
                self.ui.tableWidget_ubSiceView.set_from_list(ret_obj)
        else:
            self.pop_one_button_dialog('None is selected to set UB matrix.')

        return

    def do_setup_dir_default(self):
        """
        Set up default directory for storing data and working
        :return:
        """
        home_dir = os.path.expanduser('~')

        # Data cache directory
        data_cache_dir = os.path.join(home_dir, 'Temp/HB3ATest')
        self.ui.lineEdit_localSpiceDir.setText(data_cache_dir)
        self.ui.lineEdit_localSrcDir.setText(data_cache_dir)

        work_dir = os.path.join(data_cache_dir, 'Workspace')
        self.ui.lineEdit_workDir.setText(work_dir)

        return

    def do_apply_setup(self):
        """
        Apply set up ...
        :return:
        """
        # Local data directory
        local_data_dir = str(self.ui.lineEdit_localSpiceDir.text())
        if os.path.exists(local_data_dir) is False:
            try:
                os.mkdir(local_data_dir)
            except OSError as os_error:
                self.pop_one_button_dialog(
                    'Unable to create local data directory %s due to %s.' %
                    (local_data_dir, str(os_error)))
                self.ui.lineEdit_localSpiceDir.setStyleSheet("color: red;")
                return
            else:
                self.ui.lineEdit_localSpiceDir.setStyleSheet("color: black;")
        # END-IF

        # Working directory
        working_dir = str(self.ui.lineEdit_workDir.text())
        if os.path.exists(working_dir) is False:
            try:
                os.mkdir(working_dir)
            except OSError as os_error:
                self.pop_one_button_dialog(
                    'Unable to create working directory %s due to %s.' %
                    (working_dir, str(os_error)))
                self.ui.lineEdit_workDir.setStyleSheet("color: red;")
                return
            else:
                self.ui.lineEdit_workDir.setStyleSheet("color: black;")
        # END-IF

        # Server URL
        data_server = str(self.ui.lineEdit_url.text())
        url_is_good = self.do_test_url()
        if url_is_good is False:
            self.ui.lineEdit_url.setStyleSheet("color: red;")
            return
        else:
            self.ui.lineEdit_url.setStyleSheet("color: black;")

        # Set to control
        self._myControl.set_local_data_dir(local_data_dir)
        self._myControl.set_working_directory(working_dir)
        self._myControl.set_server_url(data_server)

        return

    def do_test_url(self):
        """ Test whether the root URL provided specified is good
        """
        url = str(self.ui.lineEdit_url.text())

        url_is_good, err_msg = fcutil.check_url(url)
        if url_is_good is True:
            self.pop_one_button_dialog("URL %s is valid." % url)
        else:
            self.pop_one_button_dialog(err_msg)

        return url_is_good

    def pop_one_button_dialog(self, message):
        """ Pop up a one-button dialog
        :param message:
        :return:
        """
        assert isinstance(message, str)
        QtGui.QMessageBox.information(self, '4-circle Data Reduction', message)

        return

    def save_current_session(self, filename=None):
        """ Save current session/value setup to
        :return:
        """
        # Set up dictionary
        save_dict = dict()

        # Setup
        save_dict['lineEdit_localSpiceDir'] = str(
            self.ui.lineEdit_localSpiceDir.text())
        save_dict['lineEdit_url'] = str(self.ui.lineEdit_url.text())
        save_dict['lineEdit_workDir'] = str(self.ui.lineEdit_workDir.text())

        # Experiment
        save_dict['lineEdit_exp'] = str(self.ui.lineEdit_exp.text())
        save_dict['lineEdit_scanNumber'] = self.ui.lineEdit_scanNumber.text()
        save_dict['lineEdit_ptNumber'] = str(self.ui.lineEdit_ptNumber.text())

        # Lattice
        save_dict['lineEdit_a'] = str(self.ui.lineEdit_a.text())
        save_dict['lineEdit_b'] = str(self.ui.lineEdit_b.text())
        save_dict['lineEdit_c'] = str(self.ui.lineEdit_c.text())
        save_dict['lineEdit_alpha'] = str(self.ui.lineEdit_alpha.text())
        save_dict['lineEdit_beta'] = str(self.ui.lineEdit_beta.text())
        save_dict['lineEdit_gamma'] = str(self.ui.lineEdit_gamma.text())

        # Merge scan
        save_dict['plainTextEdit_ubInput'] = str(
            self.ui.plainTextEdit_ubInput.toPlainText())
        save_dict['lineEdit_listScansSliceView'] = str(
            self.ui.lineEdit_listScansSliceView.text())
        save_dict['lineEdit_baseMergeMDName'] = str(
            self.ui.lineEdit_baseMergeMDName.text())

        # Save to csv file
        if filename is None:
            filename = 'session_backup.csv'
        ofile = open(filename, 'w')
        writer = csv.writer(ofile)
        for key, value in save_dict.items():
            writer.writerow([key, value])
        ofile.close()

        return

    def load_session(self, filename=None):
        """
        To load a session, i.e., read it back:
        :param filename:
        :return:
        """
        if filename is None:
            filename = 'session_backup.csv'

        in_file = open(filename, 'r')
        reader = csv.reader(in_file)
        my_dict = dict(x for x in reader)

        # ...
        for key, value in my_dict.items():
            if key.startswith('lineEdit') is True:
                self.ui.__getattribute__(key).setText(value)
            elif key.startswith('plainText') is True:
                self.ui.__getattribute__(key).setPlainText(value)
            elif key.startswith('comboBox') is True:
                self.ui.__getattribute__(key).setCurrentIndex(int(value))
            else:
                self.pop_one_button_dialog(
                    'Error! Widget name %s is not supported' % key)
        # END-FOR

        # ...
        self._myControl.set_local_data_dir(
            str(self.ui.lineEdit_localSpiceDir.text()))

        return

    def menu_quit(self):
        """

        :return:
        """
        self.close()

    def show_scan_pt_list(self):
        """ Show the range of Pt. in a scan
        :return:
        """
        # Get parameters
        status, inp_list = gutil.parse_integers_editors(
            [self.ui.lineEdit_exp, self.ui.lineEdit_run])
        if status is False:
            self.pop_one_button_dialog(inp_list)
            return
        else:
            exp_no = inp_list[0]
            scan_no = inp_list[1]

        status, ret_obj = self._myControl.get_pt_numbers(exp_no, scan_no)

        # Form message
        if status is False:
            # Failed to get Pt. list
            error_message = ret_obj
            self.pop_one_button_dialog(error_message)
        else:
            # Form message
            pt_list = sorted(ret_obj)
            num_pts = len(pt_list)
            info = 'Exp %d Scan %d has %d Pt. ranging from %d to %d.\n' % (
                exp_no, scan_no, num_pts, pt_list[0], pt_list[-1])
            num_miss_pt = pt_list[-1] - pt_list[0] + 1 - num_pts
            if num_miss_pt > 0:
                info += 'There are %d Pt. skipped.\n' % num_miss_pt

            self.pop_one_button_dialog(info)

        return

    def set_ub_peak_table(self, peakinfo):
        """
        DOC
        :param peak_info:
        :return:
        """
        assert isinstance(peakinfo, r4c.PeakInfo)

        # Get data
        exp_number, scan_number, pt_number = peakinfo.getExpInfo()
        h, k, l = peakinfo.get_user_hkl()
        q_sample = peakinfo.getQSample()
        m1 = self._myControl.get_sample_log_value(exp_number, scan_number,
                                                  pt_number, '_m1')

        # Set to table
        status, err_msg = self.ui.tableWidget_peaksCalUB.append_row([
            scan_number, pt_number, h, k, l, q_sample[0], q_sample[1],
            q_sample[2], False, m1, ''
        ])
        if status is False:
            self.pop_one_button_dialog(err_msg)

        return

    def _get_lattice_parameters(self):
        """
        Get lattice parameters from GUI
        :return: (Boolean, Object).  True, 6-tuple as a, b, c, alpha, beta, gamm
                                     False: error message
        """
        status, ret_list = gutil.parse_float_editors([
            self.ui.lineEdit_a, self.ui.lineEdit_b, self.ui.lineEdit_c,
            self.ui.lineEdit_alpha, self.ui.lineEdit_beta,
            self.ui.lineEdit_gamma
        ])
        if status is False:
            err_msg = ret_list
            err_msg = 'Unable to parse unit cell due to %s' % err_msg
            return False, err_msg

        a, b, c, alpha, beta, gamma = ret_list

        return True, (a, b, c, alpha, beta, gamma)

    def _plot_raw_xml_2d(self, exp_no, scan_no, pt_no):
        """ Plot raw workspace from XML file for a measurement/pt.
        """
        # Check and load SPICE table file
        does_exist = self._myControl.does_spice_loaded(exp_no, scan_no)
        if does_exist is False:
            # Download data
            status, error_message = self._myControl.download_spice_file(
                exp_no, scan_no, over_write=False)
            if status is True:
                status, error_message = self._myControl.load_spice_scan_file(
                    exp_no, scan_no)
                if status is False and self._allowDownload is False:
                    self.pop_one_button_dialog(error_message)
                    return
            else:
                self.pop_one_button_dialog(error_message)
                return
        # END-IF(does_exist)

        # Load Data for Pt's xml file
        does_exist = self._myControl.does_raw_loaded(exp_no, scan_no, pt_no)

        if does_exist is False:
            # Check whether needs to download
            status, error_message = self._myControl.download_spice_xml_file(
                scan_no, pt_no, exp_no=exp_no)
            if status is False:
                self.pop_one_button_dialog(error_message)
                return
            # Load SPICE xml file
            status, error_message = self._myControl.load_spice_xml_file(
                exp_no, scan_no, pt_no)
            if status is False:
                self.pop_one_button_dialog(error_message)
                return

        # Convert a list of vector to 2D numpy array for imshow()
        # Get data and plot
        raw_det_data = self._myControl.get_raw_detector_counts(
            exp_no, scan_no, pt_no)
        self.ui.graphicsView.clear_canvas()
        self.ui.graphicsView.add_plot_2d(raw_det_data,
                                         x_min=0,
                                         x_max=256,
                                         y_min=0,
                                         y_max=256,
                                         hold_prev_image=False)

        return

    def _show_ub_matrix(self, ubmatrix):
        """ Show UB matrix
        :param ubmatrix:
        :return:
        """
        assert ubmatrix.shape == (3, 3)

        self.ui.tableWidget_ubMatrix.set_from_matrix(ubmatrix)

        return
Esempio n. 2
0
class MainWindow(QtGui.QMainWindow):
    """ Class of Main Window (top)
    """
    def __init__(self, parent=None):
        """ Initialization and set up
        """
        # Base class
        QtGui.QMainWindow.__init__(self,parent)

        # UI Window (from Qt Designer)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        # Make UI scrollable
        self._scrollbars = MantidQt.API.WidgetScrollbarDecorator(self)
        self._scrollbars.setEnabled(True) # Must follow after setupUi(self)!

        # Mantid configuration
        self._instrument = str(self.ui.comboBox_instrument.currentText())
        # config = ConfigService.Instance()
        # self._instrument = config["default.instrument"]

        # Event handling definitions
        # Top
        self.connect(self.ui.pushButton_setExp, QtCore.SIGNAL('clicked()'),
                     self.do_set_experiment)

        # Tab 'Data Access'
        self.connect(self.ui.pushButton_applySetup, QtCore.SIGNAL('clicked()'),
                     self.do_apply_setup)
        self.connect(self.ui.pushButton_browseLocalDataDir, QtCore.SIGNAL('clicked()'),
                     self.do_browse_local_spice_data)
        self.connect(self.ui.pushButton_testURLs, QtCore.SIGNAL('clicked()'),
                     self.do_test_url)
        self.connect(self.ui.pushButton_ListScans, QtCore.SIGNAL('clicked()'),
                     self.do_list_scans)
        self.connect(self.ui.pushButton_downloadExpData, QtCore.SIGNAL('clicked()'),
                     self.do_download_spice_data)
        self.connect(self.ui.comboBox_mode, QtCore.SIGNAL('currentIndexChanged(int)'),
                     self.change_data_access_mode)

        # Tab 'View Raw Data'
        self.connect(self.ui.pushButton_setScanInfo, QtCore.SIGNAL('clicked()'),
                     self.do_load_scan_info)
        self.connect(self.ui.pushButton_plotRawPt, QtCore.SIGNAL('clicked()'),
                     self.do_plot_pt_raw)
        self.connect(self.ui.pushButton_prevPtNumber, QtCore.SIGNAL('clicked()'),
                     self.do_plot_prev_pt_raw)
        self.connect(self.ui.pushButton_nextPtNumber, QtCore.SIGNAL('clicked()'),
                     self.do_plot_next_pt_raw)
        self.connect(self.ui.pushButton_showPtList, QtCore.SIGNAL('clicked()'),
                     self.show_scan_pt_list)
        self.connect(self.ui.pushButton_usePt4UB, QtCore.SIGNAL('clicked()'),
                     self.do_add_peak_to_find)

        # Tab 'calculate ub matrix'
        self.connect(self.ui.pushButton_findPeak, QtCore.SIGNAL('clicked()'),
                     self.do_find_peak)
        self.connect(self.ui.pushButton_addPeakToCalUB, QtCore.SIGNAL('clicked()'),
                     self.do_add_ub_peak)
        self.connect(self.ui.pushButton_calUB, QtCore.SIGNAL('clicked()'),
                     self.do_cal_ub_matrix)
        self.connect(self.ui.pushButton_acceptUB, QtCore.SIGNAL('clicked()'),
                     self.doAcceptCalUB)
        self.connect(self.ui.pushButton_indexUBPeaks, QtCore.SIGNAL('clicked()'),
                     self.do_index_ub_peaks)
        self.connect(self.ui.pushButton_deleteUBPeak, QtCore.SIGNAL('clicked()'),
                     self.do_del_ub_peaks)
        self.connect(self.ui.pushButton_clearUBPeakTable, QtCore.SIGNAL('clicked()'),
                     self.do_clear_ub_peaks)
        self.connect(self.ui.pushButton_resetPeakHKLs, QtCore.SIGNAL('clicked()'),
                     self.do_reset_ub_peaks_hkl)

        # Tab 'Slice View'
        self.connect(self.ui.pushButton_setUBSliceView, QtCore.SIGNAL('clicked()'),
                     self.do_set_ub_sv)
        self.connect(self.ui.pushButton_process4SliceView, QtCore.SIGNAL('clicked()'),
                     self.do_merge_scans)

        # Tab 'Advanced'
        self.connect(self.ui.pushButton_useDefaultDir, QtCore.SIGNAL('clicked()'),
                     self.do_setup_dir_default)
        self.connect(self.ui.pushButton_browseLocalCache, QtCore.SIGNAL('clicked()'),
                     self.do_browse_local_cache_dir)
        self.connect(self.ui.pushButton_browseWorkDir, QtCore.SIGNAL('clicked()'),
                     self.do_browse_working_dir)
        self.connect(self.ui.comboBox_instrument, QtCore.SIGNAL('currentIndexChanged(int)'),
                     self.change_instrument_name)

        # Refine UB matrix
        self.connect(self.ui.pushButton_addToRefine, QtCore.SIGNAL('clicked()'),
                     self.do_refine_ub)
        self.connect(self.ui.pushButton_addAllRefineUB, QtCore.SIGNAL('clicked()'),
                     self.do_refine_ub)
        self.connect(self.ui.pushButton_acceptRefinedUB, QtCore.SIGNAL('clicked()'),
                     self.do_refine_ub)
        self.connect(self.ui.pushButton_resetRefinedUB, QtCore.SIGNAL('clicked()'),
                     self.do_refine_ub)

        # Tab 'Integrate Peaks'
        self.connect(self.ui.pushButton_integratePeak, QtCore.SIGNAL('clicked()'),
                     self.do_integrate_peaks)

        # Menu
        self.connect(self.ui.actionExit, QtCore.SIGNAL('triggered()'),
                     self.menu_quit)

        self.connect(self.ui.actionSave_Session, QtCore.SIGNAL('triggered()'),
                     self.save_current_session)
        self.connect(self.ui.actionLoad_Session, QtCore.SIGNAL('triggered()'),
                     self.load_session)

        # Event handling for tab 'refine ub matrix'
        self.connect(self.ui.pushButton_addToRefine, QtCore.SIGNAL('clicked()'),
                     self.doAddScanPtToRefineUB)

        # Validator ... (NEXT)

        # Declaration of class variable
        # some configuration
        self._homeSrcDir = os.getcwd()
        self._homeDir = os.getcwd()

        # Control
        self._myControl = r4c.CWSCDReductionControl(self._instrument)
        self._allowDownload = True
        self._dataAccessMode = 'Download'

        # Initial setup
        self.ui.tabWidget.setCurrentIndex(0)
        self.ui.tabWidget.setTabEnabled(4, False)
        self.ui.tabWidget.setTabEnabled(5, False)
        self._init_ub_table()
        self.ui.radioButton_ubFromTab1.setChecked(True)

        # Tab 'Access'
        self.ui.lineEdit_url.setText('http://neutron.ornl.gov/user_data/hb3a/')
        self.ui.comboBox_mode.setCurrentIndex(0)
        self.ui.lineEdit_localSpiceDir.setEnabled(True)
        self.ui.pushButton_browseLocalDataDir.setEnabled(True)

        return

    def do_integrate_peaks(self):
        """

        :return:
        """
        raise RuntimeError('ASAP')

    def do_refine_ub(self):
        """

        :return:
        """
        raise RuntimeError('Next Release')

    def _init_ub_table(self):
        """ DOC
        :return:
        """
        # UB-peak table
        # NOTE: have to call this because pyqt set column and row to 0 after __init__
        #       thus a 2-step initialization has to been adopted
        self.ui.tableWidget_peaksCalUB.setup()

        self.ui.tableWidget_ubMatrix.setup()
        self.ui.tableWidget_ubSiceView.setup()
        self.ui.tableWidget_refinedUB.setup()

        self.ui.tableWidget_sliceViewProgress.setup()

        return

    def change_data_access_mode(self):
        """ Change data access mode between downloading from server and local
        Event handling methods
        :return:
        """
        new_mode = str(self.ui.comboBox_mode.currentText())
        self._dataAccessMode = new_mode

        if new_mode.startswith('Local') is True:
            self.ui.lineEdit_localSpiceDir.setEnabled(True)
            self.ui.pushButton_browseLocalDataDir.setEnabled(True)
            self.ui.lineEdit_url.setEnabled(False)
            self.ui.lineEdit_localSrcDir.setEnabled(False)
            self.ui.pushButton_browseLocalCache.setEnabled(False)
            self._allowDownload = False
        else:
            self.ui.lineEdit_localSpiceDir.setEnabled(False)
            self.ui.pushButton_browseLocalDataDir.setEnabled(False)
            self.ui.lineEdit_url.setEnabled(True)
            self.ui.lineEdit_localSrcDir.setEnabled(True)
            self.ui.pushButton_browseLocalCache.setEnabled(True)
            self._allowDownload = True

        return

    def change_instrument_name(self):
        """ Handing the event as the instrument name is changed
        :return:
        """
        new_instrument = str(self.ui.comboBox_instrument.currentText())
        self.pop_one_button_dialog('Change of instrument during data processing is dangerous.')
        status, error_message = self._myControl.set_instrument_name(new_instrument)
        if status is False:
            self.pop_one_button_dialog(error_message)

        return

    def do_add_ub_peak(self):
        """ Add current to ub peaks
        :return:
        """
        # Add peak
        status, int_list = gutil.parse_integers_editors([self.ui.lineEdit_exp,
                                                         self.ui.lineEdit_scanNumber,
                                                         self.ui.lineEdit_ptNumber])
        if status is False:
            self.pop_one_button_dialog(int_list)
        exp_no, scan_no, pt_no = int_list

        # Get HKL from GUI
        status, float_list = gutil.parse_float_editors([self.ui.lineEdit_H,
                                                        self.ui.lineEdit_K,
                                                        self.ui.lineEdit_L])
        if status is False:
            err_msg = float_list
            self.pop_one_button_dialog(err_msg)
            return
        h, k, l = float_list

        status, peak_info_obj = self._myControl.get_peak_info(exp_no, scan_no, pt_no)
        if status is False:
            error_message = peak_info_obj
            self.pop_one_button_dialog(error_message)
            return
        assert isinstance(peak_info_obj, r4c.PeakInfo)

        if self.ui.checkBox_roundHKLInt.isChecked():
            h = math.copysign(1, h)*int(abs(h)+0.5)
            k = math.copysign(1, k)*int(abs(k)+0.5)
            l = math.copysign(1, l)*int(abs(l)+0.5)
        peak_info_obj.set_user_hkl(h, k, l)
        self.set_ub_peak_table(peak_info_obj)

        # Clear
        self.ui.lineEdit_scanNumber.setText('')
        self.ui.lineEdit_ptNumber.setText('')

        self.ui.lineEdit_sampleQx.setText('')
        self.ui.lineEdit_sampleQy.setText('')
        self.ui.lineEdit_sampleQz.setText('')

        self.ui.lineEdit_H.setText('')
        self.ui.lineEdit_K.setText('')
        self.ui.lineEdit_L.setText('')

        return

    def doAcceptCalUB(self):
        """ Accept the calculated UB matrix
        """
        raise RuntimeError('ASAP')
        return

    def doAddScanPtToRefineUB(self):
        """ Add scan/pt numbers to the list of data points for refining ub matrix

        And the added scan number and pt numbers will be reflected in the (left sidebar)

        """
        raise RuntimeError("ASAP")

    def do_add_peak_to_find(self):
        """
        Add the scan/pt to the next
        :return:
        """
        scan_no = self.ui.lineEdit_run.text()
        pt_no = self.ui.lineEdit_rawDataPtNo.text()

        self.ui.lineEdit_scanNumber.setText(scan_no)
        self.ui.lineEdit_ptNumber.setText(pt_no)

        self.ui.tabWidget.setCurrentIndex(2)

    def do_browse_local_cache_dir(self):
        """ Browse local cache directory
        :return:
        """
        local_cache_dir = str(QtGui.QFileDialog.getExistingDirectory(self,
                                                                     'Get Local Cache Directory',
                                                                     self._homeSrcDir))

        # Set local directory to control
        status, error_message = self._myControl.set_local_data_dir(local_cache_dir)
        if status is False:
            self.pop_one_button_dialog(error_message)
            return

        # Synchronize to local data/spice directory and local cache directory
        if str(self.ui.lineEdit_localSpiceDir.text()) != '':
            prev_dir = str(self.ui.lineEdit_localSrcDir.text())
            self.pop_one_button_dialog('Local data directory was set up as %s' %
                                       prev_dir)
        self.ui.lineEdit_localSrcDir.setText(local_cache_dir)
        self.ui.lineEdit_localSpiceDir.setText(local_cache_dir)

        return

    def do_browse_local_spice_data(self):
        """ Browse local source SPICE data directory
        """
        src_spice_dir = str(QtGui.QFileDialog.getExistingDirectory(self, 'Get Directory',
                                                                   self._homeSrcDir))
        # Set local data directory to controller
        status, error_message = self._myControl.set_local_data_dir(src_spice_dir)
        if status is False:
            self.pop_one_button_dialog(error_message)
            return

        self._homeSrcDir = src_spice_dir
        self.ui.lineEdit_localSpiceDir.setText(src_spice_dir)

        return

    def do_browse_working_dir(self):
        """
        Browse and set up working directory
        :return:
        """
        work_dir = str(QtGui.QFileDialog.getExistingDirectory(self, 'Get Working Directory', self._homeDir))
        status, error_message = self._myControl.set_working_directory(work_dir)
        if status is False:
            self.pop_one_button_dialog(error_message)
        else:
            self.ui.lineEdit_workDir.setText(work_dir)

        return

    def do_cal_ub_matrix(self):
        """ Calculate UB matrix by 2 or 3 reflections
        """
        # Get reflections
        num_rows = self.ui.tableWidget_peaksCalUB.rowCount()
        peak_info_list = list()
        status, exp_number = gutil.parse_integers_editors(self.ui.lineEdit_exp)
        for i_row in xrange(num_rows):
            if self.ui.tableWidget_peaksCalUB.is_selected(i_row) is True:
                scan_num, pt_num = self.ui.tableWidget_peaksCalUB.get_exp_info(i_row)
                status, peak_info = self._myControl.get_peak_info(exp_number, scan_num, pt_num)
                peak_info.set_peak_ws_hkl_from_user()
                if status is False:
                    self.pop_one_button_dialog(peak_info)
                    return
                assert isinstance(peak_info, r4c.PeakInfo)
                peak_info_list.append(peak_info)
        # END-FOR

        # Get lattice
        status, ret_obj = self._get_lattice_parameters()
        if status is True:
            a, b, c, alpha, beta, gamma = ret_obj
        else:
            err_msg = ret_obj
            self.pop_one_button_dialog(err_msg)
            return

        # Calculate UB matrix
        status, ub_matrix = self._myControl.calculate_ub_matrix(peak_info_list, a, b, c,
                                                                alpha, beta, gamma)

        # Deal with result
        if status is True:
            self._show_ub_matrix(ub_matrix)
        else:
            err_msg = ub_matrix
            self.pop_one_button_dialog(err_msg)

        return

    def do_clear_ub_peaks(self):
        """
        Clear all peaks in UB-Peak table
        :return:
        """
        self.ui.tableWidget_peaksCalUB.clear()

        return

    def do_del_ub_peaks(self):
        """
        Delete a peak in UB-Peak table
        :return:
        """
        # Find out the lines to get deleted
        row_num_list = self.ui.tableWidget_peaksCalUB.get_selected_rows()
        print '[DB] Row %s are selected' % str(row_num_list)

        # Delete
        self.ui.tableWidget_peaksCalUB.delete_rows(row_num_list)

        return

    def do_download_spice_data(self):
        """ Download SPICE data
        :return:
        """
        # Check scans to download
        scan_list_str = str(self.ui.lineEdit_downloadScans.text())
        if len(scan_list_str) > 0:
            # user specifies scans to download
            valid, scan_list = fcutil.parse_int_array(scan_list_str)
            if valid is False:
                error_message = scan_list
                self.pop_one_button_dialog(error_message)
        else:
            # Get all scans
            status, ret_obj = gutil.parse_integers_editors([self.ui.lineEdit_exp])
            if status is False:
                self.pop_one_button_dialog(ret_obj)
                return
            exp_no = ret_obj
            assert isinstance(exp_no, int)
            server_url = str(self.ui.lineEdit_url.text())
            scan_list = fcutil.get_scans_list(server_url, exp_no, return_list=True)
        self.pop_one_button_dialog('Going to download scans %s.' % str(scan_list))

        # Check location
        destination_dir = str(self.ui.lineEdit_localSrcDir.text())
        status, error_message = self._myControl.set_local_data_dir(destination_dir)
        if status is False:
            self.pop_one_button_dialog(error_message)
        else:
            self.pop_one_button_dialog('Spice files will be downloaded to %s.' % destination_dir)

        # Set up myControl for downloading data
        exp_no = int(self.ui.lineEdit_exp.text())
        self._myControl.set_exp_number(exp_no)

        server_url = str(self.ui.lineEdit_url.text())
        status, error_message = self._myControl.set_server_url(server_url)
        if status is False:
            self.pop_one_button_dialog(error_message)
            return

        # Download
        self._myControl.download_data_set(scan_list)

        return

    def do_find_peak(self):
        """ Find peak in a given scan/pt and record it
        """
        # Get experiment, scan and pt
        status, ret_obj = gutil.parse_integers_editors([self.ui.lineEdit_exp,
                                                        self.ui.lineEdit_scanNumber,
                                                        self.ui.lineEdit_ptNumber])
        if status is True:
            exp_no, scan_no, pt_no = ret_obj
        else:
            self.pop_one_button_dialog(ret_obj)
            return

        # Find peak
        status, err_msg = self._myControl.find_peak(exp_no, scan_no, pt_no)
        if status is False:
            self.pop_one_button_dialog(ret_obj)
            return
        if self.ui.checkBox_loadHKLfromFile.isChecked() is True:
            # This is the first time that in the workflow to get HKL from MD workspace
            status, err_msg = self._myControl.set_hkl_to_peak(exp_no, scan_no, pt_no)
            if status is False:
                self.pop_one_button_dialog('Unable to locate peak info due to %s.' % err_msg)

        # Set up correct values to table tableWidget_peaksCalUB
        self._myControl.add_peak_info(exp_no, scan_no, pt_no)
        status, peak_info = self._myControl.get_peak_info(exp_no, scan_no, pt_no)
        if status is False:
            err_msg = peak_info
            raise KeyError(err_msg)
        assert isinstance(peak_info, r4c.PeakInfo)

        # Set the HKL value from PeakInfo directly
        # BAD PROGRAMMING! THERE ARE TOO MANY WAYS TO ACCESS STORED HKL
        h, k, l = peak_info.get_peak_ws_hkl()
        self.ui.lineEdit_H.setText('%.2f' % h)
        self.ui.lineEdit_K.setText('%.2f' % k)
        self.ui.lineEdit_L.setText('%.2f' % l)

        q_sample = peak_info.getQSample()
        self.ui.lineEdit_sampleQx.setText('%.5E' % q_sample[0])
        self.ui.lineEdit_sampleQy.setText('%.5E' % q_sample[1])
        self.ui.lineEdit_sampleQz.setText('%.5E' % q_sample[2])

        # self.set_ub_peak_table(peak_info)

        return

    def do_index_ub_peaks(self):
        """ Index the peaks in the UB matrix peak table
        :return:
        """
        # Get UB matrix
        ub_matrix = self.ui.tableWidget_ubMatrix.get_matrix()
        print '[DB] Get UB matrix ', ub_matrix

        # Do it for each peak
        num_peaks = self.ui.tableWidget_peaksCalUB.rowCount()
        err_msg = ''
        for i_peak in xrange(num_peaks):
            scan_no, pt_no = self.ui.tableWidget_peaksCalUB.get_exp_info(i_peak)
            status, ret_obj = self._myControl.index_peak(ub_matrix, scan_number=scan_no,
                                                         pt_number=pt_no)
            if status is True:
                new_hkl = ret_obj[0]
                error = ret_obj[1]
                self.ui.tableWidget_peaksCalUB.set_hkl(i_peak, new_hkl, error)
            else:
                err_msg += ret_obj + '\n'
        # END-FOR

        if len(err_msg) > 0:
            self.pop_one_button_dialog(err_msg)

        return

    def do_list_scans(self):
        """ List all scans available
        :return:
        """
        # Experiment number
        exp_no = int(self.ui.lineEdit_exp.text())

        access_mode = str(self.ui.comboBox_mode.currentText())
        if access_mode == 'Local':
            spice_dir = str(self.ui.lineEdit_localSpiceDir.text())
            message = fcutil.get_scans_list_local_disk(spice_dir, exp_no)
        else:
            url = str(self.ui.lineEdit_url.text())
            message = fcutil.get_scans_list(url, exp_no)

        self.pop_one_button_dialog(message)

        return

    def do_load_scan_info(self):
        """ Load SIICE's scan file
        :return:
        """
        # Get scan number
        status, ret_obj = gutil.parse_integers_editors([self.ui.lineEdit_run])
        if status is True:
            scan_no = ret_obj[0]
        else:
            err_msg = ret_obj
            self.pop_one_button_dialog('Unable to get scan number in raw data tab due to %s.' % err_msg)
            return

        status, err_msg = self._myControl.load_spice_scan_file(exp_no=None, scan_no=scan_no)
        if status is False:
            self.pop_one_button_dialog(err_msg)

        return

    def do_plot_pt_raw(self):
        """ Plot the Pt.
        """
        # Get measurement pt and the file number
        status, ret_obj = gutil.parse_integers_editors([self.ui.lineEdit_exp,
                                                        self.ui.lineEdit_run,
                                                        self.ui.lineEdit_rawDataPtNo])
        if status is True:
            exp_no = ret_obj[0]
            scan_no = ret_obj[1]
            pt_no = ret_obj[2]
        else:
            self.pop_one_button_dialog(ret_obj)
            return

        # Call to plot 2D
        self._plot_raw_xml_2d(exp_no, scan_no, pt_no)

        return

    def do_plot_prev_pt_raw(self):
        """ Plot the Pt.
        """
        # Get measurement pt and the file number
        status, ret_obj = gutil.parse_integers_editors([self.ui.lineEdit_exp,
                                                        self.ui.lineEdit_run,
                                                        self.ui.lineEdit_rawDataPtNo])
        if status is True:
            exp_no = ret_obj[0]
            scan_no = ret_obj[1]
            pt_no = ret_obj[2]
        else:
            self.pop_one_button_dialog(ret_obj)
            return

        # Previous one
        pt_no -= 1
        if pt_no <= 0:
            self.pop_one_button_dialog('Pt. = 1 is the first one.')
            return
        else:
            self.ui.lineEdit_rawDataPtNo.setText('%d' % pt_no)

        # Plot
        self._plot_raw_xml_2d(exp_no, scan_no, pt_no)

        return

    def do_plot_next_pt_raw(self):
        """ Plot the Pt.
        """
        # Get measurement pt and the file number
        status, ret_obj = gutil.parse_integers_editors([self.ui.lineEdit_exp,
                                                        self.ui.lineEdit_run,
                                                        self.ui.lineEdit_rawDataPtNo])
        if status is True:
            exp_no = ret_obj[0]
            scan_no = ret_obj[1]
            pt_no = ret_obj[2]
        else:
            self.pop_one_button_dialog(ret_obj)
            return

        # Previous one
        pt_no += 1
        # get last Pt. number
        status, last_pt_no = self._myControl.get_pt_numbers(exp_no, scan_no)
        if status is False:
            error_message = last_pt_no
            self.pop_one_button_dialog('Unable to access Spice table for scan %d. Reason" %s.' % (
                scan_no, error_message))
        if pt_no > last_pt_no:
            self.pop_one_button_dialog('Pt. = %d is the last one of scan %d.' % (pt_no, scan_no))
            return
        else:
            self.ui.lineEdit_rawDataPtNo.setText('%d' % pt_no)

        # Plot
        self._plot_raw_xml_2d(exp_no, scan_no, pt_no)

        return

    def do_merge_scans(self):
        """ Process data for slicing view
        :return:
        """
        # Get UB matrix
        ub_matrix = self.ui.tableWidget_ubSiceView.get_matrix()
        self._myControl.set_ub_matrix(exp_number=None, ub_matrix=ub_matrix)

        # Get list of scans
        scan_list = gutil.parse_integer_list(str(self.ui.lineEdit_listScansSliceView.text()))
        if len(scan_list) == 0:
            self.pop_one_button_dialog('Scan list is empty.')

        # Set table
        self.ui.tableWidget_sliceViewProgress.append_scans(scans=scan_list)

        # Warning
        self.pop_one_button_dialog('Data processing is long. Be patient!')

        # Process
        base_name = str(self.ui.lineEdit_baseMergeMDName.text())
        scan_list.sort()
        frame = str(self.ui.comboBox_mergeScanFrame.currentText())
        for scan_no in scan_list:
            # Download/check SPICE file
            self._myControl.download_spice_file(None, scan_no, over_write=False)

            # Get some information
            status, pt_list = self._myControl.get_pt_numbers(None, scan_no, load_spice_scan=True)
            if status is False:
                err_msg = pt_list
                self.pop_one_button_dialog('Failed to get Pt. number: %s' % err_msg)
                return
            else:
                # Set information to table
                err_msg = self.ui.tableWidget_sliceViewProgress.set_scan_pt(scan_no, pt_list)
                if len(err_msg) > 0:
                    self.pop_one_button_dialog(err_msg)

            out_ws_name = base_name + '%04d' % scan_no
            self.ui.tableWidget_sliceViewProgress.set_scan_pt(scan_no, 'In Processing')
            try:
                ret_tup = self._myControl.merge_pts_in_scan(exp_no=None, scan_no=scan_no,
                                                            target_ws_name=out_ws_name,
                                                            target_frame=frame)
                merge_status = 'Done'
                merged_name = ret_tup[0]
                group_name = ret_tup[1]
            except RuntimeError as e:
                merge_status = 'Failed. Reason: %s' % str(e)
                merged_name = ''
                group_name = ''
            finally:
                self.ui.tableWidget_sliceViewProgress.set_status(scan_no, merge_status)
                self.ui.tableWidget_sliceViewProgress.set_ws_names(scan_no, merged_name, group_name)

            # Sleep for a while
            time.sleep(0.1)
        # END-FOR

        return

    def do_reset_ub_peaks_hkl(self):
        """
        Reset user specified HKL value to peak table
        :return:
        """
        num_rows = self.ui.tableWidget_peaksCalUB.rowCount()
        for i_row in xrange(num_rows):
            print '[DB] Update row %d' % (i_row)
            scan, pt = self.ui.tableWidget_peaksCalUB.get_scan_pt(i_row)
            status, peak_info = self._myControl.get_peak_info(None, scan, pt)
            if status is False:
                error_message = peak_info
                raise RuntimeError(error_message)
            h, k, l = peak_info.get_user_hkl()
            self.ui.tableWidget_peaksCalUB.update_hkl(i_row, h, k, l)
        # END-FOR

        return

    def do_set_experiment(self):
        """ Set experiment
        :return:
        """
        status, ret_obj = gutil.parse_integers_editors([self.ui.lineEdit_exp])
        if status is True:
            exp_number = ret_obj[0]
            curr_exp_number = self._myControl.get_experiment()
            if curr_exp_number is not None and exp_number != curr_exp_number:
                self.pop_one_button_dialog('Changing experiment to %d.  Clean previous experiment %d\'s result'
                                           ' in Mantid manually.' % (exp_number, curr_exp_number))
            self._myControl.set_exp_number(exp_number)
            self.ui.lineEdit_exp.setStyleSheet('color: black')
        else:
            err_msg = ret_obj
            self.pop_one_button_dialog('Unable to set experiment as %s' % err_msg)
            self.ui.lineEdit_exp.setStyleSheet('color: red')

        self.ui.tabWidget.setCurrentIndex(0)

        return

    def do_set_ub_sv(self):
        """ Set UB matrix in Slice view
        :return:
        """
        if self.ui.radioButton_ubFromTab1.isChecked():
            self.ui.tableWidget_ubSiceView.set_from_matrix(self.ui.tableWidget_ubMatrix.get_matrix())
        elif self.ui.radioButton_ubFromTab3.isChecked():
            self.ui.tableWidget_ubSiceView.set_from_matrix(self.ui.tableWidget_refinedUB.get_matrix())
        elif self.ui.radioButton_ubFromList.isChecked():
            status, ret_obj = gutil.parse_float_array(str(self.ui.plainTextEdit_ubInput.toPlainText()))
            if status is False:
                self.pop_one_button_dialog(ret_obj)
            elif len(ret_obj) != 9:
                self.pop_one_button_dialog('Requiring 9 floats for UB matrix.  Only %d are given.' % len(ret_obj))
            else:
                self.ui.tableWidget_ubSiceView.set_from_list(ret_obj)
        else:
            self.pop_one_button_dialog('None is selected to set UB matrix.')

        return

    def do_setup_dir_default(self):
        """
        Set up default directory for storing data and working
        :return:
        """
        home_dir = os.path.expanduser('~')

        # Data cache directory
        data_cache_dir = os.path.join(home_dir, 'Temp/HB3ATest')
        self.ui.lineEdit_localSpiceDir.setText(data_cache_dir)
        self.ui.lineEdit_localSrcDir.setText(data_cache_dir)

        work_dir = os.path.join(data_cache_dir, 'Workspace')
        self.ui.lineEdit_workDir.setText(work_dir)

        return

    def do_apply_setup(self):
        """
        Apply set up ...
        :return:
        """
        # Local data directory
        local_data_dir = str(self.ui.lineEdit_localSpiceDir.text())
        if os.path.exists(local_data_dir) is False:
            try:
                os.mkdir(local_data_dir)
            except OSError as os_error:
                self.pop_one_button_dialog('Unable to create local data directory %s due to %s.' % (
                    local_data_dir, str(os_error)))
                self.ui.lineEdit_localSpiceDir.setStyleSheet("color: red;")
                return
            else:
                self.ui.lineEdit_localSpiceDir.setStyleSheet("color: black;")
        # END-IF

        # Working directory
        working_dir = str(self.ui.lineEdit_workDir.text())
        if os.path.exists(working_dir) is False:
            try:
                os.mkdir(working_dir)
            except OSError as os_error:
                self.pop_one_button_dialog('Unable to create working directory %s due to %s.' % (
                    working_dir, str(os_error)))
                self.ui.lineEdit_workDir.setStyleSheet("color: red;")
                return
            else:
                self.ui.lineEdit_workDir.setStyleSheet("color: black;")
        # END-IF

        # Server URL
        data_server = str(self.ui.lineEdit_url.text())
        url_is_good = self.do_test_url()
        if url_is_good is False:
            self.ui.lineEdit_url.setStyleSheet("color: red;")
            return
        else:
            self.ui.lineEdit_url.setStyleSheet("color: black;")

        # Set to control
        self._myControl.set_local_data_dir(local_data_dir)
        self._myControl.set_working_directory(working_dir)
        self._myControl.set_server_url(data_server)

        return

    def do_test_url(self):
        """ Test whether the root URL provided specified is good
        """
        url = str(self.ui.lineEdit_url.text())

        url_is_good, err_msg = fcutil.check_url(url)
        if url_is_good is True:
            self.pop_one_button_dialog("URL %s is valid." % url)
        else:
            self.pop_one_button_dialog(err_msg)

        return url_is_good

    def pop_one_button_dialog(self, message):
        """ Pop up a one-button dialog
        :param message:
        :return:
        """
        assert isinstance(message, str)
        QtGui.QMessageBox.information(self, '4-circle Data Reduction', message)

        return

    def save_current_session(self, filename=None):
        """ Save current session/value setup to
        :return:
        """
        # Set up dictionary
        save_dict = dict()

        # Setup
        save_dict['lineEdit_localSpiceDir'] = str(self.ui.lineEdit_localSpiceDir.text())
        save_dict['lineEdit_url'] = str(self.ui.lineEdit_url.text())
        save_dict['lineEdit_workDir']= str(self.ui.lineEdit_workDir.text())

        # Experiment
        save_dict['lineEdit_exp'] = str(self.ui.lineEdit_exp.text())
        save_dict['lineEdit_scanNumber'] = self.ui.lineEdit_scanNumber.text()
        save_dict['lineEdit_ptNumber'] = str(self.ui.lineEdit_ptNumber.text())

        # Lattice
        save_dict['lineEdit_a'] = str(self.ui.lineEdit_a.text())
        save_dict['lineEdit_b'] = str(self.ui.lineEdit_b.text())
        save_dict['lineEdit_c'] = str(self.ui.lineEdit_c.text())
        save_dict['lineEdit_alpha'] = str(self.ui.lineEdit_alpha.text())
        save_dict['lineEdit_beta'] = str(self.ui.lineEdit_beta.text())
        save_dict['lineEdit_gamma'] = str(self.ui.lineEdit_gamma.text())

        # Merge scan
        save_dict['plainTextEdit_ubInput'] = str(self.ui.plainTextEdit_ubInput.toPlainText())
        save_dict['lineEdit_listScansSliceView'] = str(self.ui.lineEdit_listScansSliceView.text())
        save_dict['lineEdit_baseMergeMDName'] = str(self.ui.lineEdit_baseMergeMDName.text())

        # Save to csv file
        if filename is None:
            filename = 'session_backup.csv'
        ofile = open(filename, 'w')
        writer = csv.writer(ofile)
        for key, value in save_dict.items():
            writer.writerow([key, value])
        ofile.close()

        return

    def load_session(self, filename=None):
        """
        To load a session, i.e., read it back:
        :param filename:
        :return:
        """
        if filename is None:
            filename = 'session_backup.csv'

        in_file = open(filename, 'r')
        reader = csv.reader(in_file)
        my_dict = dict(x for x in reader)

        # ...
        for key, value in my_dict.items():
            if key.startswith('lineEdit') is True:
                self.ui.__getattribute__(key).setText(value)
            elif key.startswith('plainText') is True:
                self.ui.__getattribute__(key).setPlainText(value)
            elif key.startswith('comboBox') is True:
                self.ui.__getattribute__(key).setCurrentIndex(int(value))
            else:
                self.pop_one_button_dialog('Error! Widget name %s is not supported' % key)
        # END-FOR

        # ...
        self._myControl.set_local_data_dir(str(self.ui.lineEdit_localSpiceDir.text()))

        return

    def menu_quit(self):
        """

        :return:
        """
        self.close()

    def show_scan_pt_list(self):
        """ Show the range of Pt. in a scan
        :return:
        """
        # Get parameters
        status, inp_list = gutil.parse_integers_editors([self.ui.lineEdit_exp, self.ui.lineEdit_run])
        if status is False:
            self.pop_one_button_dialog(inp_list)
            return
        else:
            exp_no = inp_list[0]
            scan_no = inp_list[1]

        status, ret_obj = self._myControl.get_pt_numbers(exp_no, scan_no)

        # Form message
        if status is False:
            # Failed to get Pt. list
            error_message = ret_obj
            self.pop_one_button_dialog(error_message)
        else:
            # Form message
            pt_list = sorted(ret_obj)
            num_pts = len(pt_list)
            info = 'Exp %d Scan %d has %d Pt. ranging from %d to %d.\n' % (exp_no, scan_no, num_pts,
                                                                           pt_list[0], pt_list[-1])
            num_miss_pt = pt_list[-1] - pt_list[0] + 1 - num_pts
            if num_miss_pt > 0:
                info += 'There are %d Pt. skipped.\n' % num_miss_pt

            self.pop_one_button_dialog(info)

        return

    def set_ub_peak_table(self, peakinfo):
        """
        DOC
        :param peak_info:
        :return:
        """
        assert isinstance(peakinfo, r4c.PeakInfo)

        # Get data
        exp_number, scan_number, pt_number = peakinfo.getExpInfo()
        h, k, l = peakinfo.get_user_hkl()
        q_sample = peakinfo.getQSample()
        m1 = self._myControl.get_sample_log_value(exp_number, scan_number, pt_number, '_m1')

        # Set to table
        status, err_msg = self.ui.tableWidget_peaksCalUB.append_row(
            [scan_number, pt_number, h, k, l, q_sample[0], q_sample[1], q_sample[2], False, m1, ''])
        if status is False:
            self.pop_one_button_dialog(err_msg)

        return

    def _get_lattice_parameters(self):
        """
        Get lattice parameters from GUI
        :return: (Boolean, Object).  True, 6-tuple as a, b, c, alpha, beta, gamm
                                     False: error message
        """
        status, ret_list = gutil.parse_float_editors([self.ui.lineEdit_a,
                                                      self.ui.lineEdit_b,
                                                      self.ui.lineEdit_c,
                                                      self.ui.lineEdit_alpha,
                                                      self.ui.lineEdit_beta,
                                                      self.ui.lineEdit_gamma])
        if status is False:
            err_msg = ret_list
            err_msg = 'Unable to parse unit cell due to %s' % err_msg
            return False, err_msg

        a, b, c, alpha, beta, gamma = ret_list

        return True, (a, b, c, alpha, beta, gamma)

    def _plot_raw_xml_2d(self, exp_no, scan_no, pt_no):
        """ Plot raw workspace from XML file for a measurement/pt.
        """
        # Check and load SPICE table file
        does_exist = self._myControl.does_spice_loaded(exp_no, scan_no)
        if does_exist is False:
            # Download data
            status, error_message = self._myControl.download_spice_file(exp_no, scan_no, over_write=False)
            if status is True:
                status, error_message = self._myControl.load_spice_scan_file(exp_no, scan_no)
                if status is False and self._allowDownload is False:
                    self.pop_one_button_dialog(error_message)
                    return
            else:
                self.pop_one_button_dialog(error_message)
                return
        # END-IF(does_exist)

        # Load Data for Pt's xml file
        does_exist = self._myControl.does_raw_loaded(exp_no, scan_no, pt_no)

        if does_exist is False:
            # Check whether needs to download
            status, error_message = self._myControl.download_spice_xml_file(scan_no, pt_no, exp_no=exp_no)
            if status is False:
                self.pop_one_button_dialog(error_message)
                return
            # Load SPICE xml file
            status, error_message = self._myControl.load_spice_xml_file(exp_no, scan_no, pt_no)
            if status is False:
                self.pop_one_button_dialog(error_message)
                return

        # Convert a list of vector to 2D numpy array for imshow()
        # Get data and plot
        raw_det_data = self._myControl.get_raw_detector_counts(exp_no, scan_no, pt_no)
        self.ui.graphicsView.clear_canvas()
        self.ui.graphicsView.add_plot_2d(raw_det_data, x_min=0, x_max=256, y_min=0, y_max=256,
                                         hold_prev_image=False)

        return

    def _show_ub_matrix(self, ubmatrix):
        """ Show UB matrix
        :param ubmatrix:
        :return:
        """
        assert ubmatrix.shape == (3, 3)

        self.ui.tableWidget_ubMatrix.set_from_matrix(ubmatrix)

        return