def setUp(self):
     # patch away getting a real icon as it can hit a race condition when running tests
     # in parallel
     patcher = mock.patch('mantidqt.dialogs.spectraselectordialog.get_icon')
     self._mock_get_icon = patcher.start()
     self._mock_get_icon.return_value = QIcon()
     self.addCleanup(patcher.stop)
     if self._single_spec_ws is None:
         self.__class__._single_spec_ws = WorkspaceFactory.Instance().create("Workspace2D", NVectors=1,
                                                                             XLength=1, YLength=1)
         self.__class__._multi_spec_ws = WorkspaceFactory.Instance().create("Workspace2D", NVectors=200,
                                                                            XLength=1, YLength=1)
Beispiel #2
0
    def setUp(self):
        if self._test_ws is None:
            self.__class__._test_ws = WorkspaceFactory.Instance().create(
                "Workspace2D", NVectors=2, YLength=5, XLength=5)
        if self._test_ws_2 is None:
            self.__class__._test_ws_2 = WorkspaceFactory.Instance().create(
                "Workspace2D", NVectors=2, YLength=5, XLength=5)

        AnalysisDataService.addOrReplace('test_ws', self._test_ws)
        AnalysisDataService.addOrReplace('test_ws_2', self._test_ws_2)

        self.get_spectra_selection_patcher = mock.patch('mantidqt.plotting.functions.get_spectra_selection')
        self.addCleanup(self.get_spectra_selection_patcher.stop)
        self.get_spectra_selection_mock = self.get_spectra_selection_patcher.start()
 def test_get_spectra_selection_removes_wrong_workspace_types_from_list(
         self):
     table = WorkspaceFactory.Instance().createTable()
     workspaces = [self._single_spec_ws, table]
     self.assertEqual(
         get_spectra_selection(workspaces).workspaces,
         [self._single_spec_ws])
 def test_construction_with_non_MatrixWorkspace_type_removes_non_MatrixWorkspaces_from_list(
         self):
     table = WorkspaceFactory.Instance().createTable()
     workspaces = [self._single_spec_ws, table]
     ssd = SpectraSelectionDialog(workspaces)
     spectraselectordialog.RED_ASTERISK = None
     self.assertEqual(ssd._workspaces, [self._single_spec_ws])
    def test_fit_result_matrix_workspace_in_browser_is_viewed_when_clicked(
            self):
        if not PYQT5:
            self.skipTest(
                "MatrixWorkspaceDisplay and TableWorkspaceDisplay cannot be "
                "imported in qt4 so the test fails with an error.")
        from mantidqt.widgets.workspacedisplay.matrix.presenter import MatrixWorkspaceDisplay

        name = "ws"
        fig, canvas = self._create_and_plot_matrix_workspace(name)
        property_browser = self._create_widget(canvas=canvas)
        property_browser.setOutputName(name)

        # create fake fit output results
        matrixWorkspace = WorkspaceFactory.Instance().create("Workspace2D",
                                                             NVectors=3,
                                                             YLength=5,
                                                             XLength=5)
        AnalysisDataService.Instance().addOrReplace(name + "_Workspace",
                                                    matrixWorkspace)

        property_browser.fitting_done_slot(name + "_Workspace")
        wsList = property_browser.getWorkspaceList()

        # click on matrix workspace
        MatrixWorkspaceDisplay.show_view = Mock()
        item = wsList.item(0).text()
        property_browser.workspaceClicked.emit(item)
        self.assertEqual(1, MatrixWorkspaceDisplay.show_view.call_count)
 def test_filling_workspace_details_multiple_workspaces_of_different_sizes(self):
     cropped_ws = WorkspaceFactory.Instance().create("Workspace2D", NVectors=50, XLength=1, YLength=1)
     for i in range(cropped_ws.getNumberHistograms()):
         cropped_ws.getSpectrum(i).setSpectrumNo(51 + i)
     dlg = SpectraSelectionDialog([cropped_ws, self._multi_spec_ws])
     self.assertEqual("valid range: 51-100", dlg._ui.specNums.placeholderText())
     self.assertEqual("valid range: 0-49", dlg._ui.wkspIndices.placeholderText())
    def test_fit_curves_removed_when_workspaces_deleted(self):
        fig, canvas, _ = self._create_and_plot_matrix_workspace(name="ws")
        property_browser = self._create_widget(canvas=canvas)

        manager_mock = Mock()
        manager_mock.canvas = canvas
        observer = FigureManagerADSObserver(manager=manager_mock)  # noqa: F841

        for plot_diff in [True, False]:
            # create fake fit output results
            matrixWorkspace = WorkspaceFactory.Instance().create("Workspace2D",
                                                                 NVectors=3,
                                                                 YLength=5,
                                                                 XLength=5)
            tableWorkspace = WorkspaceFactory.createTable()
            AnalysisDataService.Instance().addOrReplace("ws_Workspace", matrixWorkspace)
            AnalysisDataService.Instance().addOrReplace("ws_Parameters", tableWorkspace)
            AnalysisDataService.Instance().addOrReplace("ws_NormalisedCovarianceMatrix",
                                                        tableWorkspace)

            property_browser.plotDiff = Mock(return_value=plot_diff)
            property_browser.fitting_done_slot("ws_Workspace")

            if plot_diff:
                self.assertEqual(3, len(fig.get_axes()[0].lines))
            else:
                self.assertEqual(2, len(fig.get_axes()[0].lines))

            AnalysisDataService.Instance().remove("ws_Workspace")
            AnalysisDataService.Instance().remove("ws_Parameters")
            AnalysisDataService.Instance().remove("ws_NormalisedCovarianceMatrix")

            self.assertEqual(1, len(fig.get_axes()[0].lines))
