def _get_detector_ids_for_transmission_calculation(self, transmission_workspace, calculate_transmission_state):
        """
        Get the detector ids which participate in the transmission calculation.

        This can come either from a ROI/MASK/RADIUS selection or from a transmission monitor, not both.
        :param transmission_workspace: the transmission workspace.
        :param calculate_transmission_state: a SANSStateCalculateTransmission object.
        :return: a list of detector ids for ROI and a detector id for the transmission monitor, either can be None
        """
        # Get the potential ROI detector ids
        transmission_radius = calculate_transmission_state.transmission_radius_on_detector
        transmission_roi = calculate_transmission_state.transmission_roi_files
        transmission_mask = calculate_transmission_state.transmission_mask_files
        detector_ids_roi = get_region_of_interest(transmission_workspace, transmission_radius, transmission_roi,
                                                  transmission_mask)

        # Get the potential transmission monitor detector id
        transmission_monitor_spectrum_number = calculate_transmission_state.transmission_monitor
        detector_id_transmission_monitor = None
        if transmission_monitor_spectrum_number is not None:
            detector_id_transmission_monitor = get_detector_id_for_spectrum_number(transmission_workspace,
                                                                                   transmission_monitor_spectrum_number)

        # Get the default transmission monitor detector id. This is our fallback if nothing else was specified.
        default_transmission_monitor = calculate_transmission_state.default_transmission_monitor

        detector_id_default_transmission_monitor = get_detector_id_for_spectrum_number(transmission_workspace,
                                                                                       default_transmission_monitor)

        return detector_ids_roi, detector_id_transmission_monitor, detector_id_default_transmission_monitor
    def _get_detector_ids_for_transmission_calculation(self, transmission_workspace, calculate_transmission_state):
        """
        Get the detector ids which participate in the transmission calculation.

        This can come either from a ROI/MASK/RADIUS selection or from a transmission monitor, not both.
        :param transmission_workspace: the transmission workspace.
        :param calculate_transmission_state: a SANSStateCalculateTransmission object.
        :return: a list of detector ids for ROI and a detector id for the transmission monitor, either can be None
        """
        # Get the potential ROI detector ids
        transmission_radius = calculate_transmission_state.transmission_radius_on_detector
        transmission_roi = calculate_transmission_state.transmission_roi_files
        transmission_mask = calculate_transmission_state.transmission_mask_files
        detector_ids_roi = get_region_of_interest(transmission_workspace, transmission_radius, transmission_roi,
                                                  transmission_mask)

        # Get the potential transmission monitor detector id
        transmission_monitor_spectrum_number = calculate_transmission_state.transmission_monitor
        detector_id_transmission_monitor = None
        if transmission_monitor_spectrum_number is not None:
            detector_id_transmission_monitor = get_detector_id_for_spectrum_number(transmission_workspace,
                                                                                   transmission_monitor_spectrum_number)

        # Get the default transmission monitor detector id. This is our fallback if nothing else was specified.
        default_transmission_monitor = calculate_transmission_state.default_transmission_monitor

        detector_id_default_transmission_monitor = get_detector_id_for_spectrum_number(transmission_workspace,
                                                                                       default_transmission_monitor)

        return detector_ids_roi, detector_id_transmission_monitor, detector_id_default_transmission_monitor
