def set_detector_names(state, ipf_path, invalid_detector_types=None): """ Sets the detectors names on a State object which has a `detector` map entry, e.g. StateMask :param state: the state object :param ipf_path: the path to the Instrument Parameter File :param invalid_detector_types: a list of invalid detector types which don't exist for the instrument """ if invalid_detector_types is None: invalid_detector_types = [] lab_keyword = DetectorType.to_string(DetectorType.LAB) hab_keyword = DetectorType.to_string(DetectorType.HAB) detector_names = { lab_keyword: "low-angle-detector-name", hab_keyword: "high-angle-detector-name" } detector_names_short = { lab_keyword: "low-angle-detector-short-name", hab_keyword: "high-angle-detector-short-name" } names_to_search = [] names_to_search.extend(list(detector_names.values())) names_to_search.extend(list(detector_names_short.values())) found_detector_names = get_named_elements_from_ipf_file( ipf_path, names_to_search, str) for detector_type in state.detectors: try: if DetectorType.from_string( detector_type) in invalid_detector_types: continue detector_name_tag = detector_names[detector_type] detector_name_short_tag = detector_names_short[detector_type] detector_name = found_detector_names[detector_name_tag] detector_name_short = found_detector_names[detector_name_short_tag] except KeyError: continue state.detectors[detector_type].detector_name = detector_name state.detectors[ detector_type].detector_name_short = detector_name_short
def set_detector_names(state, ipf_path, invalid_detector_types=None): """ Sets the detectors names on a State object which has a `detector` map entry, e.g. StateMask :param state: the state object :param ipf_path: the path to the Instrument Parameter File :param invalid_detector_types: a list of invalid detector types which don't exist for the instrument """ if invalid_detector_types is None: invalid_detector_types = [] lab_keyword = DetectorType.to_string(DetectorType.LAB) hab_keyword = DetectorType.to_string(DetectorType.HAB) detector_names = {lab_keyword: "low-angle-detector-name", hab_keyword: "high-angle-detector-name"} detector_names_short = {lab_keyword: "low-angle-detector-short-name", hab_keyword: "high-angle-detector-short-name"} names_to_search = [] names_to_search.extend(list(detector_names.values())) names_to_search.extend(list(detector_names_short.values())) found_detector_names = get_named_elements_from_ipf_file(ipf_path, names_to_search, str) for detector_type in state.detectors: try: if DetectorType.from_string(detector_type) in invalid_detector_types: continue detector_name_tag = detector_names[detector_type] detector_name_short_tag = detector_names_short[detector_type] detector_name = found_detector_names[detector_name_tag] detector_name_short = found_detector_names[detector_name_short_tag] except KeyError: continue state.detectors[detector_type].detector_name = detector_name state.detectors[detector_type].detector_name_short = detector_name_short
def _get_component(self, workspace): component_as_string = self.getProperty("Component").value component = DetectorType.from_string(component_as_string) return get_component_name(workspace, component)
def _get_component(self): component_as_string = self.getProperty("Component").value return DetectorType.from_string(component_as_string)
def PyExec(self): # Get the input state = self._get_state() state_serialized = state.property_manager component_as_string = self.getProperty("Component").value progress = self._get_progress() # -------------------------------------------------------------------------------------------------------------- # 1. Crop workspace by detector name # This will create a reduced copy of the original workspace with only those spectra which are relevant # for this particular reduction. # -------------------------------------------------------------------------------------------------------------- progress.report("Cropping ...") workspace = self._get_cropped_workspace(component_as_string) # -------------------------------------------------------------------------------------------- # 2. Perform dark run subtraction # This will subtract a dark background from the scatter workspace. Note that dark background subtraction # will also affect the transmission calculation later on. # -------------------------------------------------------------------------------------------------------------- # -------------------------------------------------------------------------------------------------------------- # 3. Create event slice # If we are dealing with an event workspace as input, this will cut out a time-based (user-defined) slice. # In case of a histogram workspace, nothing happens. # -------------------------------------------------------------------------------------------------------------- progress.report("Event slicing ...") data_type_as_string = self.getProperty("DataType").value monitor_workspace = self._get_monitor_workspace() workspace, monitor_workspace, slice_event_factor = self._slice(state_serialized, workspace, monitor_workspace, data_type_as_string) # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # COMPATIBILITY # The old reduction workflow converted the workspace to a histogram at this point. # A more recent workflow keeps the workspaces as Events for longer, to make use of cheap rebinning for # EventWorkspaces, and to optimise for event slicing. # However, in the new workflow ("non-compatibility mode") it is necessary to keep a workspace as a histogram # to keep track of the bin masking. These masks are lifted from the dummy workspace to the actual workspace # near the end of the reduction. # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! workspace, dummy_mask_workspace, \ use_dummy_workspace = self._check_compatibility_mode(workspace, monitor_workspace, state.compatibility) # ------------------------------------------------------------ # 4. Move the workspace into the correct position # The detectors in the workspaces are set such that the beam centre is at (0,0). The position is # a user-specified value which can be obtained with the help of the beam centre finder. # ------------------------------------------------------------ progress.report("Moving ...") workspace = self._move(state_serialized, workspace, component_as_string) monitor_workspace = self._move(state_serialized, monitor_workspace, component_as_string) # -------------------------------------------------------------------------------------------------------------- # 5. Apply masking (pixel masking and time masking) # -------------------------------------------------------------------------------------------------------------- progress.report("Masking ...") workspace = self._mask(state_serialized, workspace, component_as_string) # -------------------------------------------------------------------------------------------------------------- # 6. Convert to Wavelength # -------------------------------------------------------------------------------------------------------------- progress.report("Converting to wavelength ...") workspace = self._convert_to_wavelength(state_serialized, workspace) # Convert and rebin the dummy workspace to get correct bin flags if use_dummy_workspace: dummy_mask_workspace = mask_bins(state.mask, dummy_mask_workspace, DetectorType.from_string(component_as_string)) dummy_mask_workspace = self._convert_to_wavelength(state_serialized, dummy_mask_workspace) # -------------------------------------------------------------------------------------------------------------- # 7. Multiply by volume and absolute scale # -------------------------------------------------------------------------------------------------------------- progress.report("Multiplying by volume and absolute scale ...") workspace = self._scale(state_serialized, workspace) # -------------------------------------------------------------------------------------------------------------- # 8. Create adjustment workspaces, those are # 1. pixel-based adjustments # 2. wavelength-based adjustments # 3. pixel-and-wavelength-based adjustments # Note that steps 4 to 7 could run in parallel if we don't use wide angle correction. If we do then the # creation of the adjustment workspaces requires the sample workspace itself and we have to run it sequentially. # We could consider to have a serial and a parallel strategy here, depending on the wide angle correction # settings. On the other hand it is not clear that this would be an advantage with the GIL. # -------------------------------------------------------------------------------------------------------------- progress.report("Creating adjustment workspaces ...") wavelength_adjustment_workspace, pixel_adjustment_workspace, wavelength_and_pixel_adjustment_workspace, \ calculated_transmission_workspace, unfitted_transmission_workspace = \ self._adjustment(state_serialized, workspace, monitor_workspace, component_as_string, data_type_as_string) # ---------------------------------------------------------------- # 9. Convert event workspaces to histogram workspaces, and re-mask # ---------------------------------------------------------------- progress.report("Converting to histogram mode ...") workspace = self._convert_to_histogram(workspace) if use_dummy_workspace: workspace = self._copy_bin_masks(workspace, dummy_mask_workspace) # ------------------------------------------------------------ # 10. Convert to Q # ----------------------------------------------------------- progress.report("Converting to q ...") workspace, sum_of_counts, sum_of_norms = self._convert_to_q(state_serialized, workspace, wavelength_adjustment_workspace, pixel_adjustment_workspace, wavelength_and_pixel_adjustment_workspace) progress.report("Completed SANSReductionCore ...") # ------------------------------------------------------------ # Populate the output # ------------------------------------------------------------ self.setProperty("OutputWorkspace", workspace) # ------------------------------------------------------------ # Diagnostic output # ------------------------------------------------------------ if sum_of_counts: self.setProperty("SumOfCounts", sum_of_counts) if sum_of_norms: self.setProperty("SumOfNormFactors", sum_of_norms) self.setProperty("CalculatedTransmissionWorkspace", calculated_transmission_workspace) self.setProperty("UnfittedTransmissionWorkspace", unfitted_transmission_workspace)
def PyExec(self): # Get the input state = self._get_state() state_serialized = state.property_manager component_as_string = self.getProperty("Component").value progress = self._get_progress() # -------------------------------------------------------------------------------------------------------------- # 1. Crop workspace by detector name # This will create a reduced copy of the original workspace with only those spectra which are relevant # for this particular reduction. # -------------------------------------------------------------------------------------------------------------- progress.report("Cropping ...") workspace = self._get_cropped_workspace(component_as_string) # -------------------------------------------------------------------------------------------- # 2. Perform dark run subtraction # This will subtract a dark background from the scatter workspace. Note that dark background subtraction # will also affect the transmission calculation later on. # -------------------------------------------------------------------------------------------------------------- # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # COMPATIBILITY BEGIN # IMPORTANT: This section of the code should only be temporary. It allows us to convert to histogram # early on and hence compare the new reduction results with the output of the new reduction chain. # Once the new reduction chain is established, we should remove the compatibility feature. # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! monitor_workspace = self._get_monitor_workspace() workspace, dummy_mask_workspace, \ use_dummy_workspace = self._check_compatibility_mode(workspace, monitor_workspace, state.compatibility) # ------------------------------------------------------------ # 3. Move the workspace into the correct position # The detectors in the workspaces are set such that the beam centre is at (0,0). The position is # a user-specified value which can be obtained with the help of the beam centre finder. # ------------------------------------------------------------ progress.report("Moving ...") workspace = self._move(state_serialized, workspace, component_as_string) monitor_workspace = self._move(state_serialized, monitor_workspace, component_as_string) # -------------------------------------------------------------------------------------------------------------- # 4. Apply masking (pixel masking and time masking) # -------------------------------------------------------------------------------------------------------------- progress.report("Masking ...") workspace = self._mask(state_serialized, workspace, component_as_string) # -------------------------------------------------------------------------------------------------------------- # 5. Convert to Wavelength # -------------------------------------------------------------------------------------------------------------- progress.report("Converting to wavelength ...") workspace = self._convert_to_wavelength(state_serialized, workspace) # Convert and rebin the dummy workspace to get correct bin flags if use_dummy_workspace: dummy_mask_workspace = mask_bins( state.mask, dummy_mask_workspace, DetectorType.from_string(component_as_string)) dummy_mask_workspace = self._convert_to_wavelength( state_serialized, dummy_mask_workspace) # -------------------------------------------------------------------------------------------------------------- # 6. Multiply by volume and absolute scale # -------------------------------------------------------------------------------------------------------------- progress.report("Multiplying by volume and absolute scale ...") workspace = self._scale(state_serialized, workspace) progress.report("Completed SANSReductionCorePreprocess ...") # ------------------------------------------------------------ # Populate the output # ------------------------------------------------------------ self.setProperty("OutputWorkspace", workspace) if use_dummy_workspace: self.setProperty("DummyMaskWorkspace", dummy_mask_workspace) self.setProperty("OutputMonitorWorkspace", monitor_workspace)