Beispiel #8
0
    def test_fit_result_workspaces_are_added_to_browser_when_fitting_done(
            self):
        name = "ws"
        fig, canvas, _ = self._create_and_plot_matrix_workspace(name)
        property_browser = self._create_widget(canvas=canvas)
        property_browser.setOutputName(name)

        # create fake fit output results
        matrixWorkspace = WorkspaceFactory.Instance().create("Workspace2D",
                                                             NVectors=3,
                                                             YLength=5,
                                                             XLength=5)
        tableWorkspace = WorkspaceFactory.createTable()
        AnalysisDataService.Instance().addOrReplace(name + "_Workspace",
                                                    matrixWorkspace)
        AnalysisDataService.Instance().addOrReplace(name + "_Parameters",
                                                    tableWorkspace)
        AnalysisDataService.Instance().addOrReplace(
            name + "_NormalisedCovarianceMatrix", tableWorkspace)

        property_browser.fitting_done_slot(name + "_Workspace")
        workspaceList = property_browser.getWorkspaceList()

        self.assertEqual(3, workspaceList.count())
        self.assertEqual(name + "_NormalisedCovarianceMatrix",
                         workspaceList.item(0).text())
        self.assertEqual(name + "_Parameters", workspaceList.item(1).text())
        self.assertEqual(name + "_Workspace", workspaceList.item(2).text())
Beispiel #9
0
    def test_fit_result_matrix_workspace_in_browser_is_viewed_when_clicked(
            self):
        from mantidqt.widgets.workspacedisplay.table.presenter import TableWorkspaceDisplay

        name = "ws"
        fig, canvas, _ = self._create_and_plot_matrix_workspace(name)
        property_browser = self._create_widget(canvas=canvas)
        property_browser.setOutputName(name)

        # create fake fit output results
        matrixWorkspace = WorkspaceFactory.Instance().create("Workspace2D",
                                                             NVectors=3,
                                                             YLength=5,
                                                             XLength=5)
        AnalysisDataService.Instance().addOrReplace(name + "_Workspace",
                                                    matrixWorkspace)
        tableWorkspace = WorkspaceFactory.createTable()
        AnalysisDataService.Instance().addOrReplace(name + "_Parameters",
                                                    tableWorkspace)

        property_browser.fitting_done_slot(name + "_Workspace")
        wsList = property_browser.getWorkspaceList()
        TableWorkspaceDisplay.show_view = Mock()

        # click on table workspace
        item = wsList.item(0).text()
        property_browser.workspaceClicked.emit(item)
        self.assertEqual(1, TableWorkspaceDisplay.show_view.call_count)
