def PyExec(self):

        from IndirectReductionCommon import (
            get_multi_frame_rebin, identify_bad_detectors, unwrap_monitor,
            process_monitor_efficiency, scale_monitor, scale_detectors,
            rebin_reduction, group_spectra, fold_chopped, rename_reduction)

        self._setup()

        load_opts = dict()
        if self._instrument_name == 'VESUVIO':
            load_opts['InstrumentParFile'] = self._par_filename
            load_opts['Mode'] = 'FoilOut'
            load_opts['LoadMonitors'] = True

        self._workspace_names, self._chopped_data = load_file_ranges(
            self._data_files,
            self._ipf_filename,
            self._spectra_range[0],
            self._spectra_range[1],
            sum_files=self._sum_files,
            load_logs=self._load_logs,
            load_opts=load_opts)

        # applies the changes in the provided calibration file
        self._apply_calibration()
        # Load container if run is given
        self._load_and_scale_container(self._container_scale_factor, load_opts)

        # Load vanadium runs if given
        if self._vanadium_runs:
            self._vanadium_ws, _, _ = load_files(self._vanadium_runs,
                                                 self._ipf_filename,
                                                 self._spectra_range[0],
                                                 self._spectra_range[1],
                                                 load_logs=self._load_logs,
                                                 load_opts=load_opts)

            if len(self._workspace_names) > len(self._vanadium_runs):
                raise RuntimeError(
                    "There cannot be more sample runs than vanadium runs.")

        for index, c_ws_name in enumerate(self._workspace_names):
            is_multi_frame = isinstance(mtd[c_ws_name], WorkspaceGroup)

            # Get list of workspaces
            if is_multi_frame:
                workspaces = mtd[c_ws_name].getNames()
            else:
                workspaces = [c_ws_name]

            # Process rebinning for framed data
            rebin_string_2, num_bins = get_multi_frame_rebin(
                c_ws_name, self._rebin_string)

            masked_detectors = identify_bad_detectors(workspaces[0])

            # Process workspaces
            for ws_name in workspaces:
                monitor_ws_name = ws_name + '_mon'

                # Subtract empty container if there is one
                if self._container_workspace is not None:
                    Minus(LHSWorkspace=ws_name,
                          RHSWorkspace=self._container_workspace,
                          OutputWorkspace=ws_name)

                if self._vanadium_ws:
                    van_ws_name = self._vanadium_ws[index]
                    van_ws = mtd[van_ws_name]
                    if self._container_workspace is not None:
                        cont_ws = mtd[self._container_workspace]

                        if van_ws.blocksize() > cont_ws.blocksize():
                            RebinToWorkspace(
                                WorkspaceToRebin=van_ws_name,
                                WorkspaceToMatch=self._container_workspace,
                                OutputWorkspace=van_ws_name)
                        elif cont_ws.blocksize() > van_ws.blocksize():
                            RebinToWorkspace(
                                WorkspaceToRebin=self._container_workspace,
                                WorkspaceToMatch=van_ws_name,
                                OutputWorkspace=self._container_workspace)

                        Minus(LHSWorkspace=van_ws_name,
                              RHSWorkspace=self._container_workspace,
                              OutputWorkspace=van_ws_name)

                    if mtd[ws_name].blocksize() > van_ws.blocksize():
                        RebinToWorkspace(WorkspaceToRebin=ws_name,
                                         WorkspaceToMatch=van_ws_name,
                                         OutputWorkspace=ws_name)
                    elif van_ws.blocksize() > mtd[ws_name].blocksize():
                        RebinToWorkspace(WorkspaceToRebin=van_ws_name,
                                         WorkspaceToMatch=ws_name,
                                         OutputWorkspace=van_ws_name)

                    replacement_value = 0.1 * find_minimum_non_zero_y_in_workspace(
                        van_ws)
                    logger.information(
                        'Replacing zeros in {0} with {1}.'.format(
                            van_ws_name, replacement_value))
                    ReplaceSpecialValues(
                        InputWorkspace=van_ws_name,
                        SmallNumberThreshold=0.0000001,
                        SmallNumberValue=replacement_value,
                        OutputWorkspace=self._replace_zeros_name)

                    Divide(LHSWorkspace=ws_name,
                           RHSWorkspace=self._replace_zeros_name,
                           OutputWorkspace=ws_name,
                           AllowDifferentNumberSpectra=True)

                    DeleteWorkspace(self._replace_zeros_name)

                # Process monitor
                if not unwrap_monitor(ws_name):
                    ConvertUnits(InputWorkspace=monitor_ws_name,
                                 OutputWorkspace=monitor_ws_name,
                                 Target='Wavelength',
                                 EMode='Elastic')

                process_monitor_efficiency(ws_name)
                scale_monitor(ws_name)

                # Scale detector data by monitor intensities
                scale_detectors(ws_name, 'Elastic')

                # Remove the no longer needed monitor workspace
                DeleteWorkspace(monitor_ws_name)

                # Convert to dSpacing
                ConvertUnits(InputWorkspace=ws_name,
                             OutputWorkspace=ws_name,
                             Target='dSpacing',
                             EMode='Elastic')

                # Handle rebinning
                rebin_reduction(ws_name, self._rebin_string, rebin_string_2,
                                num_bins)

                # Group spectra
                group_spectra(ws_name,
                              masked_detectors=masked_detectors,
                              method=self._grouping_method,
                              group_ws=self._grouping_workspace)

            if is_multi_frame:
                fold_chopped(c_ws_name)

        # Remove the container workspaces
        if self._container_workspace is not None:
            self._delete_all([self._container_workspace])

        # Remove the vanadium workspaces
        if self._vanadium_ws:
            self._delete_all(self._vanadium_ws)

        # Rename output workspaces
        output_workspace_names = [
            rename_reduction(ws_name, self._sum_files)
            for ws_name in self._workspace_names
        ]

        # Group result workspaces
        GroupWorkspaces(InputWorkspaces=output_workspace_names,
                        OutputWorkspace=self._output_ws)

        self.setProperty('OutputWorkspace', self._output_ws)
    def PyExec(self):

        from IndirectReductionCommon import (get_multi_frame_rebin,
                                             identify_bad_detectors,
                                             unwrap_monitor,
                                             process_monitor_efficiency,
                                             scale_monitor,
                                             scale_detectors,
                                             rebin_reduction,
                                             group_spectra,
                                             fold_chopped,
                                             rename_reduction)

        self._setup()

        load_opts = dict()
        if self._instrument_name == 'VESUVIO':
            load_opts['InstrumentParFile'] = self._par_filename
            load_opts['Mode'] = 'FoilOut'
            load_opts['LoadMonitors'] = True

        self._workspace_names, self._chopped_data = load_file_ranges(self._data_files,
                                                                     self._ipf_filename,
                                                                     self._spectra_range[0],
                                                                     self._spectra_range[1],
                                                                     sum_files=self._sum_files,
                                                                     load_logs=self._load_logs,
                                                                     load_opts=load_opts)

        # applies the changes in the provided calibration file
        self._apply_calibration()
        # Load container if run is given
        self._load_and_scale_container(self._container_scale_factor, load_opts)

        # Load vanadium runs if given
        if self._vanadium_runs:
            self._vanadium_ws, _ = load_files(self._vanadium_runs,
                                              self._ipf_filename,
                                              self._spectra_range[0],
                                              self._spectra_range[1],
                                              load_logs=self._load_logs,
                                              load_opts=load_opts)

            if len(self._workspace_names) > len(self._vanadium_runs):
                raise RuntimeError("There cannot be more sample runs than vanadium runs.")

        for index, c_ws_name in enumerate(self._workspace_names):
            is_multi_frame = isinstance(mtd[c_ws_name], WorkspaceGroup)

            # Get list of workspaces
            if is_multi_frame:
                workspaces = mtd[c_ws_name].getNames()
            else:
                workspaces = [c_ws_name]

            # Process rebinning for framed data
            rebin_string_2, num_bins = get_multi_frame_rebin(c_ws_name,
                                                             self._rebin_string)

            masked_detectors = identify_bad_detectors(workspaces[0])

            # Process workspaces
            for ws_name in workspaces:
                monitor_ws_name = ws_name + '_mon'

                # Subtract empty container if there is one
                if self._container_workspace is not None:
                    Minus(LHSWorkspace=ws_name,
                          RHSWorkspace=self._container_workspace,
                          OutputWorkspace=ws_name)

                if self._vanadium_ws:
                    van_ws_name = self._vanadium_ws[index]
                    van_ws = mtd[van_ws_name]
                    if self._container_workspace is not None:
                        cont_ws = mtd[self._container_workspace]

                        if van_ws.blocksize() > cont_ws.blocksize():
                            RebinToWorkspace(WorkspaceToRebin=van_ws_name,
                                             WorkspaceToMatch=self._container_workspace,
                                             OutputWorkspace=van_ws_name)
                        elif cont_ws.blocksize() > van_ws.blocksize():
                            RebinToWorkspace(WorkspaceToRebin=self._container_workspace,
                                             WorkspaceToMatch=van_ws_name,
                                             OutputWorkspace=self._container_workspace)

                        Minus(LHSWorkspace=van_ws_name,
                              RHSWorkspace=self._container_workspace,
                              OutputWorkspace=van_ws_name)

                    if mtd[ws_name].blocksize() > van_ws.blocksize():
                        RebinToWorkspace(WorkspaceToRebin=ws_name,
                                         WorkspaceToMatch=van_ws_name,
                                         OutputWorkspace=ws_name)
                    elif van_ws.blocksize() > mtd[ws_name].blocksize():
                        RebinToWorkspace(WorkspaceToRebin=van_ws_name,
                                         WorkspaceToMatch=ws_name,
                                         OutputWorkspace=van_ws_name)

                    Divide(LHSWorkspace=ws_name,
                           RHSWorkspace=van_ws_name,
                           OutputWorkspace=ws_name,
                           AllowDifferentNumberSpectra=True)

                # Process monitor
                if not unwrap_monitor(ws_name):
                    ConvertUnits(InputWorkspace=monitor_ws_name,
                                 OutputWorkspace=monitor_ws_name,
                                 Target='Wavelength',
                                 EMode='Elastic')

                process_monitor_efficiency(ws_name)
                scale_monitor(ws_name)

                # Scale detector data by monitor intensities
                scale_detectors(ws_name, 'Elastic')

                # Remove the no longer needed monitor workspace
                DeleteWorkspace(monitor_ws_name)

                # Convert to dSpacing
                ConvertUnits(InputWorkspace=ws_name,
                             OutputWorkspace=ws_name,
                             Target='dSpacing',
                             EMode='Elastic')

                # Handle rebinning
                rebin_reduction(ws_name,
                                self._rebin_string,
                                rebin_string_2,
                                num_bins)

                # Group spectra
                group_spectra(ws_name,
                              masked_detectors=masked_detectors,
                              method=self._grouping_method,
                              group_ws=self._grouping_workspace)

            if is_multi_frame:
                fold_chopped(c_ws_name)

        # Remove the container workspaces
        if self._container_workspace is not None:
            self._delete_all([self._container_workspace])

        # Remove the vanadium workspaces
        if self._vanadium_ws:
            self._delete_all(self._vanadium_ws)

        # Rename output workspaces
        output_workspace_names = [rename_reduction(ws_name, self._sum_files) for ws_name in self._workspace_names]

        # Group result workspaces
        GroupWorkspaces(InputWorkspaces=output_workspace_names,
                        OutputWorkspace=self._output_ws)

        self.setProperty('OutputWorkspace', self._output_ws)