def _calculate_area_density_from_density(self): """Calculates area density (atom/cm^2) using number density and thickness.""" if self._density_type == 'Mass Density': builder = MaterialBuilder().setFormula(self._chemical_formula) mat = builder.setMassDensity(self._density).build() self._density = mat.numberDensity self._area_density = self._density * self._thickness
def _set_material(self, ws_name, chemical_formula, density_type, density): """ Sets the sample material for a given workspace @param ws_name :: name of the workspace to set sample material for @param chemical_formula :: Chemical formula of sample @param density_type :: 'Mass Density' or 'Number Density' @param density :: Density of sample @return pointer to the workspace with sample material set AND number density of the sample material """ set_material_alg = self.createChildAlgorithm('SetSampleMaterial') if density_type == 'Mass Density': set_material_alg.setProperty('SampleMassDensity', density) builder = MaterialBuilder() mat = builder.setFormula(chemical_formula).setMassDensity( density).build() number_density = mat.numberDensity else: number_density = density set_material_alg.setProperty('InputWorkspace', ws_name) set_material_alg.setProperty('ChemicalFormula', chemical_formula) set_material_alg.setProperty('SampleNumberDensity', number_density) set_material_alg.execute() return number_density
def _set_material(self, ws_name, chemical_formula, density_type, density): """ Sets the sample material for a given workspace @param ws_name :: name of the workspace to set sample material for @param chemical_formula :: Chemical formula of sample @param density_type :: 'Mass Density' or 'Number Density' @param density :: Density of sample @return pointer to the workspace with sample material set AND number density of the sample material """ set_material_alg = self.createChildAlgorithm('SetSampleMaterial') if density_type == 'Mass Density': set_material_alg.setProperty('SampleMassDensity', density) builder = MaterialBuilder() mat = builder.setFormula(chemical_formula).setMassDensity(density).build() number_density = mat.numberDensity else: number_density = density set_material_alg.setProperty('InputWorkspace', ws_name) set_material_alg.setProperty('ChemicalFormula', chemical_formula) set_material_alg.setProperty('SampleNumberDensity', number_density) set_material_alg.execute() ws = set_material_alg.getProperty('InputWorkspace').value return ws, number_density
def _sample(self): set_material_alg = self.createChildAlgorithm('SetSampleMaterial') logger.information('Sample chemical formula : %s ' % (self._sample_chemical_formula)) if self._sample_density_type == 'Mass Density': logger.information('Sample Mass density : %f' % (self._sample_density)) set_material_alg.setProperty('SampleMassDensity', self._sample_density) builder = MaterialBuilder() mat = builder.setFormula(self._sample_chemical_formula).setMassDensity(self._sample_density).build() self._sample_number_density = mat.numberDensity logger.information('Sample Number density : %f' % (self._sample_number_density)) else: self._sample_number_density = self._sample_density logger.information('Sample Number density : %f' % (self._sample_number_density)) set_material_alg.setProperty('SampleNumberDensity', self._sample_number_density) set_material_alg.setProperty('InputWorkspace', self._sample_ws_name) set_material_alg.setProperty('ChemicalFormula', self._sample_chemical_formula) set_material_alg.execute() sam_material = mtd[self._sample_ws_name].sample().getMaterial() # Sample cross section self._sigc = sam_material.cohScatterXSection() self._sigi = sam_material.incohScatterXSection() self._sigt = sam_material.totalScatterXSection() self._siga_in = sam_material.absorbXSection() self._siga = self._siga_in self._sigss = self._sofq*self._sigc + self._sigi #q_dependent total scatt X-sect self._sigss = np.log(self._sigss) #interpolation later on self._sofq = np.log(self._sofq/self._sigt) #S(Q) normalised
def _create_profile_strs_and_mass_list(profile_flags): """ Create a string suitable for the algorithms out of the mass profile flags and a list of mass values :param profile_flags: A list of dict objects for the mass profile flags :return: A tuple of list of masses, a string to pass to the algorithm and a dictionary containing a map from mass index to a symbol - where chemical formula was used to define a mass. """ material_builder = MaterialBuilder() mass_values, profiles = [], [] all_mass_values, all_profiles = [], [] for idx, mass_prop in enumerate(profile_flags): function_name = ("function=%s," % mass_prop.pop('function')) function_props = [ "{0}={1}".format(key, value) for key, value in mass_prop.items() ] function_props = ("%s,%s" % (function_name, (','.join(function_props)))) mass_value = mass_prop.pop('value', None) if mass_value is None: symbol = mass_prop.pop('symbol', None) if symbol is None: raise RuntimeError( 'Invalid mass specified - ' + str(mass_prop) + " - either 'value' or 'symbol' must be given.") try: if symbol == 'H': mass = material_builder.setFormula( symbol).build().relativeMolecularMass() all_mass_values.append(mass) all_profiles.append(function_props) continue mass_value = material_builder.setFormula( symbol).build().relativeMolecularMass() except BaseException as exc: raise RuntimeError('Error when parsing mass - ' + str(mass_prop) + ": " + "\n" + str(exc)) all_mass_values.append(mass_value) mass_values.append(mass_value) all_profiles.append(function_props) profiles.append(function_props) profiles = ";".join(profiles) all_profiles = ";".join(all_profiles) return mass_values, profiles, all_mass_values, all_profiles
def test_build_material(self): builder = MaterialBuilder() material = builder.setName('Bizarre oxide').setFormula('Al2 O3').setNumberDensity(0.23).build() self.assertEqual(material.name(), 'Bizarre oxide') formula = material.chemicalFormula() self.assertEqual(len(formula), 2) atoms = formula[0] multiplicities = formula[1] self.assertEqual(len(atoms), 2) self.assertEqual(atoms[0].symbol, 'Al') self.assertEqual(atoms[1].symbol, 'O') self.assertEqual(len(multiplicities), 2) self.assertEqual(multiplicities[0], 2) self.assertEqual(multiplicities[1], 3) self.assertEqual(material.numberDensity, 0.23)
def test_build_material(self): builder = MaterialBuilder() material = builder.setName('Bizarre oxide').setFormula( 'Al2 O3').setNumberDensity(0.23).build() self.assertEqual(material.name(), 'Bizarre oxide') formula = material.chemicalFormula() self.assertEqual(len(formula), 2) atoms = formula[0] multiplicities = formula[1] self.assertEqual(len(atoms), 2) self.assertEqual(atoms[0].symbol, 'Al') self.assertEqual(atoms[1].symbol, 'O') self.assertEqual(len(multiplicities), 2) self.assertEqual(multiplicities[0], 2) self.assertEqual(multiplicities[1], 3) self.assertEqual(material.numberDensity, 0.23)
def _calculate_packing_fraction(self): try: self._content.packingfraction_edit.setText('{:.5f}'.format(MaterialBuilder().setFormula( self._content.sampleformula_edit.text()).setNumberDensity( float(self._content.numberdensity_edit.text())).setMassDensity( float(self._content.massdensity_edit.text())).build().packingFraction)) except ValueError: # boost.python.ArgumentError are not catchable self._content.packingfraction_edit.setText(str(1))
def _create_profile_strs_and_mass_list(profile_flags): """ Create a string suitable for the algorithms out of the mass profile flags and a list of mass values :param profile_flags: A list of dict objects for the mass profile flags :return: A tuple of list of masses, a string to pass to the algorithm and a dictionary containing a map from mass index to a symbol - where chemical formula was used to define a mass. """ material_builder = MaterialBuilder() mass_values, profiles = [], [] all_mass_values, all_profiles = [], [] for idx, mass_prop in enumerate(profile_flags): function_name = ("function=%s," % mass_prop.pop('function')) function_props = ["{0}={1}".format(key, value) for key, value in mass_prop.items()] function_props = ("%s,%s" % (function_name, (','.join(function_props)))) mass_value = mass_prop.pop('value', None) if mass_value is None: symbol = mass_prop.pop('symbol', None) if symbol is None: raise RuntimeError('Invalid mass specified - ' + str(mass_prop) + " - either 'value' or 'symbol' must be given.") try: if symbol == 'H': mass = material_builder.setFormula(symbol).build().relativeMolecularMass() all_mass_values.append(mass) all_profiles.append(function_props) continue mass_value = material_builder.setFormula(symbol).build().relativeMolecularMass() except BaseException as exc: raise RuntimeError('Error when parsing mass - ' + str(mass_prop) + ": " + "\n" + str(exc)) all_mass_values.append(mass_value) mass_values.append(mass_value) all_profiles.append(function_props) profiles.append(function_props) profiles = ";".join(profiles) all_profiles = ";".join(all_profiles) return mass_values, profiles, all_mass_values, all_profiles
def test_number_density_units(self): builder = MaterialBuilder() builder.setName('Bizarre oxide').setFormula('Al2 O3').setNumberDensity( 0.23) builder.setNumberDensityUnit(NumberDensityUnit.FormulaUnits) material = builder.build() self.assertEqual(material.numberDensity, 0.23 * (2. + 3.))
def test_number_density_units(self): builder = MaterialBuilder() builder.setName(NAME).setFormula(FORMULA).setNumberDensity(NUMBER_DENSITY) builder.setNumberDensityUnit(NumberDensityUnit.FormulaUnits) material = builder.build() self.assertEqual(material.numberDensity, NUMBER_DENSITY * (2. + 3.)) self.assertEqual(material.numberDensityEffective, NUMBER_DENSITY * (2. + 3.)) self.assertEqual(material.packingFraction, 1.)
def _validate_formula(self): try: if self._content.sampleformula_edit.text().strip() != '': MaterialBuilder().setFormula(self._content.sampleformula_edit.text().strip()) self._content.sampleformula_edit.setToolTip("") self._content.sampleformula_edit.setStyleSheet("QLineEdit{}") except ValueError as e: self._content.sampleformula_edit.setToolTip( str(e).replace("MaterialBuilder::setFormula() - ", "")) self._content.sampleformula_edit.setStyleSheet("QLineEdit{background:salmon;}")
def test_build_material(self): builder = MaterialBuilder() material = builder.setName(NAME).setFormula(FORMULA).setNumberDensity(NUMBER_DENSITY).build() self.assertEqual(material.name(), NAME) self.assertEqual(material.numberDensity, NUMBER_DENSITY) self.assertEqual(material.numberDensityEffective, NUMBER_DENSITY) self.assertEqual(material.packingFraction, 1.) formula = material.chemicalFormula() self.assertEqual(len(formula), 2) atoms = formula[0] multiplicities = formula[1] self.assertEqual(len(atoms), 2) self.assertEqual(atoms[0].symbol, 'Al') self.assertEqual(atoms[1].symbol, 'O') self.assertEqual(len(multiplicities), 2) self.assertEqual(multiplicities[0], 2) self.assertEqual(multiplicities[1], 3) self.assertEqual(material.numberDensity, NUMBER_DENSITY)
def fit_tof(runs, flags, iterations=1, convergence_threshold=None): # Retrieve vesuvio input data vesuvio_loader = VesuvioLoadHelper( flags['diff_mode'], flags['fit_mode'], flags['ip_file'], flags.get('bin_parameters', None), _extract_bool_from_flags('load_log_files', flags)) vesuvio_input = VesuvioTOFFitInput(runs, flags.get('container_runs', None), flags.get('spectra', None), vesuvio_loader) if flags.get('ms_enabled', True): hydrogen_constraints = flags['ms_flags'].pop("HydrogenConstraints", None) ms_helper = VesuvioMSHelper(**flags['ms_flags']) if hydrogen_constraints is not None: ms_helper.add_hydrogen_constraints(hydrogen_constraints) else: ms_helper = VesuvioMSHelper() intensity_string = _create_intensity_constraint_str( flags['intensity_constraints']) fit_helper = VesuvioTOFFitHelper( _create_background_str(flags.get('background', None)), intensity_string, _create_user_defined_ties_str(flags['masses']), flags.get('max_fit_iterations', 5000), flags['fit_minimizer']) corrections_helper = VesuvioCorrectionsHelper( _extract_bool_from_flags('gamma_correct', flags, False), _extract_bool_from_flags('ms_enabled', flags), flags.get('fixed_gamma_scaling', 0.0), flags.get('fixed_container_scaling', 0.0), intensity_string) create_mass_profile = _mass_profile_generator(MaterialBuilder()) profiles = [create_mass_profile(profile) for profile in flags['masses']] mass_profile_collection = MassProfileCollection2D.from_collection( MassProfileCollection(profiles), vesuvio_input.spectra_number) fit_namer = VesuvioFitNamer.from_vesuvio_input(vesuvio_input, flags['fit_mode']) vesuvio_fit_routine = VesuvioTOFFitRoutine(ms_helper, fit_helper, corrections_helper, mass_profile_collection, fit_namer) vesuvio_output, result, exit_iteration = vesuvio_fit_routine( vesuvio_input, iterations, convergence_threshold, _extract_bool_from_flags('output_verbose_corrections', flags, False), _extract_bool_from_flags('calculate_caad', flags, False)) result = result if len(result) > 1 else result[0] return result, vesuvio_output.fit_parameters_workspace, vesuvio_output.chi2_values, exit_iteration
def PyExec(self): from IndirectCommon import getEfixed self._setup() # 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) efixed = getEfixed(self._sample_ws_name) sample_wave_ws = '__sam_wave' ConvertUnits(InputWorkspace=self._sample_ws_name, OutputWorkspace=sample_wave_ws, Target='Wavelength', EMode='Indirect', EFixed=efixed, EnableLogging=False) sample_thickness = self._sample_outer_radius - self._sample_inner_radius logger.information('Sample thickness: ' + str(sample_thickness)) prog.report('Calculating sample corrections') if self._sample_density_type == 'Mass Density': builder = MaterialBuilder() mat = builder.setFormula( self._sample_chemical_formula).setMassDensity( self._sample_density).build() self._sample_density = mat.numberDensity SetSampleMaterial(sample_wave_ws, ChemicalFormula=self._sample_chemical_formula, SampleNumberDensity=self._sample_density) AnnularRingAbsorption( InputWorkspace=sample_wave_ws, OutputWorkspace=self._ass_ws, SampleHeight=3.0, SampleThickness=sample_thickness, CanInnerRadius=self._can_inner_radius, CanOuterRadius=self._can_outer_radius, SampleChemicalFormula=self._sample_chemical_formula, SampleNumberDensity=self._sample_density, NumberOfWavelengthPoints=10, EventsPerPoint=self._events) group = self._ass_ws if self._can_ws_name is not None: can1_wave_ws = '__can1_wave' can2_wave_ws = '__can2_wave' ConvertUnits(InputWorkspace=self._can_ws_name, OutputWorkspace=can1_wave_ws, Target='Wavelength', EMode='Indirect', EFixed=efixed, EnableLogging=False) if self._can_scale != 1.0: logger.information('Scaling container by: ' + str(self._can_scale)) Scale(InputWorkspace=can1_wave_ws, OutputWorkspace=can1_wave_ws, Factor=self._can_scale, Operation='Multiply') CloneWorkspace(InputWorkspace=can1_wave_ws, OutputWorkspace=can2_wave_ws, EnableLogging=False) can_thickness_1 = self._sample_inner_radius - self._can_inner_radius can_thickness_2 = self._can_outer_radius - self._sample_outer_radius logger.information('Container thickness: %f & %f' % (can_thickness_1, can_thickness_2)) if self._use_can_corrections: prog.report('Calculating container corrections') Divide(LHSWorkspace=sample_wave_ws, RHSWorkspace=self._ass_ws, OutputWorkspace=sample_wave_ws) if self._can_density_type == 'Mass Density': builder = MaterialBuilder() mat = builder.setFormula( self._can_chemical_formula).setMassDensity( self._can_density).build() self._can_density = mat.numberDensity SetSampleMaterial(can1_wave_ws, ChemicalFormula=self._can_chemical_formula, SampleNumberDensity=self._can_density) AnnularRingAbsorption( InputWorkspace=can1_wave_ws, OutputWorkspace='__Acc1', SampleHeight=3.0, SampleThickness=can_thickness_1, CanInnerRadius=self._can_inner_radius, CanOuterRadius=self._sample_outer_radius, SampleChemicalFormula=self._can_chemical_formula, SampleNumberDensity=self._can_density, NumberOfWavelengthPoints=10, EventsPerPoint=self._events) SetSampleMaterial(can2_wave_ws, ChemicalFormula=self._can_chemical_formula, SampleNumberDensity=self._can_density) AnnularRingAbsorption( InputWorkspace=can2_wave_ws, OutputWorkspace='__Acc2', SampleHeight=3.0, SampleThickness=can_thickness_2, CanInnerRadius=self._sample_inner_radius, CanOuterRadius=self._can_outer_radius, SampleChemicalFormula=self._can_chemical_formula, SampleNumberDensity=self._can_density, NumberOfWavelengthPoints=10, EventsPerPoint=self._events) Multiply(LHSWorkspace='__Acc1', RHSWorkspace='__Acc2', OutputWorkspace=self._acc_ws, EnableLogging=False) DeleteWorkspace('__Acc1', EnableLogging=False) DeleteWorkspace('__Acc2', EnableLogging=False) Divide(LHSWorkspace=can1_wave_ws, RHSWorkspace=self._acc_ws, OutputWorkspace=can1_wave_ws) Minus(LHSWorkspace=sample_wave_ws, RHSWorkspace=can1_wave_ws, OutputWorkspace=sample_wave_ws) group += ',' + self._acc_ws else: prog.report('Calculating can scaling') Minus(LHSWorkspace=sample_wave_ws, RHSWorkspace=can1_wave_ws, OutputWorkspace=sample_wave_ws) Divide(LHSWorkspace=sample_wave_ws, RHSWorkspace=self._ass_ws, OutputWorkspace=sample_wave_ws) DeleteWorkspace(can1_wave_ws, EnableLogging=False) DeleteWorkspace(can2_wave_ws, EnableLogging=False) else: Divide(LHSWorkspace=sample_wave_ws, RHSWorkspace=self._ass_ws, OutputWorkspace=sample_wave_ws) ConvertUnits(InputWorkspace=sample_wave_ws, OutputWorkspace=self._output_ws, Target='DeltaE', EMode='Indirect', EFixed=efixed, EnableLogging=False) DeleteWorkspace(sample_wave_ws, EnableLogging=False) prog.report('Recording sample logs') sample_log_workspaces = [self._output_ws, self._ass_ws] sample_logs = [('sample_shape', 'annulus'), ('sample_filename', self._sample_ws_name), ('sample_inner', self._sample_inner_radius), ('sample_outer', self._sample_outer_radius), ('can_inner', self._can_inner_radius), ('can_outer', self._can_outer_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_1', can_thickness_1)) sample_logs.append(('container_thickness_2', can_thickness_2)) log_names = [item[0] for item in sample_logs] log_values = [item[1] for item in sample_logs] for ws_name in sample_log_workspaces: AddSampleLogMultiple(Workspace=ws_name, LogNames=log_names, LogValues=log_values, EnableLogging=False) self.setProperty('OutputWorkspace', self._output_ws) # Output the Ass workspace if it is wanted, delete if not if self._abs_ws == '': DeleteWorkspace(self._ass_ws, EnableLogging=False) if self._can_ws_name is not None and self._use_can_corrections: DeleteWorkspace(self._acc_ws, EnableLogging=False) else: GroupWorkspaces(InputWorkspaces=group, OutputWorkspace=self._abs_ws, EnableLogging=False) self.setProperty('CorrectionsWorkspace', self._abs_ws)
def PyExec(self): from IndirectCommon import getEfixed self._setup() # 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) efixed = getEfixed(self._sample_ws) sample_wave_ws = "__sam_wave" ConvertUnits( InputWorkspace=self._sample_ws, OutputWorkspace=sample_wave_ws, Target="Wavelength", EMode="Indirect", EFixed=efixed, EnableLogging=False, ) if self._sample_density_type == "Mass Density": builder = MaterialBuilder() mat = builder.setFormula(self._sample_chemical_formula).setMassDensity(self._sample_density).build() self._sample_density = mat.numberDensity SetSampleMaterial( sample_wave_ws, ChemicalFormula=self._sample_chemical_formula, SampleNumberDensity=self._sample_density ) prog.report("Calculating sample corrections") FlatPlateAbsorption( InputWorkspace=sample_wave_ws, OutputWorkspace=self._ass_ws, SampleHeight=self._sample_height, SampleWidth=self._sample_width, SampleThickness=self._sample_thickness, ElementSize=self._element_size, EMode="Indirect", EFixed=efixed, NumberOfWavelengthPoints=10, ) group = self._ass_ws if self._can_ws_name is not None: can_wave_ws = "__can_wave" ConvertUnits( InputWorkspace=self._can_ws_name, OutputWorkspace=can_wave_ws, Target="Wavelength", EMode="Indirect", EFixed=efixed, EnableLogging=False, ) if self._can_scale != 1.0: logger.information("Scaling container by: " + str(self._can_scale)) Scale( InputWorkspace=can_wave_ws, OutputWorkspace=can_wave_ws, Factor=self._can_scale, Operation="Multiply", ) if self._use_can_corrections: prog.report("Calculating container corrections") Divide(LHSWorkspace=sample_wave_ws, RHSWorkspace=self._ass_ws, OutputWorkspace=sample_wave_ws) if self._sample_density_type == "Mass Density": builder = MaterialBuilder() mat = builder.setFormula(self._can_chemical_formula).setMassDensity(self._can_density).build() self._can_density = mat.numberDensity SetSampleMaterial( can_wave_ws, ChemicalFormula=self._can_chemical_formula, SampleNumberDensity=self._can_density ) FlatPlateAbsorption( InputWorkspace=can_wave_ws, OutputWorkspace=self._acc_ws, SampleHeight=self._sample_height, SampleWidth=self._sample_width, SampleThickness=self._can_front_thickness + self._can_back_thickness, ElementSize=self._element_size, EMode="Indirect", EFixed=efixed, NumberOfWavelengthPoints=10, ) Divide(LHSWorkspace=can_wave_ws, RHSWorkspace=self._acc_ws, OutputWorkspace=can_wave_ws) Minus(LHSWorkspace=sample_wave_ws, RHSWorkspace=can_wave_ws, OutputWorkspace=sample_wave_ws) group += "," + self._acc_ws else: prog.report("Calculating container scaling") Minus(LHSWorkspace=sample_wave_ws, RHSWorkspace=can_wave_ws, OutputWorkspace=sample_wave_ws) Divide(LHSWorkspace=sample_wave_ws, RHSWorkspace=self._ass_ws, OutputWorkspace=sample_wave_ws) DeleteWorkspace(can_wave_ws, EnableLogging=False) else: Divide(LHSWorkspace=sample_wave_ws, RHSWorkspace=self._ass_ws, OutputWorkspace=sample_wave_ws) ConvertUnits( InputWorkspace=sample_wave_ws, OutputWorkspace=self._output_ws, Target="DeltaE", EMode="Indirect", EFixed=efixed, EnableLogging=False, ) DeleteWorkspace(sample_wave_ws, EnableLogging=False) prog.report("Recording sample logs") sample_log_workspaces = [self._output_ws, self._ass_ws] sample_logs = [ ("sample_shape", "flatplate"), ("sample_filename", self._sample_ws), ("sample_height", self._sample_height), ("sample_width", self._sample_width), ("sample_thickness", self._sample_thickness), ("element_size", self._element_size), ] 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_front_thickness", self._can_front_thickness)) sample_logs.append(("container_back_thickness", self._can_back_thickness)) log_names = [item[0] for item in sample_logs] log_values = [item[1] for item in sample_logs] for ws_name in sample_log_workspaces: AddSampleLogMultiple(Workspace=ws_name, LogNames=log_names, LogValues=log_values, EnableLogging=False) self.setProperty("OutputWorkspace", self._output_ws) # Output the Ass workspace if it is wanted, delete if not if self._abs_ws == "": DeleteWorkspace(self._ass_ws, EnableLogging=False) if self._can_ws_name is not None and self._use_can_corrections: DeleteWorkspace(self._acc_ws, EnableLogging=False) else: GroupWorkspaces(InputWorkspaces=group, OutputWorkspace=self._abs_ws, EnableLogging=False) self.setProperty("CorrectionsWorkspace", self._abs_ws)
def test_number_density_units(self): builder = MaterialBuilder() builder.setName('Bizarre oxide').setFormula('Al2 O3').setNumberDensity(0.23) builder.setNumberDensityUnit(NumberDensityUnit.FormulaUnits) material = builder.build() self.assertEqual(material.numberDensity, 0.23 * (2. + 3.))
def PyExec(self): from IndirectCommon import getEfixed self._setup() # 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) efixed = getEfixed(self._sample_ws_name) sample_wave_ws = '__sam_wave' ConvertUnits(InputWorkspace=self._sample_ws_name, OutputWorkspace=sample_wave_ws, Target='Wavelength', EMode='Indirect', EFixed=efixed, EnableLogging=False) sample_thickness = self._sample_outer_radius - self._sample_inner_radius logger.information('Sample thickness: ' + str(sample_thickness)) prog.report('Calculating sample corrections') if self._sample_density_type == 'Mass Density': builder = MaterialBuilder() mat = builder.setFormula(self._sample_chemical_formula).setMassDensity(self._sample_density).build() self._sample_density = mat.numberDensity SetSampleMaterial(sample_wave_ws, ChemicalFormula=self._sample_chemical_formula, SampleNumberDensity=self._sample_density) AnnularRingAbsorption(InputWorkspace=sample_wave_ws, OutputWorkspace=self._ass_ws, SampleHeight=3.0, SampleThickness=sample_thickness, CanInnerRadius=self._can_inner_radius, CanOuterRadius=self._can_outer_radius, SampleChemicalFormula=self._sample_chemical_formula, SampleNumberDensity=self._sample_density, NumberOfWavelengthPoints=10, EventsPerPoint=self._events) group = self._ass_ws if self._can_ws_name is not None: can1_wave_ws = '__can1_wave' can2_wave_ws = '__can2_wave' ConvertUnits(InputWorkspace=self._can_ws_name, OutputWorkspace=can1_wave_ws, Target='Wavelength', EMode='Indirect', EFixed=efixed, EnableLogging=False) if self._can_scale != 1.0: logger.information('Scaling container by: ' + str(self._can_scale)) Scale(InputWorkspace=can1_wave_ws, OutputWorkspace=can1_wave_ws, Factor=self._can_scale, Operation='Multiply') CloneWorkspace(InputWorkspace=can1_wave_ws, OutputWorkspace=can2_wave_ws, EnableLogging=False) can_thickness_1 = self._sample_inner_radius - self._can_inner_radius can_thickness_2 = self._can_outer_radius - self._sample_outer_radius logger.information('Container thickness: %f & %f' % (can_thickness_1, can_thickness_2)) if self._use_can_corrections: prog.report('Calculating container corrections') Divide(LHSWorkspace=sample_wave_ws, RHSWorkspace=self._ass_ws, OutputWorkspace=sample_wave_ws) if self._can_density_type == 'Mass Density': builder = MaterialBuilder() mat = builder.setFormula(self._can_chemical_formula).setMassDensity(self._can_density).build() self._can_density = mat.numberDensity SetSampleMaterial(can1_wave_ws, ChemicalFormula=self._can_chemical_formula, SampleNumberDensity=self._can_density) AnnularRingAbsorption(InputWorkspace=can1_wave_ws, OutputWorkspace='__Acc1', SampleHeight=3.0, SampleThickness=can_thickness_1, CanInnerRadius=self._can_inner_radius, CanOuterRadius=self._sample_outer_radius, SampleChemicalFormula=self._can_chemical_formula, SampleNumberDensity=self._can_density, NumberOfWavelengthPoints=10, EventsPerPoint=self._events) SetSampleMaterial(can2_wave_ws, ChemicalFormula=self._can_chemical_formula, SampleNumberDensity=self._can_density) AnnularRingAbsorption(InputWorkspace=can2_wave_ws, OutputWorkspace='__Acc2', SampleHeight=3.0, SampleThickness=can_thickness_2, CanInnerRadius=self._sample_inner_radius, CanOuterRadius=self._can_outer_radius, SampleChemicalFormula=self._can_chemical_formula, SampleNumberDensity=self._can_density, NumberOfWavelengthPoints=10, EventsPerPoint=self._events) Multiply(LHSWorkspace='__Acc1', RHSWorkspace='__Acc2', OutputWorkspace=self._acc_ws, EnableLogging=False) DeleteWorkspace('__Acc1', EnableLogging=False) DeleteWorkspace('__Acc2', EnableLogging=False) Divide(LHSWorkspace=can1_wave_ws, RHSWorkspace=self._acc_ws, OutputWorkspace=can1_wave_ws) Minus(LHSWorkspace=sample_wave_ws, RHSWorkspace=can1_wave_ws, OutputWorkspace=sample_wave_ws) group += ',' + self._acc_ws else: prog.report('Calculating can scaling') Minus(LHSWorkspace=sample_wave_ws, RHSWorkspace=can1_wave_ws, OutputWorkspace=sample_wave_ws) Divide(LHSWorkspace=sample_wave_ws, RHSWorkspace=self._ass_ws, OutputWorkspace=sample_wave_ws) DeleteWorkspace(can1_wave_ws, EnableLogging=False) DeleteWorkspace(can2_wave_ws, EnableLogging=False) else: Divide(LHSWorkspace=sample_wave_ws, RHSWorkspace=self._ass_ws, OutputWorkspace=sample_wave_ws) ConvertUnits(InputWorkspace=sample_wave_ws, OutputWorkspace=self._output_ws, Target='DeltaE', EMode='Indirect', EFixed=efixed, EnableLogging=False) DeleteWorkspace(sample_wave_ws, EnableLogging=False) prog.report('Recording sample logs') sample_log_workspaces = [self._output_ws, self._ass_ws] sample_logs = [('sample_shape', 'annulus'), ('sample_filename', self._sample_ws_name), ('sample_inner', self._sample_inner_radius), ('sample_outer', self._sample_outer_radius), ('can_inner', self._can_inner_radius), ('can_outer', self._can_outer_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_1', can_thickness_1)) sample_logs.append(('container_thickness_2', can_thickness_2)) log_names = [item[0] for item in sample_logs] log_values = [item[1] for item in sample_logs] for ws_name in sample_log_workspaces: AddSampleLogMultiple(Workspace=ws_name, LogNames=log_names, LogValues=log_values, EnableLogging=False) self.setProperty('OutputWorkspace', self._output_ws) # Output the Ass workspace if it is wanted, delete if not if self._abs_ws == '': DeleteWorkspace(self._ass_ws, EnableLogging=False) if self._can_ws_name is not None and self._use_can_corrections: DeleteWorkspace(self._acc_ws, EnableLogging=False) else: GroupWorkspaces(InputWorkspaces=group, OutputWorkspace=self._abs_ws, EnableLogging=False) self.setProperty('CorrectionsWorkspace', self._abs_ws)
def test_packing_fraction(self): builder = MaterialBuilder().setName(NAME).setFormula(FORMULA) # setting nothing should be an error try: material = builder.build() raise AssertionError('Should throw an exception') except RuntimeError as e: assert 'number density' in str(e) builder = MaterialBuilder().setName(NAME).setFormula(FORMULA).setNumberDensity(NUMBER_DENSITY) # only with number density material = builder.build() self.assertEqual(material.name(), NAME) self.assertEqual(material.numberDensity, material.numberDensityEffective) self.assertEqual(material.packingFraction, 1.0) self.assertEqual(material.numberDensity, NUMBER_DENSITY) # with number density and packing fraction material = builder.setPackingFraction(0.5).build() self.assertEqual(material.name(), NAME) self.assertEqual(material.numberDensity, NUMBER_DENSITY) self.assertEqual(material.numberDensityEffective, NUMBER_DENSITY * 0.5) self.assertEqual(material.packingFraction, 0.5) # start a brand new material builder builder = MaterialBuilder().setName(NAME).setFormula(FORMULA).setMassDensity(MASS_DENSITY) # only with mass density material = builder.build() self.assertEqual(material.name(), NAME) self.assertEqual(material.numberDensity, material.numberDensityEffective) self.assertEqual(material.packingFraction, 1.0) self.assertAlmostEqual(material.numberDensityEffective, NUMBER_DENSITY * PACKING_OBS, delta=1e-4) # with mass density and number density material = builder.setNumberDensity(NUMBER_DENSITY).build() self.assertEqual(material.name(), NAME) self.assertEqual(material.numberDensity, NUMBER_DENSITY) self.assertAlmostEqual(material.numberDensityEffective, NUMBER_DENSITY * PACKING_OBS, delta=1e-4) self.assertAlmostEqual(material.packingFraction, PACKING_OBS, delta=1e-4) # setting all 3 should be an error try: material = builder.setPackingFraction(0.5).setNumberDensity(NUMBER_DENSITY).setMassDensity(MASS_DENSITY).build() raise AssertionError('Should throw an exception') except RuntimeError as e: assert 'number density' in str(e)
def PyExec(self): from IndirectCommon import getEfixed self._setup() # 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) efixed = getEfixed(self._sample_ws) sample_wave_ws = '__sam_wave' ConvertUnits(InputWorkspace=self._sample_ws, OutputWorkspace=sample_wave_ws, Target='Wavelength', EMode='Indirect', EFixed=efixed, EnableLogging = False) if self._sample_density_type == 'Mass Density': builder = MaterialBuilder() mat = builder.setFormula(self._sample_chemical_formula).setMassDensity(self._sample_density).build() self._sample_density = mat.numberDensity SetSampleMaterial(sample_wave_ws, ChemicalFormula=self._sample_chemical_formula, SampleNumberDensity=self._sample_density) prog.report('Calculating sample corrections') FlatPlateAbsorption(InputWorkspace=sample_wave_ws, OutputWorkspace=self._ass_ws, SampleHeight=self._sample_height, SampleWidth=self._sample_width, SampleThickness=self._sample_thickness, ElementSize=self._element_size, EMode='Indirect', EFixed=efixed, NumberOfWavelengthPoints=10) group = self._ass_ws if self._can_ws_name is not None: can_wave_ws = '__can_wave' ConvertUnits(InputWorkspace=self._can_ws_name, OutputWorkspace=can_wave_ws, Target='Wavelength', EMode='Indirect', EFixed=efixed, EnableLogging = False) if self._can_scale != 1.0: logger.information('Scaling container by: ' + str(self._can_scale)) Scale(InputWorkspace=can_wave_ws, OutputWorkspace=can_wave_ws, Factor=self._can_scale, Operation='Multiply') if self._use_can_corrections: prog.report('Calculating container corrections') Divide(LHSWorkspace=sample_wave_ws, RHSWorkspace=self._ass_ws, OutputWorkspace=sample_wave_ws) if self._sample_density_type == 'Mass Density': builder = MaterialBuilder() mat = builder.setFormula(self._can_chemical_formula).setMassDensity(self._can_density).build() self._can_density = mat.numberDensity SetSampleMaterial(can_wave_ws, ChemicalFormula=self._can_chemical_formula, SampleNumberDensity=self._can_density) FlatPlateAbsorption(InputWorkspace=can_wave_ws, OutputWorkspace=self._acc_ws, SampleHeight=self._sample_height, SampleWidth=self._sample_width, SampleThickness=self._can_front_thickness + self._can_back_thickness, ElementSize=self._element_size, EMode='Indirect', EFixed=efixed, NumberOfWavelengthPoints=10) Divide(LHSWorkspace=can_wave_ws, RHSWorkspace=self._acc_ws, OutputWorkspace=can_wave_ws) Minus(LHSWorkspace=sample_wave_ws, RHSWorkspace=can_wave_ws, OutputWorkspace=sample_wave_ws) group += ',' + self._acc_ws else: prog.report('Calculating container scaling') Minus(LHSWorkspace=sample_wave_ws, RHSWorkspace=can_wave_ws, OutputWorkspace=sample_wave_ws) Divide(LHSWorkspace=sample_wave_ws, RHSWorkspace=self._ass_ws, OutputWorkspace=sample_wave_ws) DeleteWorkspace(can_wave_ws, EnableLogging = False) else: Divide(LHSWorkspace=sample_wave_ws, RHSWorkspace=self._ass_ws, OutputWorkspace=sample_wave_ws) ConvertUnits(InputWorkspace=sample_wave_ws, OutputWorkspace=self._output_ws, Target='DeltaE', EMode='Indirect', EFixed=efixed, EnableLogging = False) DeleteWorkspace(sample_wave_ws, EnableLogging = False) prog.report('Recording sample logs') sample_log_workspaces = [self._output_ws, self._ass_ws] sample_logs = [('sample_shape', 'flatplate'), ('sample_filename', self._sample_ws), ('sample_height', self._sample_height), ('sample_width', self._sample_width), ('sample_thickness', self._sample_thickness), ('element_size', self._element_size)] 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_front_thickness', self. _can_front_thickness)) sample_logs.append(('container_back_thickness', self. _can_back_thickness)) log_names = [item[0] for item in sample_logs] log_values = [item[1] for item in sample_logs] for ws_name in sample_log_workspaces: AddSampleLogMultiple(Workspace=ws_name, LogNames=log_names, LogValues=log_values, EnableLogging = False) self.setProperty('OutputWorkspace', self._output_ws) # Output the Ass workspace if it is wanted, delete if not if self._abs_ws == '': DeleteWorkspace(self._ass_ws, EnableLogging = False) if self._can_ws_name is not None and self._use_can_corrections: DeleteWorkspace(self._acc_ws, EnableLogging = False) else: GroupWorkspaces(InputWorkspaces=group, OutputWorkspace=self._abs_ws, EnableLogging = False) self.setProperty('CorrectionsWorkspace', self._abs_ws)
def generate_ts_pdf(run_number, focus_file_path, sample_details, merge_banks=False, q_lims=None, cal_file_name=None, delta_r=None, delta_q=None, pdf_type="G(r)", lorch_filter=None, freq_params=None, debug=False): if sample_details is None: raise RuntimeError( "A SampleDetails object was not set. Please create a SampleDetails object and set the " "relevant properties it. Then set the new sample by calling set_sample_details()" ) focused_ws = _obtain_focused_run(run_number, focus_file_path) focused_ws = mantid.ConvertUnits(InputWorkspace=focused_ws, Target="MomentumTransfer", EMode='Elastic') raw_ws = mantid.Load(Filename='POLARIS' + str(run_number)) sample_geometry_json = sample_details.generate_sample_geometry() sample_material_json = sample_details.generate_sample_material() self_scattering_correction = mantid.TotScatCalculateSelfScattering( InputWorkspace=raw_ws, CalFileName=cal_file_name, SampleGeometry=sample_geometry_json, SampleMaterial=sample_material_json) ws_group_list = [] for i in range(self_scattering_correction.getNumberHistograms()): ws_name = 'correction_' + str(i) mantid.ExtractSpectra(InputWorkspace=self_scattering_correction, OutputWorkspace=ws_name, WorkspaceIndexList=[i]) ws_group_list.append(ws_name) self_scattering_correction = mantid.GroupWorkspaces( InputWorkspaces=ws_group_list) self_scattering_correction = mantid.RebinToWorkspace( WorkspaceToRebin=self_scattering_correction, WorkspaceToMatch=focused_ws) if not compare_ws_compatibility(focused_ws, self_scattering_correction): raise RuntimeError( "To use create_total_scattering_pdf you need to run focus with " "do_van_normalisation=true first.") focused_ws = mantid.Subtract(LHSWorkspace=focused_ws, RHSWorkspace=self_scattering_correction) if debug: dcs_corrected = mantid.CloneWorkspace(InputWorkspace=focused_ws) # convert diff cross section to S(Q) - 1 material_builder = MaterialBuilder() sample = material_builder.setFormula( sample_details.material_object.chemical_formula).build() sample_total_scatter_cross_section = sample.totalScatterXSection() sample_coh_scatter_cross_section = sample.cohScatterXSection() focused_ws = focused_ws - sample_total_scatter_cross_section / (4 * math.pi) focused_ws = focused_ws * 4 * math.pi / sample_coh_scatter_cross_section if debug: s_of_q_minus_one = mantid.CloneWorkspace(InputWorkspace=focused_ws) if delta_q: focused_ws = mantid.Rebin(InputWorkspace=focused_ws, Params=delta_q) if merge_banks: q_min, q_max = _load_qlims(q_lims) merged_ws = mantid.MatchAndMergeWorkspaces(InputWorkspaces=focused_ws, XMin=q_min, XMax=q_max, CalculateScale=False) fast_fourier_filter(merged_ws, rho0=sample_details.material_object.number_density, freq_params=freq_params) pdf_output = mantid.PDFFourierTransform( Inputworkspace="merged_ws", InputSofQType="S(Q)-1", PDFType=pdf_type, Filter=lorch_filter, DeltaR=delta_r, rho0=sample_details.material_object.number_density) else: for ws in focused_ws: fast_fourier_filter( ws, rho0=sample_details.material_object.number_density, freq_params=freq_params) pdf_output = mantid.PDFFourierTransform( Inputworkspace='focused_ws', InputSofQType="S(Q)-1", PDFType=pdf_type, Filter=lorch_filter, DeltaR=delta_r, rho0=sample_details.material_object.number_density) pdf_output = mantid.RebinToWorkspace(WorkspaceToRebin=pdf_output, WorkspaceToMatch=pdf_output[4], PreserveEvents=True) if not debug: common.remove_intermediate_workspace('self_scattering_correction') # Rename output ws if 'merged_ws' in locals(): mantid.RenameWorkspace(InputWorkspace='merged_ws', OutputWorkspace=run_number + '_merged_Q') mantid.RenameWorkspace(InputWorkspace='focused_ws', OutputWorkspace=run_number + '_focused_Q') target_focus_ws_name = run_number + '_focused_Q_' target_pdf_ws_name = run_number + '_pdf_R_' if isinstance(focused_ws, WorkspaceGroup): for i in range(len(focused_ws)): if str(focused_ws[i]) != (target_focus_ws_name + str(i + 1)): mantid.RenameWorkspace(InputWorkspace=focused_ws[i], OutputWorkspace=target_focus_ws_name + str(i + 1)) mantid.RenameWorkspace(InputWorkspace='pdf_output', OutputWorkspace=run_number + '_pdf_R') if isinstance(pdf_output, WorkspaceGroup): for i in range(len(pdf_output)): if str(pdf_output[i]) != (target_pdf_ws_name + str(i + 1)): mantid.RenameWorkspace(InputWorkspace=pdf_output[i], OutputWorkspace=target_pdf_ws_name + str(i + 1)) return pdf_output