Beispiel #10
0
 def test_pcolormesh_from_names_with_non_plottable_workspaces_returns_None(
         self):
     table = WorkspaceFactory.Instance().createTable()
     table_name = 'test_pcolormesh_from_names_with_non_plottable_workspaces_returns_None'
     AnalysisDataService.Instance().addOrReplace(table_name, table)
     result = pcolormesh_from_names([table_name])
     self.assertEqual(result, None)
 def _create_and_plot_matrix_workspace(self, name="workspace"):
     ws = WorkspaceFactory.Instance().create("Workspace2D",
                                             NVectors=2,
                                             YLength=5,
                                             XLength=5)
     AnalysisDataService.Instance().addOrReplace(name, ws)
     fig = plot([ws], spectrum_nums=[1])
     canvas = fig.canvas
     return fig, canvas
Beispiel #12
0
    def _create_empty_results_table(self, log_selection, results_selection,
                                    all_fits):
        """
        Create an empty table workspace to store the results.
        :param log_selection: See create_results_table
        :param results_selection: See create_results_table
        :return: A new TableWorkspace
        """
        table = WorkspaceFactory.Instance().createTable()
        table.addColumn('str', 'workspace_name', TableColumnType.NoType.value)

        def float_log(wksp_name, log_name):
            try:
                run = ads.Instance().retrieve(wksp_name).run()
                prop = run.getProperty(log_name)
                if isinstance(prop, FloatTimeSeriesProperty):
                    return True
                try:
                    float(prop.value)
                    return True
                except ValueError:
                    return False
            except (TypeError, ValueError):
                for fit in all_fits:
                    for input_workspace in fit.input_workspaces:
                        ws = ads.Instance().retrieve(input_workspace)
                        if ws.run().hasProperty(log_name):
                            return float_log(input_workspace, log_name)

        for log_name in log_selection:
            wksp_name = all_fits[0].input_workspaces[0]
            if log_name in ['run_start', 'run_end']:
                table.addColumn('str', log_name, TableColumnType.X.value)
                table.addColumn('float', log_name + '_seconds',
                                TableColumnType.X.value)
            else:
                if float_log(wksp_name, log_name):
                    table.addColumn('float', log_name, TableColumnType.X.value)
                    # only add the errors column if the value is numerical
                    table.addColumn('float', _error_column_name(log_name),
                                    TableColumnType.XErr.value)
                else:
                    table.addColumn('str', log_name, TableColumnType.X.value)
        # assume all fit functions are the same in fit_selection and take
        # the parameter names from the first fit.
        parameters = self._find_parameters_for_table(results_selection)
        for name in parameters.names():
            table.addColumn('float', name, TableColumnType.Y.value)
            if _param_error_should_be_displayed(name):
                table.addColumn('float', _error_column_name(name),
                                TableColumnType.YErr.value)
                # The error column will be the most recent one added (columnCount-1) and is corresponding value will be
                # the second to last (columnCount-2).
                table.setLinkedYCol(table.columnCount() - 1,
                                    table.columnCount() - 2)
        return table
Beispiel #13
0
def _create_parameter_workspace(num_spec, param_table):
    num_params = param_table.rowCount()
    param_workspace = WorkspaceFactory.Instance().create(
        "Workspace2D", num_params, num_spec, num_spec)
    x_axis = TextAxis.create(num_spec)
    param_workspace.replaceAxis(0, x_axis)

    y_axis = TextAxis.create(num_params)
    for idx, parameter_name in enumerate(param_table.column('Name')):
        y_axis.setLabel(idx, parameter_name)
    param_workspace.replaceAxis(1, y_axis)
    return param_workspace
