def _get_pixel_adjustment_workspace(pixel_adjustment_file, component, idf_path): """ This get the pixel-by-pixel adjustment of the workspace :param pixel_adjustment_file: full file path to the pixel adjustment file :param component: the component which is currently being investigated :param idf_path: the idf path :return: the pixel adjustment workspace """ if pixel_adjustment_file: load_name = "LoadRKH" load_options = { "Filename": pixel_adjustment_file, "OutputWorkspace": EMPTY_NAME, "FirstColumnValue": "SpectrumNumber" } load_alg = create_unmanaged_algorithm(load_name, **load_options) load_alg.execute() output_workspace = load_alg.getProperty("OutputWorkspace").value if not idf_path: raise ValueError("No IDF path was found in the provided state") # Add an instrument to the workspace instrument_name = "LoadInstrument" instrument_options = { "Workspace": output_workspace, "Filename": idf_path, "RewriteSpectraMap": False } instrument_alg = create_unmanaged_algorithm( instrument_name, **instrument_options) instrument_alg.execute() # Crop to the required detector crop_name = "CropToComponent" component_to_crop = DetectorType(component) component_to_crop = get_component_name(output_workspace, component_to_crop) crop_options = { "InputWorkspace": output_workspace, "OutputWorkspace": EMPTY_NAME, "ComponentNames": component_to_crop } crop_alg = create_unmanaged_algorithm(crop_name, **crop_options) crop_alg.execute() pixel_adjustment_workspace = crop_alg.getProperty( "OutputWorkspace").value else: pixel_adjustment_workspace = None return pixel_adjustment_workspace
def mask_workspace(state, component_as_string, workspace): assert (state is not dict) component = DetectorType(component_as_string) # Get the correct SANS masking strategy from create_masker masker = create_masker(state, component) # Perform the masking mask_info = state.mask workspace = masker.mask_workspace(mask_info, workspace, component) append_to_sans_file_tag(workspace, "_masked") return workspace
def crop_workspace(component, workspace): crop_name = "CropToComponent" component_to_crop = DetectorType(component) component_to_crop = get_component_name(workspace, component_to_crop) crop_options = {"InputWorkspace": workspace, "OutputWorkspace": EMPTY_NAME, "ComponentNames": component_to_crop} crop_alg = create_unmanaged_algorithm(crop_name, **crop_options) crop_alg.execute() output_workspace = crop_alg.getProperty("OutputWorkspace").value return output_workspace
def _get_cropped_workspace(self, component): scatter_workspace = self.getProperty("SampleScatterWorkspace").value alg_name = "CropToComponent" component_to_crop = DetectorType(component) component_to_crop = get_component_name(scatter_workspace, component_to_crop) crop_options = {"InputWorkspace": scatter_workspace, "OutputWorkspace": EMPTY_NAME, "ComponentNames": component_to_crop} crop_alg = create_child_algorithm(self, alg_name, **crop_options) crop_alg.execute() output_workspace = crop_alg.getProperty("OutputWorkspace").value return output_workspace
def _set_detector_names(state: StateInstrumentInfo, 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.LAB.value hab_keyword = DetectorType.HAB.value 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.detector_names: try: if DetectorType(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.detector_names[detector_type].detector_name = detector_name state.detector_names[ detector_type].detector_name_short = detector_name_short
def PyExec(self): # Get the input state = self._get_state() 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=state, workspace=workspace, component=component_as_string) monitor_workspace = self._move(state=state, workspace=monitor_workspace, component=component_as_string) # -------------------------------------------------------------------------------------------------------------- # 4. Apply masking (pixel masking and time masking) # -------------------------------------------------------------------------------------------------------------- progress.report("Masking ...") workspace = self._mask(state=state, workspace=workspace, component=component_as_string) # -------------------------------------------------------------------------------------------------------------- # 5. Convert to Wavelength # -------------------------------------------------------------------------------------------------------------- progress.report("Converting to wavelength ...") workspace = self._convert_to_wavelength(state=state, workspace=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(component_as_string)) dummy_mask_workspace = self._convert_to_wavelength(state=state, workspace=dummy_mask_workspace) # -------------------------------------------------------------------------------------------------------------- # 6. Multiply by volume and absolute scale # -------------------------------------------------------------------------------------------------------------- progress.report("Multiplying by volume and absolute scale ...") workspace = self._scale(state=state, workspace=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)
def PyExec(self): # Get the input state = self._get_state() 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, 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=state, workspace=workspace, component=component_as_string) monitor_workspace = self._move(state=state, workspace=monitor_workspace, component=component_as_string) # -------------------------------------------------------------------------------------------------------------- # 5. Apply masking (pixel masking and time masking) # -------------------------------------------------------------------------------------------------------------- progress.report("Masking ...") workspace = self._mask(state=state, workspace=workspace, component=component_as_string) # -------------------------------------------------------------------------------------------------------------- # 6. Convert to Wavelength # -------------------------------------------------------------------------------------------------------------- progress.report("Converting to wavelength ...") workspace = self._convert_to_wavelength(state=state, workspace=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(component_as_string)) dummy_mask_workspace = self._convert_to_wavelength( state=state, workspace=dummy_mask_workspace) # -------------------------------------------------------------------------------------------------------------- # 7. Multiply by volume and absolute scale # -------------------------------------------------------------------------------------------------------------- progress.report("Multiplying by volume and absolute scale ...") workspace = self._scale(state=state, workspace=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, 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=state, workspace=workspace, wavelength_adjustment_workspace=wavelength_adjustment_workspace, pixel_adjustment_workspace=pixel_adjustment_workspace, wavelength_and_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 _get_component(self, workspace): component = DetectorType(self.component) return get_component_name(workspace, component)