def calculate_transmission(transmission_ws, direct_ws,
                           state_adjustment_calculate_transmission,
                           data_type_str):
    """
    Calculates the transmission for a SANS reduction.
    :param transmission_ws: The transmission workspace in time-of-light units.
    :param direct_ws: The direct workspace in time-of-flight units.
    :param state_adjustment_calculate_transmission: The state.adjustment.calculate_transmission object
    :param data_type_str: The component of the instrument which is to be reduced. Allowed values: ['Sample', 'Can']
    :return: Tuple of: Output Workspace and Unfitted Data - Both in wavelength
    """
    calculate_transmission_state = state_adjustment_calculate_transmission
    # The calculation of the transmission has the following steps:
    # 1. Get all spectrum numbers which take part in the transmission calculation
    # 2. Clean up the transmission and direct workspaces, ie peak prompt correction, flat background calculation,
    #    wavelength conversion and rebinning of the data.
    # 3. Run the CalculateTransmission algorithm
    incident_monitor_spectrum_number = calculate_transmission_state.incident_monitor
    if incident_monitor_spectrum_number is None:
        incident_monitor_spectrum_number = calculate_transmission_state.default_incident_monitor

    # 1. Get relevant spectra
    detector_id_incident_monitor = get_detector_id_for_spectrum_number(
        transmission_ws, incident_monitor_spectrum_number)
    detector_ids_roi, detector_id_transmission_monitor, detector_id_default_transmission_monitor = \
        _get_detector_ids_for_transmission_calculation(transmission_ws, calculate_transmission_state)
    all_detector_ids = [detector_id_incident_monitor]

    if len(detector_ids_roi) > 0:
        all_detector_ids.extend(detector_ids_roi)
    elif detector_id_transmission_monitor is not None:
        all_detector_ids.append(detector_id_transmission_monitor)
    elif detector_id_default_transmission_monitor is not None:
        all_detector_ids.append(detector_id_default_transmission_monitor)
    else:
        raise RuntimeError(
            "SANSCalculateTransmission: No region of interest or transmission monitor selected."
        )

    # 2. Clean transmission data

    data_type = DataType(data_type_str)
    transmission_ws = _get_corrected_wavelength_workspace(
        transmission_ws,
        all_detector_ids,
        calculate_transmission_state,
        data_type=data_type)
    direct_ws = _get_corrected_wavelength_workspace(
        direct_ws,
        all_detector_ids,
        calculate_transmission_state,
        data_type=data_type)

    # 3. Fit
    output_workspace, unfitted_transmission_workspace = \
        _perform_fit(transmission_ws, direct_ws, detector_ids_roi,
                     detector_id_transmission_monitor, detector_id_default_transmission_monitor,
                     detector_id_incident_monitor, calculate_transmission_state, data_type)

    return output_workspace, unfitted_transmission_workspace
    def PyExec(self):
        # Read the state
        state_property_manager = self.getProperty("SANSState").value
        state = create_deserialized_sans_state_from_property_manager(
            state_property_manager)
        calculate_transmission_state = state.adjustment.calculate_transmission
        # The calculation of the transmission has the following steps:
        # 1. Get all spectrum numbers which take part in the transmission calculation
        # 2. Clean up the transmission and direct workspaces, ie peak prompt correction, flat background calculation,
        #    wavelength conversion and rebinning of the data.
        # 3. Run the CalculateTransmission algorithm
        transmission_workspace = self.getProperty(
            "TransmissionWorkspace").value
        direct_workspace = self.getProperty("DirectWorkspace").value
        incident_monitor_spectrum_number = calculate_transmission_state.incident_monitor
        if incident_monitor_spectrum_number is None:
            incident_monitor_spectrum_number = calculate_transmission_state.default_incident_monitor

        # 1. Get relevant spectra
        detector_id_incident_monitor = get_detector_id_for_spectrum_number(
            transmission_workspace, incident_monitor_spectrum_number)
        detector_ids_roi, detector_id_transmission_monitor, detector_id_default_transmission_monitor = \
            self._get_detector_ids_for_transmission_calculation(transmission_workspace, calculate_transmission_state)
        all_detector_ids = [detector_id_incident_monitor]

        if len(detector_ids_roi) > 0:
            all_detector_ids.extend(detector_ids_roi)
        elif detector_id_transmission_monitor is not None:
            all_detector_ids.append(detector_id_transmission_monitor)
        elif detector_id_default_transmission_monitor is not None:
            all_detector_ids.append(detector_id_default_transmission_monitor)
        else:
            raise RuntimeError(
                "SANSCalculateTransmission: No region of interest or transmission monitor selected."
            )

        # 2. Clean transmission data
        data_type_string = self.getProperty("DataType").value
        data_type = DataType.from_string(data_type_string)
        transmission_workspace = self._get_corrected_wavelength_workspace(
            transmission_workspace, all_detector_ids,
            calculate_transmission_state)
        direct_workspace = self._get_corrected_wavelength_workspace(
            direct_workspace, all_detector_ids, calculate_transmission_state)

        # 3. Fit
        output_workspace, unfitted_transmission_workspace = \
            self._perform_fit(transmission_workspace, direct_workspace, detector_ids_roi,
                              detector_id_transmission_monitor, detector_id_default_transmission_monitor,
                              detector_id_incident_monitor, calculate_transmission_state, data_type)

        self.setProperty("OutputWorkspace", output_workspace)
        if unfitted_transmission_workspace:
            self.setProperty("UnfittedData", unfitted_transmission_workspace)
    def PyExec(self):
        # Read the state
        state_property_manager = self.getProperty("SANSState").value
        state = create_deserialized_sans_state_from_property_manager(state_property_manager)
        calculate_transmission_state = state.adjustment.calculate_transmission
        # The calculation of the transmission has the following steps:
        # 1. Get all spectrum numbers which take part in the transmission calculation
        # 2. Clean up the transmission and direct workspaces, ie peak prompt correction, flat background calculation,
        #    wavelength conversion and rebinning of the data.
        # 3. Run the CalculateTransmission algorithm
        transmission_workspace = self.getProperty("TransmissionWorkspace").value
        direct_workspace = self.getProperty("DirectWorkspace").value
        incident_monitor_spectrum_number = calculate_transmission_state.incident_monitor
        if incident_monitor_spectrum_number is None:
            incident_monitor_spectrum_number = calculate_transmission_state.default_incident_monitor

        # 1. Get relevant spectra
        detector_id_incident_monitor = get_detector_id_for_spectrum_number(transmission_workspace,
                                                                           incident_monitor_spectrum_number)
        detector_ids_roi, detector_id_transmission_monitor, detector_id_default_transmission_monitor = \
            self._get_detector_ids_for_transmission_calculation(transmission_workspace, calculate_transmission_state)
        all_detector_ids = [detector_id_incident_monitor]

        if len(detector_ids_roi) > 0:
            all_detector_ids.extend(detector_ids_roi)
        elif detector_id_transmission_monitor is not None:
            all_detector_ids.append(detector_id_transmission_monitor)
        elif detector_id_default_transmission_monitor is not None:
            all_detector_ids.append(detector_id_default_transmission_monitor)
        else:
            raise RuntimeError("SANSCalculateTransmission: No region of interest or transmission monitor selected.")

        # 2. Clean transmission data
        data_type_string = self.getProperty("DataType").value
        data_type = DataType.from_string(data_type_string)
        transmission_workspace = self._get_corrected_wavelength_workspace(transmission_workspace, all_detector_ids,
                                                                          calculate_transmission_state)
        direct_workspace = self._get_corrected_wavelength_workspace(direct_workspace, all_detector_ids,
                                                                    calculate_transmission_state)

        # 3. Fit
        output_workspace, unfitted_transmission_workspace = \
            self._perform_fit(transmission_workspace, direct_workspace, detector_ids_roi,
                              detector_id_transmission_monitor, detector_id_default_transmission_monitor,
                              detector_id_incident_monitor, calculate_transmission_state, data_type)

        self.setProperty("OutputWorkspace", output_workspace)
        if unfitted_transmission_workspace:
            self.setProperty("UnfittedData", unfitted_transmission_workspace)