Beispiel #14
0
def _create_workspace_for_group_plot(
        plot_type: SpectraSelection, workspaces: List[Workspace],
        plot_index: int, log_name: str,
        custom_log_values: List[float]) -> MatrixWorkspace:
    _validate_workspace_choices(workspaces, plot_index)

    number_of_workspaces = len(workspaces)

    first_ws = workspaces[0]
    first_blocksize = first_ws.blocksize()

    if plot_type == SpectraSelection.Contour:
        x_size = first_blocksize + 1
    else:
        x_size = first_blocksize

    matrix_ws = WorkspaceFactory.Instance().create(
        parent=first_ws,
        NVectors=number_of_workspaces,
        XLength=x_size,
        YLength=first_blocksize)

    matrix_ws.setYUnitLabel(first_ws.YUnitLabel())

    log_values = []
    for i in range(number_of_workspaces):
        ws = workspaces[i]
        if isinstance(ws, MatrixWorkspace):
            if plot_type == SpectraSelection.Contour:
                matrix_ws.applyBinEdgesFromAnotherWorkspace(ws, plot_index, i)
            else:
                matrix_ws.applyPointsFromAnotherWorkspace(ws, plot_index, i)

            matrix_ws.setY(i, ws.readY(plot_index))
            matrix_ws.setE(i, ws.readE(plot_index))

            if log_name == "Custom":
                log_values.append(
                    get_single_workspace_log_value(
                        i, log_values=custom_log_values))
            else:
                log_values.append(
                    get_single_workspace_log_value(i,
                                                   matrix_ws=ws,
                                                   log_name=log_name))

    log_values_axis = NumericAxis.create(len(log_values))
    for i in range(len(log_values)):
        log_values_axis.setValue(i, log_values[i])

    matrix_ws.replaceAxis(1, log_values_axis)

    return matrix_ws
Beispiel #15
0
    def setUp(self):
        # patch away getting a real icon as it can hit a race condition when running tests
        # in parallel
        patcher = mock.patch('mantidqt.dialogs.spectraselectordialog.get_icon')
        self._mock_get_icon = patcher.start()
        self._mock_get_icon.return_value = QIcon()
        self.addCleanup(patcher.stop)
        if self._single_spec_ws is None:
            self.__class__._single_spec_ws = WorkspaceFactory.Instance(
            ).create("Workspace2D", NVectors=1, XLength=1, YLength=1)
            self.__class__._multi_spec_ws = WorkspaceFactory.Instance().create(
                "Workspace2D", NVectors=200, XLength=1, YLength=1)
        SpectraSelectionDialog._check_number_of_plots = mock.Mock(
            return_value=True)

        spectraselectordialog.RED_ASTERISK = None

        # replaceWidget doesn't exist in Qt4
        replace_widget_patcher = mock.patch.object(QVBoxLayout,
                                                   'replaceWidget',
                                                   create=True)
        replace_widget_patcher.start()
        self.addCleanup(replace_widget_patcher.stop)
Beispiel #16
0
 def setUp(self):
     if self._test_ws is None:
         self.__class__._test_ws = WorkspaceFactory.Instance().create(
             "Workspace2D", NVectors=2, YLength=5, XLength=5)
     if self._test_md_ws is None:
         self._test_md_ws = CreateMDHistoWorkspace(
             SignalInput='1,2,3,4,2,1',
             ErrorInput='1,1,1,1,1,1',
             Dimensionality=3,
             Extents='-1,1,-1,1,0.5,6.5',
             NumberOfBins='1,1,6',
             Names='x,y,|Q|',
             Units='mm,km,AA^-1',
             OutputWorkspace='test_plot_md_from_names_ws')
