def test_that_applies_flat_background_correction_only_to_monitors(self):
        # Arrange
        workspace_name = "monitor_test_workspace"
        workspace = self._create_flat_background_test_workspace(workspace_name)

        monitor_workspace_indices = [0, 1]
        # The first monitor (with spectrum index 1 should find a correction value of 2
        # The second monitor (with spectrum index 2 should find a correction value of 4
        monitor_spectrum_tof_start = {"1": 1, "2": 50}
        monitor_spectrum_tof_stop = {"1": 40, "2": 70}
        tof_general_start = 24
        tof_general_stop = 38
        # Act
        output_workspace = apply_flat_background_correction_to_monitors(
            workspace, monitor_workspace_indices, monitor_spectrum_tof_start,
            monitor_spectrum_tof_stop, tof_general_start, tof_general_stop)
        # Assert
        # The first monitor  should have [0, 0, 2, 2], it has 2.1 in the last value, not clear why
        # The second monitor  should have [0, 0, 0, 0], it has 0.1 in the last value, not clear why. Note that
        # the flat background correction never goes negative.
        self._assert_collection_elements_are_equal(output_workspace.dataY(0),
                                                   [0, 0, 2, 2.1])
        self._assert_collection_elements_are_equal(output_workspace.dataY(1),
                                                   [0, 0, 0, 0.1])
        # The detectors should be unchanged
        for index in range(2, output_workspace.getNumberHistograms()):
            self._assert_collection_elements_are_equal(
                output_workspace.dataY(index), [2, 2, 4, 4])

        # Clean up
        DeleteWorkspace(workspace)
    def test_that_applies_flat_background_correction_only_to_monitors(self):
        # Arrange
        workspace_name = "monitor_test_workspace"
        workspace = self._create_flat_background_test_workspace(workspace_name)

        monitor_workspace_indices = [0, 1]
        # The first monitor (with spectrum index 1 should find a correction value of 2
        # The second monitor (with spectrum index 2 should find a correction value of 4
        monitor_spectrum_tof_start = {"1": 1, "2": 50}
        monitor_spectrum_tof_stop = {"1": 40, "2": 70}
        tof_general_start = 24
        tof_general_stop = 38
        # Act
        output_workspace = apply_flat_background_correction_to_monitors(workspace,
                                                                        monitor_workspace_indices,
                                                                        monitor_spectrum_tof_start,
                                                                        monitor_spectrum_tof_stop, tof_general_start,
                                                                        tof_general_stop)
        # Assert
        # The first monitor  should have [0, 0, 2, 2], it has 2.1 in the last value, not clear why
        # The second monitor  should have [0, 0, 0, 0], it has 0.1 in the last value, not clear why. Note that
        # the flat background correction never goes negative.
        self._assert_collection_elements_are_equal(output_workspace.dataY(0), [0, 0, 2, 2.1])
        self._assert_collection_elements_are_equal(output_workspace.dataY(1), [0, 0, 0, 0.1])
        # The detectors should be unchanged
        for index in range(2, output_workspace.getNumberHistograms()):
            self._assert_collection_elements_are_equal(output_workspace.dataY(index), [2, 2, 4, 4])

        # Clean up
        DeleteWorkspace(workspace)
    def _get_corrected_wavelength_workspace(self, workspace, detector_ids, calculate_transmission_state):
        """
        Performs a prompt peak correction, a background correction, converts to wavelength and rebins.

        :param workspace: the workspace which is being corrected.
        :param detector_ids: a list of relevant detector ids
        :param calculate_transmission_state: a SANSStateCalculateTransmission state
        :return:  a corrected workspace.
        """
        # Extract the relevant spectra. These include
        # 1. The incident monitor spectrum
        # 2. The transmission spectra, be it monitor or ROI based.
        # A previous implementation of this code had a comment which suggested
        # that we have to exclude unused spectra as the interpolation runs into
        # problems if we don't.
        extract_name = "ExtractSpectra"
        extract_options = {"InputWorkspace": workspace,
                           "OutputWorkspace": EMPTY_NAME,
                           "DetectorList": detector_ids}
        extract_alg = create_unmanaged_algorithm(extract_name, **extract_options)
        extract_alg.execute()
        workspace = extract_alg.getProperty("OutputWorkspace").value

        # Make sure that we still have spectra in the workspace
        if workspace.getNumberHistograms() == 0:
            raise RuntimeError("SANSCalculateTransmissionCorrection: The transmission workspace does "
                               "not seem to have any spectra.")

        # ----------------------------------
        # Perform the prompt peak correction
        # ----------------------------------
        prompt_peak_correction_min = calculate_transmission_state.prompt_peak_correction_min
        prompt_peak_correction_max = calculate_transmission_state.prompt_peak_correction_max
        prompt_peak_correction_enabled = calculate_transmission_state.prompt_peak_correction_enabled
        workspace = self._perform_prompt_peak_correction(workspace, prompt_peak_correction_min,
                                                         prompt_peak_correction_max, prompt_peak_correction_enabled)

        # ---------------------------------------
        # Perform the flat background correction
        # ---------------------------------------
        # The flat background correction has two parts:
        # 1. Corrections on monitors
        # 2. Corrections on regular detectors

        # Monitor flat background correction
        workspace_indices_of_monitors = list(get_workspace_indices_for_monitors(workspace))
        background_tof_monitor_start = calculate_transmission_state.background_TOF_monitor_start
        background_tof_monitor_stop = calculate_transmission_state.background_TOF_monitor_stop
        background_tof_general_start = calculate_transmission_state.background_TOF_general_start
        background_tof_general_stop = calculate_transmission_state.background_TOF_general_stop
        workspace = apply_flat_background_correction_to_monitors(workspace,
                                                                 workspace_indices_of_monitors,
                                                                 background_tof_monitor_start,
                                                                 background_tof_monitor_stop,
                                                                 background_tof_general_start,
                                                                 background_tof_general_stop)

        # Detector flat background correction
        flat_background_correction_start = calculate_transmission_state.background_TOF_roi_start
        flat_background_correction_stop = calculate_transmission_state.background_TOF_roi_stop
        workspace = apply_flat_background_correction_to_detectors(workspace, flat_background_correction_start,
                                                                  flat_background_correction_stop)

        # ---------------------------------------
        # Convert to wavelength and rebin
        # ---------------------------------------
        # The wavelength setting is reasonably complex.
        # 1. Use full wavelength range
        # 2. Use standard settings
        if calculate_transmission_state.use_full_wavelength_range:
            wavelength_low = calculate_transmission_state.wavelength_full_range_low
            wavelength_high = calculate_transmission_state.wavelength_full_range_high
        else:
            wavelength_low = calculate_transmission_state.wavelength_low[0]
            wavelength_high = calculate_transmission_state.wavelength_high[0]

        wavelength_step = calculate_transmission_state.wavelength_step
        rebin_type = calculate_transmission_state.rebin_type
        wavelength_step_type = calculate_transmission_state.wavelength_step_type

        convert_name = "SANSConvertToWavelengthAndRebin"
        convert_options = {"InputWorkspace": workspace,
                           "WavelengthLow": wavelength_low,
                           "WavelengthHigh": wavelength_high,
                           "WavelengthStep": wavelength_step,
                           "WavelengthStepType": RangeStepType.to_string(wavelength_step_type),
                           "RebinMode": RebinType.to_string(rebin_type)}
        convert_alg = create_unmanaged_algorithm(convert_name, **convert_options)
        convert_alg.setPropertyValue("OutputWorkspace", EMPTY_NAME)
        convert_alg.setProperty("OutputWorkspace", workspace)
        convert_alg.execute()
        return convert_alg.getProperty("OutputWorkspace").value
    def _get_corrected_wavelength_workspace(self, workspace, detector_ids, calculate_transmission_state):
        """
        Performs a prompt peak correction, a background correction, converts to wavelength and rebins.

        :param workspace: the workspace which is being corrected.
        :param detector_ids: a list of relevant detector ids
        :param calculate_transmission_state: a SANSStateCalculateTransmission state
        :return:  a corrected workspace.
        """
        # Extract the relevant spectra. These include
        # 1. The incident monitor spectrum
        # 2. The transmission spectra, be it monitor or ROI based.
        # A previous implementation of this code had a comment which suggested
        # that we have to exclude unused spectra as the interpolation runs into
        # problems if we don't.
        extract_name = "ExtractSpectra"
        extract_options = {"InputWorkspace": workspace,
                           "OutputWorkspace": EMPTY_NAME,
                           "DetectorList": detector_ids}
        extract_alg = create_unmanaged_algorithm(extract_name, **extract_options)
        extract_alg.execute()
        workspace = extract_alg.getProperty("OutputWorkspace").value

        # Make sure that we still have spectra in the workspace
        if workspace.getNumberHistograms() == 0:
            raise RuntimeError("SANSCalculateTransmissionCorrection: The transmission workspace does "
                               "not seem to have any spectra.")

        # ----------------------------------
        # Perform the prompt peak correction
        # ----------------------------------
        prompt_peak_correction_min = calculate_transmission_state.prompt_peak_correction_min
        prompt_peak_correction_max = calculate_transmission_state.prompt_peak_correction_max
        prompt_peak_correction_enabled = calculate_transmission_state.prompt_peak_correction_enabled
        workspace = self._perform_prompt_peak_correction(workspace, prompt_peak_correction_min,
                                                         prompt_peak_correction_max, prompt_peak_correction_enabled)

        # ---------------------------------------
        # Perform the flat background correction
        # ---------------------------------------
        # The flat background correction has two parts:
        # 1. Corrections on monitors
        # 2. Corrections on regular detectors

        # Monitor flat background correction
        workspace_indices_of_monitors = list(get_workspace_indices_for_monitors(workspace))
        background_tof_monitor_start = calculate_transmission_state.background_TOF_monitor_start
        background_tof_monitor_stop = calculate_transmission_state.background_TOF_monitor_stop
        background_tof_general_start = calculate_transmission_state.background_TOF_general_start
        background_tof_general_stop = calculate_transmission_state.background_TOF_general_stop
        workspace = apply_flat_background_correction_to_monitors(workspace,
                                                                 workspace_indices_of_monitors,
                                                                 background_tof_monitor_start,
                                                                 background_tof_monitor_stop,
                                                                 background_tof_general_start,
                                                                 background_tof_general_stop)

        # Detector flat background correction
        flat_background_correction_start = calculate_transmission_state.background_TOF_roi_start
        flat_background_correction_stop = calculate_transmission_state.background_TOF_roi_stop
        workspace = apply_flat_background_correction_to_detectors(workspace, flat_background_correction_start,
                                                                  flat_background_correction_stop)

        # ---------------------------------------
        # Convert to wavelength and rebin
        # ---------------------------------------
        # The wavelength setting is reasonably complex.
        # 1. Use full wavelength range
        # 2. Use standard settings
        if calculate_transmission_state.use_full_wavelength_range:
            wavelength_low = calculate_transmission_state.wavelength_full_range_low
            wavelength_high = calculate_transmission_state.wavelength_full_range_high
        else:
            data_type_string = self.getProperty("DataType").value
            fit_state = calculate_transmission_state.fit[data_type_string]
            wavelength_low = fit_state.wavelength_low if fit_state.wavelength_low\
                else calculate_transmission_state.wavelength_low[0]
            wavelength_high = fit_state.wavelength_high if fit_state.wavelength_high\
                else calculate_transmission_state.wavelength_high[0]

        wavelength_step = calculate_transmission_state.wavelength_step
        rebin_type = calculate_transmission_state.rebin_type
        wavelength_step_type = calculate_transmission_state.wavelength_step_type

        convert_name = "SANSConvertToWavelengthAndRebin"
        convert_options = {"InputWorkspace": workspace,
                           "WavelengthLow": wavelength_low,
                           "WavelengthHigh": wavelength_high,
                           "WavelengthStep": wavelength_step,
                           "WavelengthStepType": RangeStepType.to_string(wavelength_step_type),
                           "RebinMode": RebinType.to_string(rebin_type)}
        convert_alg = create_unmanaged_algorithm(convert_name, **convert_options)
        convert_alg.setPropertyValue("OutputWorkspace", EMPTY_NAME)
        convert_alg.setProperty("OutputWorkspace", workspace)
        convert_alg.execute()
        return convert_alg.getProperty("OutputWorkspace").value