def testAbsoluteUnits(self): _add_natural_angle_step_parameter(self._TEST_WS_NAME) geometry = { 'Shape': 'HollowCylinder', 'Height': 4.0, 'InnerRadius': 1.9, 'OuterRadius': 2.0, 'Center': [0.0, 0.0, 0.0]} material = { 'ChemicalFormula': 'Cd S', 'SampleNumberDensity': 0.01} SetSample(self._TEST_WS_NAME, geometry, material) vgeometry = { 'Shape': 'HollowCylinder', 'Height': 4.0, 'InnerRadius': 1.9, 'OuterRadius': 2.0, 'Center': [0.0, 0.0, 0.0]} vmaterial = { 'ChemicalFormula': 'V', 'SampleNumberDensity': 0.1} SetSample(self._VANADIUM_WS_NAME, vgeometry, vmaterial) outWSName = 'outWS' algProperties = { 'InputWorkspace': self._TEST_WS_NAME, 'OutputWorkspace': outWSName, 'SubalgorithmLogging': 'Logging ON', 'AbsoluteUnitsNormalisation': 'Absolute Units ON', 'IntegratedVanadiumWorkspace': self._VANADIUM_WS_NAME, 'rethrow': True } run_algorithm('DirectILLReduction', **algProperties) self.assertTrue(mtd.doesExist(outWSName))
def setUp(self): Load(Filename='irs26176_graphite002_red.nxs', OutputWorkspace='sample') SetSample(InputWorkspace='sample', Geometry={ 'Shape': 'FlatPlate', 'Height': 2.0, 'Width': 2.0, 'Thick': 0.1, 'Center': [0., 0., 0.] }, Material={ 'ChemicalFormula': 'H2-O', 'MassDensity': 1.0 }, ContainerGeometry={ 'Shape': 'FlatPlateHolder', 'Height': 2.0, 'Width': 2.0, 'Thick': 0.1, 'FrontThick': 0.02, 'BackThick': 0.02, 'Center': [0., 0., 0.] }, ContainerMaterial={ 'ChemicalFormula': 'V', 'MassDensity': 6.0 })
def PyExec(self): wksp = self.getProperty("InputWorkspace").value # these items are not grabbed from the logs geometryContainer = self.getProperty("ContainerGeometry").value materialContainer = self.getProperty("ContainerMaterial").value # get a convenient handle to the logs runObject = wksp.run() # this is used for determining some of the log names instrEnum = ConfigService.getInstrument( wksp.getInstrument().getFullName()) # get information from the logs material = self._createMaterial(runObject) geometry = self._createGeometry(runObject, instrEnum) environment = self._createEnvironment(runObject, instrEnum) # let SetSample generate errors if anything is wrong SetSample(InputWorkspace=wksp, Material=material, Geometry=geometry, Environment=environment, ContainerGeometry=geometryContainer, ContainerMaterial=materialContainer) # validate that sample shape was set to something with volume!=0 if (wksp.sample().getShape().volume() == 0): raise RuntimeError("Resulting sample shape has volume of 0")
def runTest(self): config['default.facility'] = 'ILL' config['default.instrument'] = 'IN4' DirectILLCollectData(Run='ILL/IN4/085801-085802.nxs', OutputWorkspace='vanadium', OutputEPPWorkspace='vanadium-epps', OutputRawWorkspace='vanadium-raw', MonitorPeakWidthInSigmas=3.0) DirectILLIntegrateVanadium(InputWorkspace='vanadium', OutputWorkspace='integrated', EPPWorkspace='vanadium-epps') DirectILLDiagnostics( InputWorkspace='vanadium-raw', OutputWorkspace='diagnostics', SubalgorithmLogging='Logging ON', EPPWorkspace='vanadium-epps', ) # Samples DirectILLCollectData(Run='ILL/IN4/087294+087295.nxs', OutputWorkspace='sample', OutputIncidentEnergyWorkspace='Ei', OutputElasticChannelWorkspace='Elp', MonitorPeakWidthInSigmas=3.0) # Containers DirectILLCollectData(Run='ILL/IN4/087306-087309.nxs', OutputWorkspace='container', IncidentEnergyWorkspace='Ei', ElasticChannelWorkspace='Elp', MonitorPeakWidthInSigmas=3.0) geometry = { 'Shape': 'HollowCylinder', 'Height': 4.0, 'InnerRadius': 1.9, 'OuterRadius': 2.0, 'Center': [0.0, 0.0, 0.0] } material = {'ChemicalFormula': 'Cd S', 'SampleNumberDensity': 0.01} SetSample('sample', geometry, material) DirectILLSelfShielding(InputWorkspace='sample', OutputWorkspace='corrections', EventsPerPoint=20000) DirectILLApplySelfShielding( InputWorkspace='sample', OutputWorkspace='corrected', SelfShieldingCorrectionWorkspace='corrections', EmptyContainerWorkspace='container') DirectILLReduction(InputWorkspace='corrected', OutputWorkspace='SofQW', IntegratedVanadiumWorkspace='integrated', DiagnosticsWorkspace='diagnostics') CropWorkspace(InputWorkspace='SofQW', OutputWorkspace='cropped', XMin=1., XMax=2.75, StartWorkspaceIndex=83, EndWorkspaceIndex=222) # The 'run_title' property has been deliberately erased from the test numor. # We need to add it manually because Save/LoadNexus will do the same for # the reference file. mtd['cropped'].mutableRun().addProperty('run_title', '', True)
def test_generate_geometry_cylinder_with_container(self): workspace = CreateSampleWorkspace() # float radius_float = 1.0 height_float = 2.0 center_float = [1.0, 2.0, 3.0] sample_details_float = sample_details.SampleDetails( radius=radius_float, shape="cylinder", height=height_float, center=center_float) sample_details_float.set_material(chemical_formula='Si') sample_details_float.set_container(radius=2.0, chemical_formula='V') # int radius_int = 1 height_int = 3 center_int = [1, 2, 3] sample_details_int = sample_details.SampleDetails(radius=radius_int, shape="cylinder", height=height_int, center=center_int) sample_details_int.set_material(chemical_formula='Si') sample_details_int.set_container(radius=2, chemical_formula='V') # string radius_string = "1" height_string = "2" center_string = ["1", "2", "3"] sample_details_string = sample_details.SampleDetails( radius=radius_string, shape="cylinder", height=height_string, center=center_string) sample_details_string.set_material(chemical_formula='Si') sample_details_string.set_container(radius="2", chemical_formula='V') # mix radius_mix = 1.23 height_mix = 2 center_mix = ["1", 2, 3.45] sample_details_mix = sample_details.SampleDetails(radius=radius_mix, shape="cylinder", height=height_mix, center=center_mix) sample_details_mix.set_material(chemical_formula='Si') sample_details_mix.set_container(radius="2", chemical_formula='V') sample_details_objects = [ sample_details_float, sample_details_int, sample_details_string, sample_details_mix ] for sample_details_object in sample_details_objects: SetSample( workspace, Geometry=sample_details_object.generate_sample_geometry(), Material=sample_details_object.generate_sample_material(), ContainerGeometry=sample_details_object. generate_container_geometry(), ContainerMaterial=sample_details_object. generate_container_material())
def setup_sample(donor_ws, material, geometry, environment): """ Calls SetSample with the associated sample and container material and geometry for use in creating an input workspace for an Absorption Correction algorithm :param donor_ws: :param material: :param geometry: :param environment: """ # Set the material, geometry, and container info SetSample(InputWorkspace=donor_ws, Material=material, Geometry=geometry, Environment=environment)
def set_sample(ws_name, geometry=None, chemical_formula=None, mass_density=None): if 'Center' not in geometry: geometry.update({'Center': [ 0., 0., 0., ]}) if "Shape" not in geometry: geometry.update({'Shape': 'Cylinder'}) SetSample(InputWorkspace=ws_name, Geometry=geometry, Material={ 'ChemicalFormula': chemical_formula, 'SampleMassDensity': mass_density })
def testAbsoluteUnitsNoVanadiumMaterial(self): _add_natural_angle_step_parameter(self._TEST_WS_NAME) geometry = { 'Shape': 'HollowCylinder', 'Height': 4.0, 'InnerRadius': 1.9, 'OuterRadius': 2.0, 'Center': [0.0, 0.0, 0.0]} material = { 'ChemicalFormula': 'Cd S', 'SampleNumberDensity': 0.01} SetSample(self._TEST_WS_NAME, geometry, material) algProperties = { 'InputWorkspace': self._TEST_WS_NAME, 'OutputWorkspace': 'outWS', 'SubalgorithmLogging': 'Logging ON', 'AbsoluteUnitsNormalisation': 'Absolute Units ON', 'IntegratedVanadiumWorkspace': self._VANADIUM_WS_NAME } self.assertRaises(RuntimeError,DirectILLReduction,**algProperties)
def setUpClass(cls): Load('irs26176_graphite002_red.nxs', OutputWorkspace='red_ws') Load('osi104367_elf.nxs', OutputWorkspace='indirect_elastic_ws') Load('ILL_IN16B_FWS_Reduced.nxs', OutputWorkspace='indirect_fws_ws') Load('HRP38692a.nxs', OutputWorkspace='elastic_ws') Load('MAR21335_Ei60meV.nxs', OutputWorkspace='direct_ws') Load('irs26176_graphite002_red.nxs', OutputWorkspace='geoms_ws') # set this workspace to have defined sample and can geometries to test the preset option SetSample('geoms_ws', Geometry={ 'Shape': 'Cylinder', 'Height': 4.0, 'Radius': 2.0, 'Center': [0., 0., 0.] }, Material={'ChemicalFormula': 'Ni'}, ContainerGeometry={ 'Shape': 'HollowCylinder', 'Height': 4.0, 'InnerRadius': 2.0, 'OuterRadius': 3.5 })
def PyExec(self): raw_ws = self.getProperty('InputWorkspace').value sample_geometry = self.getPropertyValue('SampleGeometry') sample_material = self.getPropertyValue('SampleMaterial') cal_file_name = self.getPropertyValue('CalFileName') SetSample(InputWorkspace=raw_ws, Geometry=sample_geometry, Material=sample_material) # find the closest monitor to the sample for incident spectrum raw_spec_info = raw_ws.spectrumInfo() incident_index = None for i in range(raw_spec_info.size()): if raw_spec_info.isMonitor(i): l2 = raw_spec_info.position(i)[2] if not incident_index: incident_index = i else: if raw_spec_info.position(incident_index)[2] < l2 < 0: incident_index = i monitor = ExtractSpectra(InputWorkspace=raw_ws, WorkspaceIndexList=[incident_index]) monitor = ConvertUnits(InputWorkspace=monitor, Target="Wavelength") x_data = monitor.dataX(0) min_x = np.min(x_data) max_x = np.max(x_data) width_x = (max_x - min_x) / x_data.size fit_spectra = FitIncidentSpectrum( InputWorkspace=monitor, BinningForCalc=[min_x, 1 * width_x, max_x], BinningForFit=[min_x, 10 * width_x, max_x], FitSpectrumWith="CubicSpline") self_scattering_correction = CalculatePlaczekSelfScattering( InputWorkspace=raw_ws, IncidentSpecta=fit_spectra) cal_workspace = LoadCalFile(InputWorkspace=self_scattering_correction, CalFileName=cal_file_name, Workspacename='cal_workspace', MakeOffsetsWorkspace=False, MakeMaskWorkspace=False) self_scattering_correction = DiffractionFocussing( InputWorkspace=self_scattering_correction, GroupingFilename=cal_file_name) n_pixel = np.zeros(self_scattering_correction.getNumberHistograms()) for i in range(cal_workspace.getNumberHistograms()): grouping = cal_workspace.dataY(i) if grouping[0] > 0: n_pixel[int(grouping[0] - 1)] += 1 correction_ws = CreateWorkspace( DataY=n_pixel, DataX=[0, 1], NSpec=self_scattering_correction.getNumberHistograms()) self_scattering_correction = Divide( LHSWorkspace=self_scattering_correction, RHSWorkspace=correction_ws) ConvertToDistribution(Workspace=self_scattering_correction) self_scattering_correction = ConvertUnits( InputWorkspace=self_scattering_correction, Target="MomentumTransfer", EMode='Elastic') DeleteWorkspace('cal_workspace_group') DeleteWorkspace(correction_ws) DeleteWorkspace(fit_spectra) DeleteWorkspace(monitor) DeleteWorkspace(raw_ws) self.setProperty('OutputWorkspace', self_scattering_correction)
def TotalScatteringReduction(config=None): facility = config['Facility'] title = config['Title'] instr = config['Instrument'] # Get an instance to Mantid's logger log = Logger("TotalScatteringReduction") # Get sample info sample = get_sample(config) sam_mass_density = sample.get('MassDensity', None) sam_packing_fraction = sample.get('PackingFraction', None) sam_geometry = sample.get('Geometry', None) sam_material = sample.get('Material', None) sam_geo_dict = { 'Shape': 'Cylinder', 'Radius': config['Sample']['Geometry']['Radius'], 'Height': config['Sample']['Geometry']['Height'] } sam_mat_dict = { 'ChemicalFormula': sam_material, 'SampleMassDensity': sam_mass_density } if 'Environment' in config: sam_env_dict = { 'Name': config['Environment']['Name'], 'Container': config['Environment']['Container'] } else: sam_env_dict = {'Name': 'InAir', 'Container': 'PAC06'} # Get normalization info van = get_normalization(config) van_mass_density = van.get('MassDensity', None) van_packing_fraction = van.get('PackingFraction', 1.0) van_geometry = van.get('Geometry', None) van_material = van.get('Material', 'V') van_geo_dict = { 'Shape': 'Cylinder', 'Radius': config['Normalization']['Geometry']['Radius'], 'Height': config['Normalization']['Geometry']['Height'] } van_mat_dict = { 'ChemicalFormula': van_material, 'SampleMassDensity': van_mass_density } # Get calibration, characterization, and other settings merging = config['Merging'] binning = merging['QBinning'] characterizations = merging.get('Characterizations', None) # Grouping grouping = merging.get('Grouping', None) cache_dir = config.get("CacheDir", os.path.abspath('.')) OutputDir = config.get("OutputDir", os.path.abspath('.')) # Create Nexus file basenames sample['Runs'] = expand_ints(sample['Runs']) sample['Background']['Runs'] = expand_ints(sample['Background'].get( 'Runs', None)) ''' Currently not implemented: # wkspIndices = merging.get('SumBanks', None) # high_q_linear_fit_range = config['HighQLinearFitRange'] POWGEN options not used #alignAndFocusArgs['RemovePromptPulseWidth'] = 50 # alignAndFocusArgs['CompressTolerance'] use defaults # alignAndFocusArgs['UnwrapRef'] POWGEN option # alignAndFocusArgs['LowResRef'] POWGEN option # alignAndFocusArgs['LowResSpectrumOffset'] POWGEN option How much of each bank gets merged has info here in the form of # {"ID", "Qmin", "QMax"} # alignAndFocusArgs['CropWavelengthMin'] from characterizations file # alignAndFocusArgs['CropWavelengthMax'] from characterizations file ''' if facility == 'SNS': facility_file_format = '%s_%d' else: facility_file_format = '%s%d' sam_scans = ','.join( [facility_file_format % (instr, num) for num in sample['Runs']]) container_scans = ','.join([ facility_file_format % (instr, num) for num in sample['Background']["Runs"] ]) container_bg = None if "Background" in sample['Background']: sample['Background']['Background']['Runs'] = expand_ints( sample['Background']['Background']['Runs']) container_bg = ','.join([ facility_file_format % (instr, num) for num in sample['Background']['Background']['Runs'] ]) if len(container_bg) == 0: container_bg = None van['Runs'] = expand_ints(van['Runs']) van_scans = ','.join( [facility_file_format % (instr, num) for num in van['Runs']]) van_bg_scans = None if 'Background' in van: van_bg_scans = van['Background']['Runs'] van_bg_scans = expand_ints(van_bg_scans) van_bg_scans = ','.join( [facility_file_format % (instr, num) for num in van_bg_scans]) # Override Nexus file basename with Filenames if present if "Filenames" in sample: sam_scans = ','.join(sample["Filenames"]) if "Filenames" in sample['Background']: container_scans = ','.join(sample['Background']["Filenames"]) if "Background" in sample['Background']: if "Filenames" in sample['Background']['Background']: container_bg = ','.join( sample['Background']['Background']['Filenames']) if "Filenames" in van: van_scans = ','.join(van["Filenames"]) if "Background" in van: if "Filenames" in van['Background']: van_bg_scans = ','.join(van['Background']["Filenames"]) # Output nexus filename nexus_filename = title + '.nxs' try: os.remove(nexus_filename) except OSError: pass # Get sample corrections sam_abs_corr = sample.get("AbsorptionCorrection", None) sam_ms_corr = sample.get("MultipleScatteringCorrection", None) sam_inelastic_corr = SetInelasticCorrection( sample.get('InelasticCorrection', None)) # Warn about having absorption correction and multiple scat correction set if sam_abs_corr and sam_ms_corr: log.warning(MS_AND_ABS_CORR_WARNING) # Compute the absorption correction on the sample if it was provided sam_abs_ws = '' con_abs_ws = '' if sam_abs_corr: msg = "Applying '{}' absorption correction to sample" log.notice(msg.format(sam_abs_corr["Type"])) sam_abs_ws, con_abs_ws = create_absorption_wksp( sam_scans, sam_abs_corr["Type"], sam_geo_dict, sam_mat_dict, sam_env_dict, **config) # Get vanadium corrections van_mass_density = van.get('MassDensity', van_mass_density) van_packing_fraction = van.get('PackingFraction', van_packing_fraction) van_abs_corr = van.get("AbsorptionCorrection", {"Type": None}) van_ms_corr = van.get("MultipleScatteringCorrection", {"Type": None}) van_inelastic_corr = SetInelasticCorrection( van.get('InelasticCorrection', None)) # Warn about having absorption correction and multiple scat correction set if van_abs_corr["Type"] and van_ms_corr["Type"]: log.warning(MS_AND_ABS_CORR_WARNING) # Compute the absorption correction for the vanadium if provided van_abs_corr_ws = '' if van_abs_corr: msg = "Applying '{}' absorption correction to vanadium" log.notice(msg.format(van_abs_corr["Type"])) van_abs_corr_ws, van_con_ws = create_absorption_wksp( van_scans, van_abs_corr["Type"], van_geo_dict, van_mat_dict, **config) alignAndFocusArgs = dict() alignAndFocusArgs['CalFilename'] = config['Calibration']['Filename'] # alignAndFocusArgs['GroupFilename'] don't use # alignAndFocusArgs['Params'] = "0.,0.02,40." alignAndFocusArgs['ResampleX'] = -6000 alignAndFocusArgs['Dspacing'] = False alignAndFocusArgs['PreserveEvents'] = False alignAndFocusArgs['MaxChunkSize'] = 8 alignAndFocusArgs['CacheDir'] = os.path.abspath(cache_dir) # Get any additional AlignAndFocusArgs from JSON input if "AlignAndFocusArgs" in config: otherArgs = config["AlignAndFocusArgs"] alignAndFocusArgs.update(otherArgs) # Setup grouping output_grouping = False grp_wksp = "wksp_output_group" if grouping: if 'Initial' in grouping: if grouping['Initial'] and not grouping['Initial'] == u'': alignAndFocusArgs['GroupFilename'] = grouping['Initial'] if 'Output' in grouping: if grouping['Output'] and not grouping['Output'] == u'': output_grouping = True LoadDetectorsGroupingFile(InputFile=grouping['Output'], OutputWorkspace=grp_wksp) # If no output grouping specified, create it with Calibration Grouping if not output_grouping: LoadDiffCal(alignAndFocusArgs['CalFilename'], InstrumentName=instr, WorkspaceName=grp_wksp.replace('_group', ''), MakeGroupingWorkspace=True, MakeCalWorkspace=False, MakeMaskWorkspace=False) # Setup the 6 bank method if no grouping specified if not grouping: CreateGroupingWorkspace(InstrumentName=instr, GroupDetectorsBy='Group', OutputWorkspace=grp_wksp) alignAndFocusArgs['GroupingWorkspace'] = grp_wksp # TODO take out the RecalculatePCharge in the future once tested # Load Sample print("#-----------------------------------#") print("# Sample") print("#-----------------------------------#") sam_wksp = load('sample', sam_scans, sam_geometry, sam_material, sam_mass_density, sam_abs_ws, **alignAndFocusArgs) sample_title = "sample_and_container" save_banks(InputWorkspace=sam_wksp, Filename=nexus_filename, Title=sample_title, OutputDir=OutputDir, GroupingWorkspace=grp_wksp, Binning=binning) sam_molecular_mass = mtd[sam_wksp].sample().getMaterial( ).relativeMolecularMass() natoms = getNumberAtoms(sam_packing_fraction, sam_mass_density, sam_molecular_mass, Geometry=sam_geometry) # Load Sample Container print("#-----------------------------------#") print("# Sample Container") print("#-----------------------------------#") container = load('container', container_scans, absorption_wksp=con_abs_ws, **alignAndFocusArgs) save_banks(InputWorkspace=container, Filename=nexus_filename, Title=container, OutputDir=OutputDir, GroupingWorkspace=grp_wksp, Binning=binning) # Load Sample Container Background if container_bg is not None: print("#-----------------------------------#") print("# Sample Container's Background") print("#-----------------------------------#") container_bg = load('container_background', container_bg, **alignAndFocusArgs) save_banks(InputWorkspace=container_bg, Filename=nexus_filename, Title=container_bg, OutputDir=OutputDir, GroupingWorkspace=grp_wksp, Binning=binning) # Load Vanadium print("#-----------------------------------#") print("# Vanadium") print("#-----------------------------------#") van_wksp = load('vanadium', van_scans, van_geometry, van_material, van_mass_density, van_abs_corr_ws, **alignAndFocusArgs) vanadium_title = "vanadium_and_background" save_banks(InputWorkspace=van_wksp, Filename=nexus_filename, Title=vanadium_title, OutputDir=OutputDir, GroupingWorkspace=grp_wksp, Binning=binning) van_material = mtd[van_wksp].sample().getMaterial() van_molecular_mass = van_material.relativeMolecularMass() nvan_atoms = getNumberAtoms(1.0, van_mass_density, van_molecular_mass, Geometry=van_geometry) print("Sample natoms:", natoms) print("Vanadium natoms:", nvan_atoms) print("Vanadium natoms / Sample natoms:", nvan_atoms / natoms) # Load Vanadium Background van_bg = None if van_bg_scans is not None: print("#-----------------------------------#") print("# Vanadium Background") print("#-----------------------------------#") van_bg = load('vanadium_background', van_bg_scans, **alignAndFocusArgs) vanadium_bg_title = "vanadium_background" save_banks(InputWorkspace=van_bg, Filename=nexus_filename, Title=vanadium_bg_title, OutputDir=OutputDir, GroupingWorkspace=grp_wksp, Binning=binning) # Load Instrument Characterizations if characterizations: PDDetermineCharacterizations( InputWorkspace=sam_wksp, Characterizations='characterizations', ReductionProperties='__snspowderreduction') propMan = PropertyManagerDataService.retrieve('__snspowderreduction') qmax = 2. * np.pi / propMan['d_min'].value qmin = 2. * np.pi / propMan['d_max'].value for a, b in zip(qmin, qmax): print('Qrange:', a, b) # TODO: Add when we apply Qmin, Qmax cropping # mask_info = generate_cropping_table(qmin, qmax) # STEP 1: Subtract Backgrounds sam_raw = 'sam_raw' CloneWorkspace(InputWorkspace=sam_wksp, OutputWorkspace=sam_raw) # for later container_raw = 'container_raw' CloneWorkspace(InputWorkspace=container, OutputWorkspace=container_raw) # for later if van_bg is not None: RebinToWorkspace(WorkspaceToRebin=van_bg, WorkspaceToMatch=van_wksp, OutputWorkspace=van_bg) Minus(LHSWorkspace=van_wksp, RHSWorkspace=van_bg, OutputWorkspace=van_wksp) RebinToWorkspace(WorkspaceToRebin=container, WorkspaceToMatch=sam_wksp, OutputWorkspace=container) Minus(LHSWorkspace=sam_wksp, RHSWorkspace=container, OutputWorkspace=sam_wksp) if container_bg is not None: RebinToWorkspace(WorkspaceToRebin=container_bg, WorkspaceToMatch=container, OutputWorkspace=container_bg) Minus(LHSWorkspace=container, RHSWorkspace=container_bg, OutputWorkspace=container) for wksp in [container, van_wksp, sam_wksp]: ConvertUnits(InputWorkspace=wksp, OutputWorkspace=wksp, Target="MomentumTransfer", EMode="Elastic") container_title = "container_minus_back" vanadium_title = "vanadium_minus_back" sample_title = "sample_minus_back" save_banks(InputWorkspace=container, Filename=nexus_filename, Title=container_title, OutputDir=OutputDir, GroupingWorkspace=grp_wksp, Binning=binning) save_banks(InputWorkspace=van_wksp, Filename=nexus_filename, Title=vanadium_title, OutputDir=OutputDir, GroupingWorkspace=grp_wksp, Binning=binning) save_banks(InputWorkspace=sam_wksp, Filename=nexus_filename, Title=sample_title, OutputDir=OutputDir, GroupingWorkspace=grp_wksp, Binning=binning) # STEP 2.0: Prepare vanadium as normalization calibrant # Multiple-Scattering and Absorption (Steps 2-4) for Vanadium van_corrected = 'van_corrected' ConvertUnits(InputWorkspace=van_wksp, OutputWorkspace=van_corrected, Target="Wavelength", EMode="Elastic") if "Type" in van_abs_corr: if van_abs_corr['Type'] == 'Carpenter' \ or van_ms_corr['Type'] == 'Carpenter': CarpenterSampleCorrection( InputWorkspace=van_corrected, OutputWorkspace=van_corrected, CylinderSampleRadius=van['Geometry']['Radius']) elif van_abs_corr['Type'] == 'Mayers' \ or van_ms_corr['Type'] == 'Mayers': if van_ms_corr['Type'] == 'Mayers': MayersSampleCorrection(InputWorkspace=van_corrected, OutputWorkspace=van_corrected, MultipleScattering=True) else: MayersSampleCorrection(InputWorkspace=van_corrected, OutputWorkspace=van_corrected, MultipleScattering=False) else: print("NO VANADIUM absorption or multiple scattering!") else: CloneWorkspace(InputWorkspace=van_corrected, OutputWorkspace=van_corrected) ConvertUnits(InputWorkspace=van_corrected, OutputWorkspace=van_corrected, Target='MomentumTransfer', EMode='Elastic') vanadium_title += "_ms_abs_corrected" save_banks(InputWorkspace=van_corrected, Filename=nexus_filename, Title=vanadium_title, OutputDir=OutputDir, GroupingWorkspace=grp_wksp, Binning=binning) save_banks(InputWorkspace=van_corrected, Filename=nexus_filename, Title=vanadium_title + "_with_peaks", OutputDir=OutputDir, GroupingWorkspace=grp_wksp, Binning=binning) # TODO subtract self-scattering of vanadium (According to Eq. 7 of Howe, # McGreevey, and Howells, JPCM, 1989) # Smooth Vanadium (strip peaks plus smooth) ConvertUnits(InputWorkspace=van_corrected, OutputWorkspace=van_corrected, Target='dSpacing', EMode='Elastic') # After StripVanadiumPeaks, the workspace goes from EventWorkspace -> # Workspace2D StripVanadiumPeaks(InputWorkspace=van_corrected, OutputWorkspace=van_corrected, BackgroundType='Quadratic') ConvertUnits(InputWorkspace=van_corrected, OutputWorkspace=van_corrected, Target='MomentumTransfer', EMode='Elastic') vanadium_title += '_peaks_stripped' save_banks(InputWorkspace=van_corrected, Filename=nexus_filename, Title=vanadium_title, OutputDir=OutputDir, GroupingWorkspace=grp_wksp, Binning=binning) ConvertUnits(InputWorkspace=van_corrected, OutputWorkspace=van_corrected, Target='TOF', EMode='Elastic') FFTSmooth(InputWorkspace=van_corrected, OutputWorkspace=van_corrected, Filter="Butterworth", Params='20,2', IgnoreXBins=True, AllSpectra=True) ConvertUnits(InputWorkspace=van_corrected, OutputWorkspace=van_corrected, Target='MomentumTransfer', EMode='Elastic') vanadium_title += '_smoothed' save_banks(InputWorkspace=van_corrected, Filename=nexus_filename, Title=vanadium_title, OutputDir=OutputDir, GroupingWorkspace=grp_wksp, Binning=binning) # Inelastic correction if van_inelastic_corr['Type'] == "Placzek": van_scan = van['Runs'][0] van_incident_wksp = 'van_incident_wksp' van_inelastic_opts = van['InelasticCorrection'] lambda_binning_fit = van_inelastic_opts['LambdaBinningForFit'] lambda_binning_calc = van_inelastic_opts['LambdaBinningForCalc'] print('van_scan:', van_scan) GetIncidentSpectrumFromMonitor(Filename=facility_file_format % (instr, van_scan), OutputWorkspace=van_incident_wksp) fit_type = van['InelasticCorrection']['FitSpectrumWith'] FitIncidentSpectrum(InputWorkspace=van_incident_wksp, OutputWorkspace=van_incident_wksp, FitSpectrumWith=fit_type, BinningForFit=lambda_binning_fit, BinningForCalc=lambda_binning_calc, PlotDiagnostics=False) van_placzek = 'van_placzek' SetSample(InputWorkspace=van_incident_wksp, Material={ 'ChemicalFormula': str(van_material), 'SampleMassDensity': str(van_mass_density) }) CalculatePlaczekSelfScattering(IncidentWorkspace=van_incident_wksp, ParentWorkspace=van_corrected, OutputWorkspace=van_placzek, L1=19.5, L2=alignAndFocusArgs['L2'], Polar=alignAndFocusArgs['Polar']) ConvertToHistogram(InputWorkspace=van_placzek, OutputWorkspace=van_placzek) # Save before rebin in Q for wksp in [van_placzek, van_corrected]: ConvertUnits(InputWorkspace=wksp, OutputWorkspace=wksp, Target='MomentumTransfer', EMode='Elastic') Rebin(InputWorkspace=wksp, OutputWorkspace=wksp, Params=binning, PreserveEvents=True) save_banks(InputWorkspace=van_placzek, Filename=nexus_filename, Title="vanadium_placzek", OutputDir=OutputDir, GroupingWorkspace=grp_wksp, Binning=binning) # Rebin in Wavelength for wksp in [van_placzek, van_corrected]: ConvertUnits(InputWorkspace=wksp, OutputWorkspace=wksp, Target='Wavelength', EMode='Elastic') Rebin(InputWorkspace=wksp, OutputWorkspace=wksp, Params=lambda_binning_calc, PreserveEvents=True) # Save after rebin in Q for wksp in [van_placzek, van_corrected]: ConvertUnits(InputWorkspace=wksp, OutputWorkspace=wksp, Target='MomentumTransfer', EMode='Elastic') # Subtract correction in Wavelength for wksp in [van_placzek, van_corrected]: ConvertUnits(InputWorkspace=wksp, OutputWorkspace=wksp, Target='Wavelength', EMode='Elastic') if not mtd[wksp].isDistribution(): ConvertToDistribution(wksp) Minus(LHSWorkspace=van_corrected, RHSWorkspace=van_placzek, OutputWorkspace=van_corrected) # Save after subtraction for wksp in [van_placzek, van_corrected]: ConvertUnits(InputWorkspace=wksp, OutputWorkspace=wksp, Target='MomentumTransfer', EMode='Elastic') vanadium_title += '_placzek_corrected' save_banks(InputWorkspace=van_corrected, Filename=nexus_filename, Title=vanadium_title, OutputDir=OutputDir, GroupingWorkspace=grp_wksp, Binning=binning) ConvertUnits(InputWorkspace=van_corrected, OutputWorkspace=van_corrected, Target='MomentumTransfer', EMode='Elastic') SetUncertainties(InputWorkspace=van_corrected, OutputWorkspace=van_corrected, SetError='zero') # STEP 2.1: Normalize by Vanadium wksp_list = [sam_wksp, sam_raw, van_corrected] for name in wksp_list: ConvertUnits(InputWorkspace=name, OutputWorkspace=name, Target='MomentumTransfer', EMode='Elastic', ConvertFromPointData=False) Rebin(InputWorkspace=name, OutputWorkspace=name, Params=binning, PreserveEvents=True) # Save the sample - back / normalized Divide(LHSWorkspace=sam_wksp, RHSWorkspace=van_corrected, OutputWorkspace=sam_wksp) sample_title += "_normalized" save_banks(InputWorkspace=sam_wksp, Filename=nexus_filename, Title=sample_title, OutputDir=OutputDir, GroupingWorkspace=grp_wksp, Binning=binning) # Save the sample / normalized (ie no background subtraction) Divide(LHSWorkspace=sam_raw, RHSWorkspace=van_corrected, OutputWorkspace=sam_raw) save_banks(InputWorkspace=sam_raw, Filename=nexus_filename, Title="sample_normalized", OutputDir=OutputDir, GroupingWorkspace=grp_wksp, Binning=binning) # Output an initial I(Q) for sample iq_filename = title + '_initial_iofq_banks.nxs' save_banks(InputWorkspace=sam_wksp, Filename=iq_filename, Title="IQ_banks", OutputDir=OutputDir, GroupingWorkspace=grp_wksp, Binning=binning) wksp_list = [container, container_raw, van_corrected] if container_bg is not None: wksp_list.append(container_bg) if van_bg is not None: wksp_list.append(van_bg) for name in wksp_list: ConvertUnits(InputWorkspace=name, OutputWorkspace=name, Target='MomentumTransfer', EMode='Elastic', ConvertFromPointData=False) Rebin(InputWorkspace=name, OutputWorkspace=name, Params=binning, PreserveEvents=True) # Save the container - container_background / normalized Divide(LHSWorkspace=container, RHSWorkspace=van_corrected, OutputWorkspace=container) container_title += '_normalized' save_banks(InputWorkspace=container, Filename=nexus_filename, Title=container_title, OutputDir=OutputDir, GroupingWorkspace=grp_wksp, Binning=binning) # Save the container / normalized (ie no background subtraction) Divide(LHSWorkspace=container_raw, RHSWorkspace=van_corrected, OutputWorkspace=container_raw) save_banks(InputWorkspace=container_raw, Filename=nexus_filename, Title="container_normalized", OutputDir=OutputDir, GroupingWorkspace=grp_wksp, Binning=binning) # Save the container_background / normalized if container_bg is not None: Divide(LHSWorkspace=container_bg, RHSWorkspace=van_corrected, OutputWorkspace=container_bg) container_bg_title = "container_back_normalized" save_banks(InputWorkspace=container_bg, Filename=nexus_filename, Title=container_bg_title, OutputDir=OutputDir, GroupingWorkspace=grp_wksp, Binning=binning) # Save the vanadium_background / normalized if van_bg is not None: Divide(LHSWorkspace=van_bg, RHSWorkspace=van_corrected, OutputWorkspace=van_bg) vanadium_bg_title += "_normalized" save_banks(InputWorkspace=van_bg, Filename=nexus_filename, Title=vanadium_bg_title, OutputDir=OutputDir, GroupingWorkspace=grp_wksp, Binning=binning) # STEP 3 & 4: Subtract multiple scattering and apply absorption correction ConvertUnits(InputWorkspace=sam_wksp, OutputWorkspace=sam_wksp, Target="Wavelength", EMode="Elastic") sam_corrected = 'sam_corrected' if sam_abs_corr and sam_ms_corr: if sam_abs_corr['Type'] == 'Carpenter' \ or sam_ms_corr['Type'] == 'Carpenter': CarpenterSampleCorrection( InputWorkspace=sam_wksp, OutputWorkspace=sam_corrected, CylinderSampleRadius=sample['Geometry']['Radius']) elif sam_abs_corr['Type'] == 'Mayers' \ or sam_ms_corr['Type'] == 'Mayers': if sam_ms_corr['Type'] == 'Mayers': MayersSampleCorrection(InputWorkspace=sam_wksp, OutputWorkspace=sam_corrected, MultipleScattering=True) else: MayersSampleCorrection(InputWorkspace=sam_wksp, OutputWorkspace=sam_corrected, MultipleScattering=False) else: print("NO SAMPLE absorption or multiple scattering!") CloneWorkspace(InputWorkspace=sam_wksp, OutputWorkspace=sam_corrected) ConvertUnits(InputWorkspace=sam_corrected, OutputWorkspace=sam_corrected, Target='MomentumTransfer', EMode='Elastic') sample_title += "_ms_abs_corrected" save_banks(InputWorkspace=sam_corrected, Filename=nexus_filename, Title=sample_title, OutputDir=OutputDir, GroupingWorkspace=grp_wksp, Binning=binning) else: CloneWorkspace(InputWorkspace=sam_wksp, OutputWorkspace=sam_corrected) # STEP 5: Divide by number of atoms in sample mtd[sam_corrected] = (nvan_atoms / natoms) * mtd[sam_corrected] ConvertUnits(InputWorkspace=sam_corrected, OutputWorkspace=sam_corrected, Target='MomentumTransfer', EMode='Elastic') sample_title += "_norm_by_atoms" save_banks(InputWorkspace=sam_corrected, Filename=nexus_filename, Title=sample_title, OutputDir=OutputDir, GroupingWorkspace=grp_wksp, Binning=binning) # STEP 6: Divide by total scattering length squared = total scattering # cross-section over 4 * pi van_material = mtd[van_corrected].sample().getMaterial() sigma_v = van_material.totalScatterXSection() prefactor = (sigma_v / (4. * np.pi)) msg = "Total scattering cross-section of Vanadium:{} sigma_v / 4*pi: {}" print(msg.format(sigma_v, prefactor)) mtd[sam_corrected] = prefactor * mtd[sam_corrected] sample_title += '_multiply_by_vanSelfScat' save_banks(InputWorkspace=sam_corrected, Filename=nexus_filename, Title=sample_title, OutputDir=OutputDir, GroupingWorkspace=grp_wksp, Binning=binning) # STEP 7: Inelastic correction ConvertUnits(InputWorkspace=sam_corrected, OutputWorkspace=sam_corrected, Target='Wavelength', EMode='Elastic') if sam_inelastic_corr['Type'] == "Placzek": if sam_material is None: error = "For Placzek correction, must specifiy a sample material." raise Exception(error) for sam_scan in sample['Runs']: sam_incident_wksp = 'sam_incident_wksp' sam_inelastic_opts = sample['InelasticCorrection'] lambda_binning_fit = sam_inelastic_opts['LambdaBinningForFit'] lambda_binning_calc = sam_inelastic_opts['LambdaBinningForCalc'] GetIncidentSpectrumFromMonitor(Filename=facility_file_format % (instr, sam_scan), OutputWorkspace=sam_incident_wksp) fit_type = sample['InelasticCorrection']['FitSpectrumWith'] FitIncidentSpectrum(InputWorkspace=sam_incident_wksp, OutputWorkspace=sam_incident_wksp, FitSpectrumWith=fit_type, BinningForFit=lambda_binning_fit, BinningForCalc=lambda_binning_calc) sam_placzek = 'sam_placzek' SetSample(InputWorkspace=sam_incident_wksp, Material={ 'ChemicalFormula': str(sam_material), 'SampleMassDensity': str(sam_mass_density) }) CalculatePlaczekSelfScattering(IncidentWorkspace=sam_incident_wksp, ParentWorkspace=sam_corrected, OutputWorkspace=sam_placzek, L1=19.5, L2=alignAndFocusArgs['L2'], Polar=alignAndFocusArgs['Polar']) ConvertToHistogram(InputWorkspace=sam_placzek, OutputWorkspace=sam_placzek) # Save before rebin in Q for wksp in [sam_placzek, sam_corrected]: ConvertUnits(InputWorkspace=wksp, OutputWorkspace=wksp, Target='MomentumTransfer', EMode='Elastic') Rebin(InputWorkspace=wksp, OutputWorkspace=wksp, Params=binning, PreserveEvents=True) save_banks(InputWorkspace=sam_placzek, Filename=nexus_filename, Title="sample_placzek", OutputDir=OutputDir, GroupingWorkspace=grp_wksp, Binning=binning) # Save after rebin in Q for wksp in [sam_placzek, sam_corrected]: ConvertUnits(InputWorkspace=wksp, OutputWorkspace=wksp, Target='MomentumTransfer', EMode='Elastic') Minus(LHSWorkspace=sam_corrected, RHSWorkspace=sam_placzek, OutputWorkspace=sam_corrected) # Save after subtraction for wksp in [sam_placzek, sam_corrected]: ConvertUnits(InputWorkspace=wksp, OutputWorkspace=wksp, Target='MomentumTransfer', EMode='Elastic') sample_title += '_placzek_corrected' save_banks(InputWorkspace=sam_corrected, Filename=nexus_filename, Title=sample_title, OutputDir=OutputDir, GroupingWorkspace=grp_wksp, Binning=binning) # STEP 7: Output spectrum # TODO Since we already went from Event -> 2D workspace, can't use this # anymore print('sam:', mtd[sam_corrected].id()) print('van:', mtd[van_corrected].id()) if alignAndFocusArgs['PreserveEvents']: CompressEvents(InputWorkspace=sam_corrected, OutputWorkspace=sam_corrected) # F(Q) bank-by-bank Section fq_banks_wksp = "FQ_banks_wksp" CloneWorkspace(InputWorkspace=sam_corrected, OutputWorkspace=fq_banks_wksp) # TODO: Add the following when implemented - FQ_banks = 'FQ_banks' # S(Q) bank-by-bank Section material = mtd[sam_corrected].sample().getMaterial() if material.name() is None or len(material.name().strip()) == 0: raise RuntimeError('Sample material was not set') bcoh_avg_sqrd = material.cohScatterLength() * material.cohScatterLength() btot_sqrd_avg = material.totalScatterLengthSqrd() laue_monotonic_diffuse_scat = btot_sqrd_avg / bcoh_avg_sqrd sq_banks_wksp = 'SQ_banks_wksp' CloneWorkspace(InputWorkspace=sam_corrected, OutputWorkspace=sq_banks_wksp) # TODO: Add the following when implemented ''' SQ_banks = (1. / bcoh_avg_sqrd) * \ mtd[sq_banks_wksp] - laue_monotonic_diffuse_scat + 1. ''' # Save S(Q) and F(Q) to diagnostics NeXus file save_banks(InputWorkspace=fq_banks_wksp, Filename=nexus_filename, Title="FQ_banks", OutputDir=OutputDir, GroupingWorkspace=grp_wksp, Binning=binning) save_banks(InputWorkspace=sq_banks_wksp, Filename=nexus_filename, Title="SQ_banks", OutputDir=OutputDir, GroupingWorkspace=grp_wksp, Binning=binning) # Output a main S(Q) and F(Q) file fq_filename = title + '_fofq_banks_corrected.nxs' save_banks(InputWorkspace=fq_banks_wksp, Filename=fq_filename, Title="FQ_banks", OutputDir=OutputDir, GroupingWorkspace=grp_wksp, Binning=binning) sq_filename = title + '_sofq_banks_corrected.nxs' save_banks(InputWorkspace=sq_banks_wksp, Filename=sq_filename, Title="SQ_banks", OutputDir=OutputDir, GroupingWorkspace=grp_wksp, Binning=binning) # Print log information print("<b>^2:", bcoh_avg_sqrd) print("<b^2>:", btot_sqrd_avg) print("Laue term:", laue_monotonic_diffuse_scat) print("sample total xsection:", mtd[sam_corrected].sample().getMaterial().totalScatterXSection()) print("vanadium total xsection:", mtd[van_corrected].sample().getMaterial().totalScatterXSection()) # Output Bragg Diffraction ConvertUnits(InputWorkspace=sam_corrected, OutputWorkspace=sam_corrected, Target="TOF", EMode="Elastic") ConvertToHistogram(InputWorkspace=sam_corrected, OutputWorkspace=sam_corrected) xmin, xmax = get_each_spectra_xmin_xmax(mtd[sam_corrected]) CropWorkspaceRagged(InputWorkspace=sam_corrected, OutputWorkspace=sam_corrected, Xmin=xmin, Xmax=xmax) xmin_rebin = min(xmin) xmax_rebin = max(xmax) tof_binning = "{xmin},-0.01,{xmax}".format(xmin=xmin_rebin, xmax=xmax_rebin) Rebin(InputWorkspace=sam_corrected, OutputWorkspace=sam_corrected, Params=tof_binning) SaveGSS(InputWorkspace=sam_corrected, Filename=os.path.join(os.path.abspath(OutputDir), title + ".gsa"), SplitFiles=False, Append=False, MultiplyByBinWidth=True, Format="SLOG", ExtendedHeader=True) return mtd[sam_corrected]
def PyExec(self): # Set up progress reporting n_prog_reports = 2 if self._can_ws_name is not None: n_prog_reports += 1 prog = Progress(self, 0.0, 1.0, n_prog_reports) sample_wave_ws = '__sam_wave' convert_unit_alg = self.createChildAlgorithm("ConvertUnits", enableLogging=False) convert_unit_alg.setProperty("InputWorkspace", self._sample_ws_name) convert_unit_alg.setProperty("OutputWorkspace", sample_wave_ws) convert_unit_alg.setProperty("Target", 'Wavelength') convert_unit_alg.setProperty("EMode", self._emode) convert_unit_alg.setProperty("EFixed", self._efixed) convert_unit_alg.execute() mtd.addOrReplace(sample_wave_ws, convert_unit_alg.getProperty("OutputWorkspace").value) prog.report('Calculating sample corrections') SetBeam(sample_wave_ws, Geometry={ 'Shape': 'Slit', 'Width': self._beam_width, 'Height': self._beam_height }) if self._sample_density_type == 'Mass Density': sample_mat_list = { 'ChemicalFormula': self._sample_chemical_formula, 'SampleMassDensity': self._sample_density } if self._sample_density_type == 'Number Density': sample_mat_list = { 'ChemicalFormula': self._sample_chemical_formula, 'SampleNumberDensity': self._sample_density } SetSample(sample_wave_ws, Geometry={ 'Shape': 'Cylinder', 'Height': self._sample_height, 'Radius': self._sample_radius, 'Center': [0., 0., 0.] }, Material=sample_mat_list) prog.report('Calculating sample corrections') MonteCarloAbsorption(InputWorkspace=sample_wave_ws, OutputWorkspace=self._ass_ws, EventsPerPoint=self._events, NumberOfWavelengthPoints=self._number_wavelengths, Interpolation='CSpline') group = self._ass_ws delete_alg = self.createChildAlgorithm("DeleteWorkspace", enableLogging=False) divide_alg = self.createChildAlgorithm("Divide", enableLogging=False) minus_alg = self.createChildAlgorithm("Minus", enableLogging=False) if self._can_ws_name is not None: can_wave_ws = '__can_wave' convert_unit_alg.setProperty("InputWorkspace", self._can_ws_name) convert_unit_alg.setProperty("OutputWorkspace", can_wave_ws) convert_unit_alg.setProperty("Target", 'Wavelength') convert_unit_alg.setProperty("EMode", self._emode) convert_unit_alg.setProperty("EFixed", self._efixed) convert_unit_alg.execute() mtd.addOrReplace( can_wave_ws, convert_unit_alg.getProperty("OutputWorkspace").value) if self._can_scale != 1.0: logger.information('Scaling can by: %s' % self._can_scale) scale_alg = self.createChildAlgorithm("Scale", enableLogging=False) scale_alg.setProperty("InputWorkspace", can_wave_ws) scale_alg.setProperty("OutputWorkspace", can_wave_ws) scale_alg.setProperty("Factor", self._can_scale) scale_alg.setProperty("Operation", 'Multiply') scale_alg.execute() can_thickness = self._can_radius - self._sample_radius logger.information('Container thickness: ' + str(can_thickness)) if self._use_can_corrections: # Doing can corrections prog.report('Calculating container corrections') divide_alg.setProperty("LHSWorkspace", sample_wave_ws) divide_alg.setProperty("RHSWorkspace", self._ass_ws) divide_alg.setProperty("OutputWorkspace", sample_wave_ws) divide_alg.execute() if self._sample_density_type == 'Mass Density': container_mat_list = { 'ChemicalFormula': self._can_chemical_formula, 'SampleMassDensity': self._can_density } if self._sample_density_type == 'Number Density': container_mat_list = { 'ChemicalFormula': self._can_chemical_formula, 'SampleNumberDensity': self._can_density } SetSample(can_wave_ws, Geometry={ 'Shape': 'HollowCylinder', 'Height': self._sample_height, 'InnerRadius': self._sample_radius, 'OuterRadius': self._can_radius, 'Center': [0., 0., 0.] }, Material=container_mat_list) MonteCarloAbsorption( InputWorkspace=can_wave_ws, OutputWorkspace=self._acc_ws, EventsPerPoint=self._events, NumberOfWavelengthPoints=self._number_wavelengths, Interpolation='CSpline') divide_alg.setProperty("LHSWorkspace", can_wave_ws) divide_alg.setProperty("RHSWorkspace", self._acc_ws) divide_alg.setProperty("OutputWorkspace", can_wave_ws) divide_alg.execute() minus_alg.setProperty("LHSWorkspace", sample_wave_ws) minus_alg.setProperty("RHSWorkspace", can_wave_ws) minus_alg.setProperty("OutputWorkspace", sample_wave_ws) minus_alg.execute() group += ',' + self._acc_ws else: # Doing simple can subtraction prog.report('Calculating container scaling') minus_alg.setProperty("LHSWorkspace", sample_wave_ws) minus_alg.setProperty("RHSWorkspace", can_wave_ws) minus_alg.setProperty("OutputWorkspace", sample_wave_ws) minus_alg.execute() divide_alg.setProperty("LHSWorkspace", sample_wave_ws) divide_alg.setProperty("RHSWorkspace", self._ass_ws) divide_alg.setProperty("OutputWorkspace", sample_wave_ws) divide_alg.execute() delete_alg.setProperty("Workspace", can_wave_ws) delete_alg.execute() else: divide_alg.setProperty("LHSWorkspace", sample_wave_ws) divide_alg.setProperty("RHSWorkspace", self._ass_ws) divide_alg.setProperty("OutputWorkspace", sample_wave_ws) divide_alg.execute() convert_unit_alg.setProperty("InputWorkspace", sample_wave_ws) convert_unit_alg.setProperty("OutputWorkspace", self._output_ws) convert_unit_alg.setProperty("Target", 'DeltaE') convert_unit_alg.setProperty("EMode", self._emode) convert_unit_alg.setProperty("EFixed", self._efixed) convert_unit_alg.execute() mtd.addOrReplace(self._output_ws, convert_unit_alg.getProperty("OutputWorkspace").value) delete_alg.setProperty("Workspace", sample_wave_ws) delete_alg.execute() # Record sample logs prog.report('Recording sample logs') sample_log_workspaces = [self._output_ws, self._ass_ws] sample_logs = [('sample_shape', 'cylinder'), ('sample_filename', self._sample_ws_name), ('sample_radius', self._sample_radius)] if self._can_ws_name is not None: sample_logs.append(('container_filename', self._can_ws_name)) sample_logs.append(('container_scale', self._can_scale)) if self._use_can_corrections: sample_log_workspaces.append(self._acc_ws) sample_logs.append(('container_thickness', can_thickness)) log_names = [item[0] for item in sample_logs] log_values = [item[1] for item in sample_logs] add_sample_log_alg = self.createChildAlgorithm("AddSampleLogMultiple", enableLogging=False) for ws_name in sample_log_workspaces: add_sample_log_alg.setProperty("Workspace", ws_name) add_sample_log_alg.setProperty("LogNames", log_names) add_sample_log_alg.setProperty("LogValues", log_values) add_sample_log_alg.execute() self.setProperty('OutputWorkspace', self._output_ws) # Output the Abs group workspace if it is wanted, delete if not if self._abs_ws == '': delete_alg.setProperty("Workspace", self._ass_ws) delete_alg.execute() if self._can_ws_name is not None and self._use_can_corrections: delete_alg.setProperty("Workspace", self._acc_ws) delete_alg.execute() else: GroupWorkspaces(InputWorkspaces=group, OutputWorkspace=self._abs_ws, EnableLogging=False) self.setProperty('CorrectionsWorkspace', self._abs_ws)
def PyExec(self): raw_ws = self.getProperty('InputWorkspace').value sample_geometry = self.getPropertyValue('SampleGeometry') sample_material = self.getPropertyValue('SampleMaterial') cal_file_name = self.getPropertyValue('CalFileName') SetSample(InputWorkspace=raw_ws, Geometry=sample_geometry, Material=sample_material) # find the closest monitor to the sample for incident spectrum raw_spec_info = raw_ws.spectrumInfo() incident_index = None for i in range(raw_spec_info.size()): if raw_spec_info.isMonitor(i): l2 = raw_spec_info.position(i)[2] if not incident_index: incident_index = i else: if raw_spec_info.position(incident_index)[2] < l2 < 0: incident_index = i monitor = ExtractSpectra(InputWorkspace=raw_ws, WorkspaceIndexList=[incident_index]) monitor = ConvertUnits(InputWorkspace=monitor, Target="Wavelength") x_data = monitor.dataX(0) min_x = np.min(x_data) max_x = np.max(x_data) width_x = (max_x - min_x) / x_data.size fit_spectra = FitIncidentSpectrum(InputWorkspace=monitor, BinningForCalc=[min_x, 1 * width_x, max_x], BinningForFit=[min_x, 10 * width_x, max_x], FitSpectrumWith="CubicSpline") self_scattering_correction = CalculatePlaczekSelfScattering(InputWorkspace=raw_ws, IncidentSpectra=fit_spectra, ScaleByPackingFraction=False, Version=1) # Convert to Q self_scattering_correction = ConvertUnits(InputWorkspace=self_scattering_correction, Target="MomentumTransfer", EMode='Elastic') cal_workspace = LoadCalFile(InputWorkspace=self_scattering_correction, CalFileName=cal_file_name, Workspacename='cal_workspace', MakeOffsetsWorkspace=False, MakeMaskWorkspace=False, MakeGroupingWorkspace=True) ssc_min_x, ssc_max_x = float('inf'), float('-inf') for index in range(self_scattering_correction.getNumberHistograms()): spec_info = self_scattering_correction.spectrumInfo() if not spec_info.isMasked(index) and not spec_info.isMonitor(index): ssc_x_data = np.ma.masked_invalid(self_scattering_correction.dataX(index)) if np.min(ssc_x_data) < ssc_min_x: ssc_min_x = np.min(ssc_x_data) if np.max(ssc_x_data) > ssc_max_x: ssc_max_x = np.max(ssc_x_data) ssc_width_x = (ssc_max_x - ssc_min_x) / ssc_x_data.size # TO DO: calculate rebin parameters per group # and run GroupDetectors on each separately self_scattering_correction = Rebin(InputWorkspace=self_scattering_correction, Params=[ssc_min_x, ssc_width_x, ssc_max_x], IgnoreBinErrors=True) self_scattering_correction = GroupDetectors(InputWorkspace=self_scattering_correction, CopyGroupingFromWorkspace='cal_workspace_group') n_pixel = np.zeros(self_scattering_correction.getNumberHistograms()) for i in range(cal_workspace.getNumberHistograms()): grouping = cal_workspace.dataY(i) if grouping[0] > 0: n_pixel[int(grouping[0] - 1)] += 1 correction_ws = CreateWorkspace(DataY=n_pixel, DataX=[0, 1], NSpec=self_scattering_correction.getNumberHistograms()) self_scattering_correction = Divide(LHSWorkspace=self_scattering_correction, RHSWorkspace=correction_ws) DeleteWorkspace('cal_workspace_group') DeleteWorkspace(correction_ws) DeleteWorkspace(fit_spectra) DeleteWorkspace(monitor) DeleteWorkspace(raw_ws) self.setProperty('OutputWorkspace', self_scattering_correction)
def PyExec(self): # setup progress reporting prog = Progress(self, 0.0, 1.0, 3) prog.report('Setting up sample environment') # set the beam shape SetBeam(self._input_ws_name, Geometry={ 'Shape': 'Slit', 'Width': self._beam_width, 'Height': self._beam_height }) # set the sample geometry sample_geometry = dict() sample_geometry['Height'] = self._height if self._shape == 'FlatPlate': sample_geometry['Shape'] = 'FlatPlate' sample_geometry['Width'] = self._width sample_geometry['Thick'] = self._thickness sample_geometry['Center'] = [0.0, 0.0, self._center] sample_geometry['Angle'] = self._angle if self._shape == 'Cylinder': sample_geometry['Shape'] = 'Cylinder' sample_geometry['Radius'] = self._radius sample_geometry['Center'] = [0.0, 0.0, 0.0] if self._shape == 'Annulus': sample_geometry['Shape'] = 'HollowCylinder' sample_geometry['InnerRadius'] = self._inner_radius sample_geometry['OuterRadius'] = self._outer_radius sample_geometry['Center'] = [0.0, 0.0, 0.0] sample_geometry['Axis'] = 1 # set sample if self._material_defined: # set sample without sample material SetSample(InputWorkspace=self._input_ws_name, Geometry=sample_geometry) else: # set the sample material sample_material = dict() sample_material['ChemicalFormula'] = self._chemical_formula if self._density_type == 'Mass Density': sample_material['SampleMassDensity'] = self._density if self._density_type == 'Number Density': sample_material['SampleNumberDensity'] = self._density SetSample(InputWorkspace=self._input_ws_name, Geometry=sample_geometry, Material=sample_material) prog.report('Calculating sample corrections') MonteCarloAbsorption(InputWorkspace=self._input_ws_name, OutputWorkspace=self._output_ws, EventsPerPoint=self._events, NumberOfWavelengthPoints=self._number_wavelengths, Interpolation=self._interpolation) prog.report('Recording Sample Logs') log_names = ['beam_height', 'beam_width'] log_values = [self._beam_height, self._beam_width] # add sample geometry to sample logs for key, value in sample_geometry.items(): log_names.append('sample_' + key.lower()) log_values.append(value) add_sample_log_alg = self.createChildAlgorithm('AddSampleLogMultiple', enableLogging=False) add_sample_log_alg.setProperty('Workspace', self._output_ws) add_sample_log_alg.setProperty('LogNames', log_names) add_sample_log_alg.setProperty('LogValues', log_values) add_sample_log_alg.execute() self.setProperty('OutputWorkspace', self._output_ws)
def test_generate_geometry_slab_with_container(self): workspace = CreateSampleWorkspace() thickness_float = 2.2 width_float = 1.0 height_float = 2.0 center_float = [1.0, 2.0, 3.0] angle_float = 3.0 sample_details_float = sample_details.SampleDetails( thickness=thickness_float, shape="slab", height=height_float, width=width_float, center=center_float, angle=angle_float) sample_details_float.set_material(chemical_formula='Si') sample_details_float.set_container(front_thick=2.0, back_thick=2.2, chemical_formula='V') thickness_int = 1 width_int = 2 height_int = 3 center_int = [1, 2, 3] angle_int = 4 sample_details_int = sample_details.SampleDetails( thickness=thickness_int, shape="slab", height=height_int, width=width_int, center=center_int, angle=angle_int) sample_details_int.set_material(chemical_formula='Si') sample_details_int.set_container(front_thick=2, back_thick=1, chemical_formula='V') thickness_string = "5" width_string = "1" height_string = "2" center_string = ["1", "2", "3"] angle_string = "3" sample_details_string = sample_details.SampleDetails( thickness=thickness_string, shape="slab", height=height_string, width=width_string, center=center_string, angle=angle_string) sample_details_string.set_material(chemical_formula='Si') sample_details_string.set_container(front_thick="2", back_thick="2.2", chemical_formula='V') thickness_mix = "5" width_mix = 3.5 height_mix = "2" center_mix = ["1", 2, 3.45] angle_mix = 3 sample_details_mix = sample_details.SampleDetails( thickness=thickness_mix, shape="slab", height=height_mix, width=width_mix, center=center_mix, angle=angle_mix) sample_details_mix.set_material(chemical_formula='Si') sample_details_mix.set_container(front_thick="2.0", back_thick=2, chemical_formula='V') sample_details_objects = [ sample_details_float, sample_details_int, sample_details_string, sample_details_mix ] for sample_details_object in sample_details_objects: SetSample( workspace, Geometry=sample_details_object.generate_sample_geometry(), Material=sample_details_object.generate_sample_material(), ContainerGeometry=sample_details_object. generate_container_geometry(), ContainerMaterial=sample_details_object. generate_container_material())