Beispiel #17
0
 def test_filling_workspace_details_multiple_workspace_with_spectra_gaps(
         self):
     gappy_ws = WorkspaceFactory.Instance().create("Workspace2D",
                                                   NVectors=50,
                                                   XLength=1,
                                                   YLength=1)
     for i in range(20):
         gappy_ws.getSpectrum(i).setSpectrumNo(1 + i)
     for i in range(20, gappy_ws.getNumberHistograms()):
         gappy_ws.getSpectrum(i).setSpectrumNo(161 + i)
     dlg = SpectraSelectionDialog([gappy_ws, self._multi_spec_ws])
     self.assertEqual("valid range: 1-20, 181-200",
                      dlg._ui.specNums.placeholderText())
     self.assertEqual("valid range: 0-49",
                      dlg._ui.wkspIndices.placeholderText())
 def test_output_workspace_name_changes_if_more_than_one_plot_of_same_workspace(self, figure_labels_mock):
     # create a workspace
     ws = WorkspaceFactory.Instance().create("Workspace2D", NVectors=2, YLength=5, XLength=5)
     AnalysisDataService.Instance().addOrReplace("workspace", ws)
     ws_window_names = ["workspace-1", "workspace-2"]
     figure_labels_mock.return_value = ws_window_names
     output_name = []
     # plot it twice
     for i in [0, 1]:
         fig = plot([ws], spectrum_nums=[1])
         fig.canvas.get_window_title = Mock(return_value=ws_window_names[i])
         browser = self._create_widget(canvas=fig.canvas)
         # don't want the widget to actually show in test
         QDockWidget.show = Mock()
         browser.show()
         output_name.append(browser.outputName())
     self.assertNotEqual(output_name[0], output_name[1])
    def test_workspaces_removed_from_workspace_list_widget_if_deleted_from_ADS(self):
        name = "ws"
        fig, canvas_mock, _ = self._create_and_plot_matrix_workspace(name)
        property_browser = self._create_widget(canvas=canvas_mock)
        property_browser.setOutputName(name)

        # create fake fit output results
        matrixWorkspace = WorkspaceFactory.Instance().create("Workspace2D", NVectors=3, YLength=5, XLength=5)
        AnalysisDataService.Instance().addOrReplace(name + "_Workspace", matrixWorkspace)
        tableWorkspace = WorkspaceFactory.createTable()
        AnalysisDataService.Instance().addOrReplace(name + "_Parameters", tableWorkspace)

        property_browser.fitting_done_slot(name + "_Workspace")
        AnalysisDataService.Instance().remove(name + "_Parameters")
        property_browser.postDeleteHandle(name + "_Parameters")

        wsList = property_browser.getWorkspaceList()
        self.assertEqual(1, len(wsList))
Beispiel #20
0
    def _create_empty_results_table(self, log_selection, results_selection,
                                    all_fits):
        """
        Create an empty table workspace to store the results.
        :param log_selection: See create_results_table
        :param results_selection: See create_results_table
        :return: A new TableWorkspace
        """
        table = WorkspaceFactory.Instance().createTable()
        table.addColumn('str', 'workspace_name', TableColumnType.NoType.value)

        def float_log(wksp_name, log_name):
            try:
                run = ads.Instance().retrieve(wksp_name).run()
                prop = run.getProperty(log_name)
                if isinstance(prop, FloatTimeSeriesProperty):
                    return True
                try:
                    float(prop.value)
                    return True
                except ValueError:
                    return False
            except (TypeError, ValueError):
                for fit in all_fits:
                    for input_workspace in fit.input_workspaces:
                        ws = ads.Instance().retrieve(input_workspace)
                        if ws.run().hasProperty(log_name):
                            return float_log(input_workspace, log_name)

        for log_name in log_selection:
            wksp_name = all_fits[0].input_workspaces[0]
            if float_log(wksp_name, log_name):
                table.addColumn('float', log_name, TableColumnType.X.value)
            else:
                table.addColumn('str', log_name, TableColumnType.X.value)
        # assume all fit functions are the same in fit_selection and take
        # the parameter names from the first fit.
        parameters = self._find_parameters_for_table(results_selection)
        for name in parameters.names():
            table.addColumn('float', name, TableColumnType.Y.value)
            if _param_error_should_be_displayed(name):
                table.addColumn('float', _error_column_name(name),
                                TableColumnType.YErr.value)
        return table
Beispiel #21
0
 def test_filling_workspace_details_single_workspace_with_spectra_gaps(
         self):
     gappy_ws = WorkspaceFactory.Instance().create("Workspace2D",
                                                   NVectors=50,
                                                   XLength=1,
                                                   YLength=1)
     for i in range(10):
         gappy_ws.getSpectrum(i).setSpectrumNo(1 + i)
     for i in range(10, 16):
         gappy_ws.getSpectrum(i).setSpectrumNo(1 + (2 * i))
     for i in range(17, 20):
         gappy_ws.getSpectrum(i).setSpectrumNo(1 + i)
     for i in range(20, gappy_ws.getNumberHistograms()):
         gappy_ws.getSpectrum(i).setSpectrumNo(51 + i)
     dlg = SpectraSelectionDialog([gappy_ws])
     self.assertEqual(
         "valid range: 1-10, 17-21, 23, 25, 27, 29, 31, 71-100",
         dlg._ui.specNums.placeholderText())
     self.assertEqual("valid range: 0-49",
                      dlg._ui.wkspIndices.placeholderText())
