def _update_function_from_params(self, function_str, params): params_dict = TableWorkspaceDictionaryFacade(params) functions = function_str.split(';') new_functions = [functions[0]] idx = 0; for func in functions[1:]: new_params = [] for param in func.split(','): if param.split('=')[0] == 'name': new_params.append(param) param_prefix = 'f{0}.'.format(idx) for name, value in params_dict.items(): if param_prefix in name: new_params.append('{0}={1}'.format(name, value)) new_functions.append(','.join(new_params)) idx += 1 new_function_str = ';'.join(new_functions) return new_function_str
def _get_correction_scale_factor(self, correction_name, corrections, params_ws): index = self._get_correction_workspace(correction_name, corrections)[0] if index is None: raise RuntimeError('No workspace for given correction') params_dict = TableWorkspaceDictionaryFacade(params_ws) scale_param_name = 'f%d.Scaling' % index return params_dict[scale_param_name]
def _run_fit_impl(self, data_ws, workspace_index, fit_options, simulation=False): """ Run the Fit algorithm with the given options on the input data @param data_ws :: The workspace containing the data to fit too @param workspace_index :: The spectra to fit against @param fit_options :: An object of type FittingOptions containing the parameters @param simulation :: If true then only a single iteration is run """ if simulation: raise RuntimeError("Simulation not implemented yet") else: # Run fitting first time using constraints matrix to reduce active parameter set function_str = fit_options.create_function_str() constraints = fit_options.create_constraints_str() ties = fit_options.create_ties_str() user_ties = self.getProperty('Ties').value if user_ties != "": ties = ties + ',' + user_ties _, params, fitted_data = self._do_fit( function_str, data_ws, workspace_index, constraints, ties, max_iter=self.getProperty("MaxIterations").value) # Run second time using standard CompositeFunction & no constraints matrix to # calculate correct reduced chisq param_values = TableWorkspaceDictionaryFacade(params) function_str = fit_options.create_function_str(param_values) max_iter = 0 if simulation else 1 reduced_chi_square, _, _ = self._do_fit(function_str, data_ws, workspace_index, constraints, ties, max_iter=max_iter) return reduced_chi_square, params, fitted_data
def _gamma_correction(self): correction_background_ws = str( self._correction_wsg) + "_GammaBackground" fit_opts = parse_fit_options( mass_values=self._masses, profile_strs=self.getProperty("MassProfiles").value, constraints_str=self.getProperty("IntensityConstraints").value) params_dict = TableWorkspaceDictionaryFacade( self.getProperty("FitParameters").value) func_str = fit_opts.create_function_str(params_dict) ms.VesuvioCalculateGammaBackground( InputWorkspace=self._output_ws, ComptonFunction=func_str, BackgroundWorkspace=correction_background_ws, CorrectedWorkspace='__corrected_dummy') ms.DeleteWorkspace('__corrected_dummy') return correction_background_ws
def _ms_correction(self): """ Calculates the contributions from multiple scattering on the input data from the set of given options """ params_dict = TableWorkspaceDictionaryFacade( self.getProperty("FitParameters").value) atom_props = list() intensities = list() contains_hydrogen = False i = 0 for idx, mass in enumerate(self._masses): if str(idx) in self._index_to_symbol_map: symbol = self._index_to_symbol_map[str(idx)].value else: symbol = None if symbol == 'H' and self._back_scattering: contains_hydrogen = True continue intensity_prop = 'f%d.Intensity' % i c0_prop = 'f%d.C_0' % i if intensity_prop in params_dict: intensity = params_dict[intensity_prop] elif c0_prop in params_dict: intensity = params_dict[c0_prop] else: i = i + 1 continue # The program DINSMS_BATCH uses those sample parameters together with the sigma divided # by the sum absolute of scattering intensities for each detector (detector bank), # sigma/int_sum # Thus: # intensity = intensity/intensity_sum # In the thin sample limit, 1-exp(-n*dens*sigma) ~ n*dens*sigma, effectively the same # scattering power (ratio of double to single scatt.) is obtained either by using # relative intensities ( sigma/int_sum ) or density divided by the total intensity # However, in the realistic case of thick sample, the SampleDensity, dens, must be # obtained by iterative numerical solution of the Eq: # 1-exp(-n*dens*sigma) = measured scattering power of the sample. # For this, a program like THICK must be used. # The program THICK also uses sigma/int_sum to be consistent with the prgram # DINSMS_BATCH width_prop = 'f%d.Width' % i sigma_x_prop = 'f%d.SigmaX' % i sigma_y_prop = 'f%d.SigmaY' % i sigma_z_prop = 'f%d.SigmaZ' % i if width_prop in params_dict: width = params_dict['f%d.Width' % i] elif sigma_x_prop in params_dict: sigma_x = float(params_dict[sigma_x_prop]) sigma_y = float(params_dict[sigma_y_prop]) sigma_z = float(params_dict[sigma_z_prop]) width = math.sqrt((sigma_x**2 + sigma_y**2 + sigma_z**2) / 3.0) else: i = i + 1 continue atom_props.append(mass) atom_props.append(intensity) atom_props.append(width) intensities.append(intensity) # Check for NoneType is necessary as hydrogen constraints are # stored in a C++ PropertyManager object, not a dict; call to # __contains__ must match the C++ signature. if self._back_scattering and symbol is not None and symbol in self._hydrogen_constraints: self._hydrogen_constraints[symbol].value[ 'intensity'] = intensity i = i + 1 if self._back_scattering and contains_hydrogen: material_builder = MaterialBuilder() hydrogen = material_builder.setFormula('H').build() hydrogen_intensity = \ self._calculate_hydrogen_intensity(hydrogen, self._hydrogen_constraints) hydrogen_width = 5 atom_props.append(hydrogen.relativeMolecularMass()) atom_props.append(hydrogen_intensity) atom_props.append(hydrogen_width) intensities.append(hydrogen_intensity) intensity_sum = sum(intensities) # Create the sample shape # Input dimensions are expected in CM ms.CreateSampleShape(InputWorkspace=self._output_ws, ShapeXML=create_cuboid_xml( self.getProperty("SampleHeight").value / 100., self.getProperty("SampleWidth").value / 100., self.getProperty("SampleDepth").value / 100.)) # Massage options into how algorithm expects them total_scatter_correction = str( self._correction_wsg) + "_TotalScattering" multi_scatter_correction = str( self._correction_wsg) + "_MultipleScattering" # Calculation # In the thin sample limit, 1-exp(-n*dens*sigma) ~ n*dens*sigma, effectively the same # scattering power(ratio of double to single scatt.) is obtained either by using relative # intensities ( sigma/int_sum )or density divided by the total intensity. # However, in the realistic case of thick sample, the SampleDensity, dens, must be # obtained by iterative numerical solution of the Eq: # 1-exp(-n*dens*sigma) = measured scattering power of the sample. # For this, a program like THICK must be used. # The program THICK also uses sigma/int_sum to be consistent with the prgram DINSMS_BATCH # The algorithm VesuvioCalculateMs called by the algorithm VesuvioCorrections takes the # parameter AtomicProperties with the absolute intensities, contraty to DINSMS_BATCH which # takes in relative intensities. # To compensate for this, the thickness parameter, dens (SampleDensity), is divided in by # the sum of absolute intensities in VesuvioCorrections before being passed to # VesuvioCalculateMs. # Then, for the modified VesuvioCorrection algorithm one can use the thickenss parameter is # as is from the THICK command, i.e. 43.20552 # This works, however, only in the thin sample limit, contrary to the THICK program. Thus, # for some detectors (detector banks) the SampleDensiy parameter may be over(under) # estimated. ms.VesuvioCalculateMS( InputWorkspace=self._output_ws, NoOfMasses=int(len(atom_props) / 3), SampleDensity=self.getProperty("SampleDensity").value / intensity_sum, AtomicProperties=atom_props, BeamRadius=self.getProperty("BeamRadius").value, NumEventsPerRun=self.getProperty("NumEvents").value, TotalScatteringWS=total_scatter_correction, MultipleScatteringWS=multi_scatter_correction) # Smooth the output smooth_neighbours = self.getProperty("SmoothNeighbours").value ms.SmoothData(InputWorkspace=total_scatter_correction, OutputWorkspace=total_scatter_correction, NPoints=smooth_neighbours) ms.SmoothData(InputWorkspace=multi_scatter_correction, OutputWorkspace=multi_scatter_correction, NPoints=smooth_neighbours) return total_scatter_correction, multi_scatter_correction
def _ms_correction(self): """ Calculates the contributions from multiple scattering on the input data from the set of given options """ masses = self.getProperty("Masses").value params_ws_name = self.getPropertyValue("FitParameters") params_dict = TableWorkspaceDictionaryFacade(mtd[params_ws_name]) atom_props = list() intensities = list() for i, mass in enumerate(masses): intentisty_prop = 'f%d.Intensity' % i c0_prop = 'f%d.C_0' % i if intentisty_prop in params_dict: intentisy = params_dict[intentisty_prop] elif c0_prop in params_dict: intentisy = params_dict[c0_prop] else: continue # The program DINSMS_BATCH uses those sample parameters together with the sigma divided # by the sum absolute of scattering intensities for each detector (detector bank), # sigma/int_sum # Thus: # intensity = intensity/intensity_sum # In the thin sample limit, 1-exp(-n*dens*sigma) ~ n*dens*sigma, effectively the same # scattering power (ratio of double to single scatt.) is obtained either by using # relative intensities ( sigma/int_sum ) or density divided by the total intensity # However, in the realistic case of thick sample, the SampleDensity, dens, must be # obtained by iterative numerical solution of the Eq: # 1-exp(-n*dens*sigma) = measured scattering power of the sample. # For this, a program like THICK must be used. # The program THICK also uses sigma/int_sum to be consistent with the prgram # DINSMS_BATCH width_prop = 'f%d.Width' % i sigma_x_prop = 'f%d.SigmaX' % i sigma_y_prop = 'f%d.SigmaY' % i sigma_z_prop = 'f%d.SigmaZ' % i if width_prop in params_dict: width = params_dict['f%d.Width' % i] elif sigma_x_prop in params_dict: sigma_x = float(params_dict[sigma_x_prop]) sigma_y = float(params_dict[sigma_y_prop]) sigma_z = float(params_dict[sigma_z_prop]) width = math.sqrt((sigma_x**2 + sigma_y**2 + sigma_z**2) / 3.0) else: continue atom_props.append(mass) atom_props.append(intentisy) atom_props.append(width) intensities.append(intentisy) intensity_sum = sum(intensities) # Create the sample shape # Input dimensions are expected in CM ms.CreateSampleShape(InputWorkspace=self._output_ws, ShapeXML=create_cuboid_xml( self.getProperty("SampleHeight").value / 100., self.getProperty("SampleWidth").value / 100., self.getProperty("SampleDepth").value / 100.)) # Massage options into how algorithm expects them total_scatter_correction = str( self._correction_wsg) + "_TotalScattering" multi_scatter_correction = str( self._correction_wsg) + "_MultipleScattering" # Calculation # In the thin sample limit, 1-exp(-n*dens*sigma) ~ n*dens*sigma, effectively the same # scattering power(ratio of double to single scatt.) is obtained either by using relative # intensities ( sigma/int_sum )or density divided by the total intensity. # However, in the realistic case of thick sample, the SampleDensity, dens, must be # obtained by iterative numerical solution of the Eq: # 1-exp(-n*dens*sigma) = measured scattering power of the sample. # For this, a program like THICK must be used. # The program THICK also uses sigma/int_sum to be consistent with the prgram DINSMS_BATCH # The algorithm VesuvioCalculateMs called by the algorithm VesuvioCorrections takes the # parameter AtomicProperties with the absolute intensities, contraty to DINSMS_BATCH which # takes in relative intensities. # To compensate for this, the thickness parameter, dens (SampleDensity), is divided in by # the sum of absolute intensities in VesuvioCorrections before being passed to # VesuvioCalculateMs. # Then, for the modified VesuvioCorrection algorithm one can use the thickenss parameter is # as is from the THICK command, i.e. 43.20552 # This works, however, only in the thin sample limit, contrary to the THICK program. Thus, # for some detectors (detector banks) the SampleDensiy parameter may be over(under) # estimated. ms.VesuvioCalculateMS( InputWorkspace=self._output_ws, NoOfMasses=len(atom_props) / 3, SampleDensity=self.getProperty("SampleDensity").value / intensity_sum, AtomicProperties=atom_props, BeamRadius=self.getProperty("BeamRadius").value, NumEventsPerRun=self.getProperty("NumEvents").value, TotalScatteringWS=total_scatter_correction, MultipleScatteringWS=multi_scatter_correction) # Smooth the output smooth_neighbours = self.getProperty("SmoothNeighbours").value ms.SmoothData(InputWorkspace=total_scatter_correction, OutputWorkspace=total_scatter_correction, NPoints=smooth_neighbours) ms.SmoothData(InputWorkspace=multi_scatter_correction, OutputWorkspace=multi_scatter_correction, NPoints=smooth_neighbours) return total_scatter_correction, multi_scatter_correction