Beispiel #22
0
    def test_changes_apply_to_all_colorfill_plots_if_one_colorbar(self):
        ws = WorkspaceFactory.Instance().create("Workspace2D", NVectors=1, YLength=5, XLength=5)
        fig = pcolormesh([ws, ws])
        # there should be 3 axes: 2 colorfill plots and 1 colorbar
        self.assertEqual(3, len(fig.axes))

        colorbarEditor = ColorbarAxisEditor(fig.canvas, fig.axes[2])

        min_value = 1.0
        max_value = 2.0
        colorbarEditor.ui.editor_min.text = MagicMock(return_value=min_value)
        colorbarEditor.ui.editor_max.text = MagicMock(return_value=max_value)
        colorbarEditor.ui.logBox.isChecked = MagicMock(return_value=True)

        colorbarEditor.changes_accepted()

        for ax in range(2):
            self.assertEqual(min_value, fig.axes[ax].collections[0].norm.vmin)
            self.assertEqual(max_value, fig.axes[ax].collections[0].norm.vmax)
            self.assertTrue(isinstance(fig.axes[ax].collections[0].norm, LogNorm))
Beispiel #23
0
 def _create_empty_results_table(self, log_selection, results_selection):
     """
     Create an empty table workspace to store the results.
     :param log_selection: See create_results_table
     :param results_selection: See create_results_table
     :return: A new TableWorkspace
     """
     table = WorkspaceFactory.Instance().createTable()
     table.addColumn('str', 'workspace_name', TableColumnType.NoType.value)
     for log_name in log_selection:
         table.addColumn('float', log_name, TableColumnType.X.value)
     # assume all fit functions are the same in fit_selection and take
     # the parameter names from the first fit.
     parameters = self._find_parameters_for_table(results_selection)
     for name in parameters.names():
         table.addColumn('float', name, TableColumnType.Y.value)
         if _param_error_should_be_displayed(name):
             table.addColumn('float', _error_column_name(name),
                             TableColumnType.YErr.value)
     return table
 def test_get_spectra_selection_raises_error_with_wrong_workspace_type(self):
     table = WorkspaceFactory.Instance().createTable()
     self.assertRaises(ValueError, get_spectra_selection, [self._single_spec_ws, table])
Beispiel #25
0
 def setUp(self):
     if self._test_ws is None:
         self.__class__._test_ws = WorkspaceFactory.Instance().create(
             "Workspace2D", NVectors=2, YLength=5, XLength=5)
Beispiel #26
0
 def test_plot_from_names_with_non_plottable_workspaces_returns_None(self):
     table = WorkspaceFactory.Instance().createTable()
     table_name = 'test_plot_from_names_with_non_plottable_workspaces_returns_None'
     AnalysisDataService.Instance().addOrReplace(table_name, table)
     result = plot_from_names([table_name], errors=False, overplot=False)
     self.assertTrue(result is None)
 def test_construction_with_non_MatrixWorkspace_type_raises_exception(self):
     table = WorkspaceFactory.Instance().createTable()
     self.assertRaises(ValueError, SpectraSelectionDialog, [self._single_spec_ws, table])
Beispiel #28
0
    def PyExec(self):
        workflow_prog = Progress(self, start=0.0, end=0.3, nreports=4)
        workflow_prog.report('Setting up algorithm')
        self._setup()

        input_ws = mtd[self._sample]

        min_spectrum_index = input_ws.getIndexFromSpectrumNumber(
            int(self._spectra_range[0]))
        max_spectrum_index = input_ws.getIndexFromSpectrumNumber(
            int(self._spectra_range[1]))

        # Crop to the required spectra range
        workflow_prog.report('Cropping Workspace')
        cropped_input = ms.CropWorkspace(
            InputWorkspace=input_ws,
            OutputWorkspace='__symm',
            StartWorkspaceIndex=min_spectrum_index,
            EndWorkspaceIndex=max_spectrum_index)
        # Find the smallest data array in the first spectra
        len_x = len(cropped_input.readX(0))
        len_y = len(cropped_input.readY(0))
        len_e = len(cropped_input.readE(0))
        sample_array_len = min(len_x, len_y, len_e)

        sample_x = cropped_input.readX(0)

        # Get slice bounds of array
        try:
            workflow_prog.report('Calculating array points')
            self._calculate_array_points(sample_x, sample_array_len)
        except Exception as exc:
            raise RuntimeError(
                'Failed to calculate array slice boundaries: %s' % exc.message)

        max_sample_index = sample_array_len - 1
        centre_range_len = self._positive_min_index + self._negative_min_index
        positive_diff_range_len = max_sample_index - self._positive_max_index

        output_cut_index = max_sample_index - self._positive_min_index - positive_diff_range_len - 1
        new_array_len = 2 * max_sample_index - centre_range_len - 2 * positive_diff_range_len - 1

        logger.information('Sample array length = %d' % sample_array_len)

        logger.information(
            'Positive X min at i=%d, x=%f' %
            (self._positive_min_index, sample_x[self._positive_min_index]))
        logger.information(
            'Negative X min at i=%d, x=%f' %
            (self._negative_min_index, sample_x[self._negative_min_index]))

        logger.information(
            'Positive X max at i=%d, x=%f' %
            (self._positive_max_index, sample_x[self._positive_max_index]))

        logger.information('New array length = %d' % new_array_len)
        logger.information('Output array LR split index = %d' %
                           output_cut_index)

        # Create an empty workspace with enough storage for the new data
        workflow_prog.report('Creating OutputWorkspace')
        out_ws = WorkspaceFactory.Instance().create(
            cropped_input, cropped_input.getNumberHistograms(),
            int(new_array_len), int(new_array_len))

        # For each spectrum copy positive values to the negative
        pop_prog = Progress(self,
                            start=0.3,
                            end=0.95,
                            nreports=out_ws.getNumberHistograms())
        for idx in range(out_ws.getNumberHistograms()):
            pop_prog.report('Populating data in workspace %i' % idx)
            # Strip any additional array cells
            x_in = cropped_input.readX(idx)[:sample_array_len]
            y_in = cropped_input.readY(idx)[:sample_array_len]
            e_in = cropped_input.readE(idx)[:sample_array_len]

            # Get some zeroed data to overwrite with copies from sample
            x_out = np.zeros(new_array_len)
            y_out = np.zeros(new_array_len)
            e_out = np.zeros(new_array_len)

            # Left hand side (reflected)
            x_out[:output_cut_index] = -x_in[self._positive_max_index -
                                             1:self._positive_min_index:-1]
            y_out[:output_cut_index] = y_in[self._positive_max_index -
                                            1:self._positive_min_index:-1]
            e_out[:output_cut_index] = e_in[self._positive_max_index -
                                            1:self._positive_min_index:-1]

            # Right hand side (copied)
            x_out[output_cut_index:] = x_in[self._negative_min_index:self.
                                            _positive_max_index]
            y_out[output_cut_index:] = y_in[self._negative_min_index:self.
                                            _positive_max_index]
            e_out[output_cut_index:] = e_in[self._negative_min_index:self.
                                            _positive_max_index]

            # Set output spectrum data
            out_ws.setX(idx, x_out)
            out_ws.setY(idx, y_out)
            out_ws.setE(idx, e_out)

            logger.information('Symmetrise spectrum %d' % idx)

        end_prog = Progress(self, start=0.95, end=1.0, nreports=3)
        end_prog.report('Deleting temp workspaces')
        ms.DeleteWorkspace(cropped_input)

        if self._props_output_workspace != '':
            end_prog.report('Generating property table')
            self._generate_props_table()

        self.setProperty('OutputWorkspace', out_ws)
        end_prog.report('Algorithm Complete')