def run_fit(wks, prob, function, minimizer='Levenberg-Marquardt', cost_function='Least squares'): """ Fits the data in a workspace with a function, using the algorithm Fit. Importantly, the option IgnoreInvalidData is enabled. Check the documentation of Fit for the implications of this. @param wks :: MatrixWorkspace with data to fit, in the format expected by the algorithm Fit @param prob :: Problem definition @param function :: function definition as used in the algorithm Fit @param minimizer :: minimizer to use in Fit @param cost_function :: cost function to use in Fit @returns the fitted parameter values and error estimates for these """ status = None chi2 = None param_tbl = None fit_wks = None try: # When using 'Least squares' (weighted by errors), ignore nans and zero errors, but don't # ignore them when using 'Unweighted least squares' as that would ignore all values! ignore_invalid = cost_function == 'Least squares' # Note the ugly adhoc exception. We need to reconsider these WISH problems: if 'WISH17701' in prob.name: ignore_invalid = False status, chi2, covar_tbl, param_tbl, fit_wks = msapi.Fit( function, wks, Output='ws_fitting_test', Minimizer=minimizer, CostFunction=cost_function, IgnoreInvalidData=ignore_invalid, StartX=prob.start_x, EndX=prob.end_x) calc_chi2 = msapi.CalculateChiSquared(Function=function, InputWorkspace=wks, IgnoreInvalidData=ignore_invalid) print("*** with minimizer {0}, calculated: chi2: {1}".format( minimizer, calc_chi2)) except RuntimeError as rerr: print("Warning, Fit probably failed. Going on. Error: {0}".format( str(rerr))) if param_tbl: params = param_tbl.column(1)[:-1] errors = param_tbl.column(2)[:-1] else: params = None errors = None return status, chi2, fit_wks, params, errors
def _fit_bank_curve(self, vanadium_ws, bank, spline_breaks, prog): """ Fits a spline to a single-spectrum workspace (in d-spacing) @param vanadium_ws :: Vanadium workspace to fit (normally this contains spectra for a single bank) @param bank :: instrument bank this is fitting is done for @param spline_breaks :: number of break points when fitting spline functions @param prog :: progress reporter @returns fit workspace (MatrixWorkspace), with the same number of bins as the input workspace, and the Y values simulated from the fitted curve """ expected_dim = 'd-Spacing' dim_type = vanadium_ws.getXDimension().name if expected_dim != dim_type: raise ValueError("This algorithm expects a workspace with %s X dimension, but " "the X dimension of the input workspace is: '%s'" % (expected_dim, dim_type)) if 1 != vanadium_ws.getNumberHistograms(): raise ValueError("The workspace does not have exactly one histogram. Inconsistency found.") # without these min/max parameters 'BSpline' would completely misbehave x_values = vanadium_ws.readX(0) start_x = min(x_values) end_x = max(x_values) function_descriptor = ('name=BSpline, Order=3, StartX={0}, EndX={1}, NBreak={2}'. format(start_x, end_x, spline_breaks)) # WorkspaceIndex is left to default '0' for 1D function fits # StartX, EndX could in principle be left to default start/end of the spectrum, but apparently # not safe for 'BSpline' prog.report("Performing fit") fit_output = mantid.Fit(InputWorkspace=vanadium_ws, Function=function_descriptor, CreateOutput=True, StoreInADS=False) prog.report("Fit complete") success = fit_output.OutputStatus self.log().information("Fitting Vanadium curve for bank %s, using function '%s', result: %s" % (bank, function_descriptor, success)) failure_msg = ("It seems that this algorithm failed to to fit a function to the summed " "spectra of a bank. The function definiton was: '%s'") % function_descriptor output_params_prop_name = "OutputParameters" if not hasattr(fit_output, output_params_prop_name): raise RuntimeError("Could not find the parameters workspace expected in the output property " + output_params_prop_name + " from the algorithm Fit. It seems that this algorithm failed." + failure_msg) try: fit_ws = fit_output.OutputWorkspace except AttributeError: raise RuntimeError("Could not find the data workspace expected in the output property " + "OutputWorkspace" + ". " + failure_msg) mtd['engg_van_ws_dsp'] = vanadium_ws mtd['engg_fit_ws_dsp'] = fit_ws return fit_ws
def fit(self): """ Run problem with Mantid. """ fit_result = msapi.Fit(Function=self._mantid_function, InputWorkspace=self._mantid_data, Output='ws_fitting_test', Minimizer=self.minimizer, CostFunction=self._cost_function) self._mantid_results = fit_result self._status = self._mantid_results.OutputStatus
def doFit(self, wprofile, **fitkwargs): """ Thin wrapper to mantid.simpleapi.Fit :param wprofile: mantid workspace holding the experimental profile :param fitkwargs: optional arguments for algorithm mantid.simpleapi.Fit :return: (type namedtuple) results of evaluating algorithm mantid.simpleapi.Fit """ if not self._valid_xdomain(wprofile.dataX(0)): raise ValueError("Experimental Q-domain not included within the simulated Q-domain") self._fitresults = smtdi.Fit(Function=self.fstr(), InputWorkspace=wprofile.name(), WorkspaceIndex=0, CreateOutput=True, **fitkwargs) return self._fitresults
def fit(self): """ Run problem with Mantid. """ fit_result = msapi.Fit(Function=self._mantid_function, CostFunction=self._cost_function, Minimizer=self.minimizer, InputWorkspace=self._mantid_data, Output='fit', **self._added_args) self._mantid_results = fit_result self._status = self._mantid_results.OutputStatus
def fit(ws, function, workspace_index, start_x, end_x): """ Performs a fit on the workspace. :param ws: The workspace on which the fit will be performed :param function: The function used for the fit. This is anything that mantid.Fit's Function parameter can handle. :param workspace_index: Workspace index which will be fitted. :param start_x: Start X for the fit :param end_x: End X for the fit :returns: Dataset containing all of Fit's outputs """ try: import mantid.simpleapi as mantid except ImportError: raise ImportError( "Mantid Python API was not found, please install Mantid framework " "as detailed in the installation instructions (https://scipp." "readthedocs.io/en/latest/getting-started/installation.html)") fit = mantid.Fit(Function=function, InputWorkspace=ws, WorkspaceIndex=workspace_index, StartX=start_x, EndX=end_x, CreateOutput=True, StoreinADS=False) ds = sc.Dataset(data={ 'workspace': sc.Variable(convert_Workspace2D_to_data_array(fit.OutputWorkspace)), 'parameters': sc.Variable(convert_TableWorkspace_to_dataset(fit.OutputParameters)), 'normalised_covariance_matrix': sc.Variable( convert_TableWorkspace_to_dataset( fit.OutputNormalisedCovarianceMatrix)), }, attrs={ 'status': sc.Variable(fit.OutputStatus), 'chi2_over_DoF': sc.Variable(fit.OutputChi2overDoF), 'function': sc.Variable(str(fit.Function)), 'cost_function': sc.Variable(fit.CostFunction) }) # clean up leftover workspaces in the ADS mantid.DeleteWorkspace(fit.OutputWorkspace) mantid.DeleteWorkspace(fit.OutputParameters) mantid.DeleteWorkspace(fit.OutputNormalisedCovarianceMatrix) return ds
def final_fit(fit_ws_name, constraints,y_range, correct_for_offsets, masses, g_log) : function = """ composite=Convolution,FixResolution=true,NumDeriv=true; name=Resolution,Workspace=resolution,WorkspaceIndex=0,X=(),Y=(); name=UserFunction,Formula=exp( -x^2/2./sigma1^2) *(1.+c4/32.*(16.*(x/sqrt(2)/sigma1)^4-48.*(x/sqrt(2)/sigma1)^2+12) +c6/384.*( 64.*(x/sqrt(2)/sigma1)^6 -480.*(x/sqrt(2)/sigma1)^4 +720.*(x/sqrt(2)/sigma1)^2 -120.) )*A + B0, sigma1=3.0,c4=0.0, c6=0.0,A=0.08, B0=0.00, ties = (c6=0. ) """ function+=constraints minimiser = "Simplex" sapi.Fit(Function= function, InputWorkspace=fit_ws_name, MaxIterations=2000, Minimizer= minimiser, Output=fit_ws_name, OutputCompositeMembers=True, StartX = y_range[0] , EndX = y_range[1]) ws = sapi.mtd[fit_ws_name+"_Parameters"] g_log.notice( "\n Final parameters \n") g_log.notice( "width: ",ws.cell(0,1)," +/- ",ws.cell(0,2), " A-1 ") g_log.notice( "c4: ",ws.cell(1,1)," +/- ",ws.cell(1,2), " A-1 ") sigma_to_energy = 1.5 * 2.0445**2 / masses[0] g_log.notice( "mean kinetic energy: ",sigma_to_energy*ws.cell(0,1)**2," +/- ", 2.*sigma_to_energy*ws.cell(0,2)*ws.cell(0,1), " meV ") if correct_for_offsets : sapi.Scale(InputWorkspace=fit_ws_name,Factor=-ws.cell(4,1),Operation="Add",OutputWorkspace=fit_ws_name+'_cor') sapi.Scale(InputWorkspace=fit_ws_name+'_cor', Factor=(2.*np.pi)**(-0.5)/ws.cell(0,1)/ws.cell(3,1),Operation="Multiply", OutputWorkspace=fit_ws_name+'_cor')
def runTest(self): data = sm.Load("irs26176_graphite002_red.nxs") sm.Load("irs26173_graphite002_res.nxs", OutputWorkspace="resolution") single_model = """(composite=Convolution,NumDeriv=true; name=TabulatedFunction,Workspace=resolution,WorkspaceIndex=0, Scaling=1,Shift=0,XScaling=1; (name=DeltaFunction,Height=1.5,Centre=0; name=TeixeiraWaterSQE,Height=1.0,Tau=1.0,DiffCoeff=1.0,Centre=0; ties=(f1.Centre=f0.Centre))); name=LinearBackground,A0=0,A1=0""" single_model = re.sub('[\s+]', '', single_model) # Include all spectra for the fit selected_wi = range(data.getNumberHistograms()) nWi = len(selected_wi) # number of selected spectra for fitting # Energy range over which we do the fitting. minE = -0.4 # Units are in meV maxE = 0.4 # Create the string representation of the global model (for selected spectra): global_model = "composite=MultiDomainFunction,NumDeriv=true;" for _ in selected_wi: global_model += "(composite=CompositeFunction,NumDeriv=true,$domains=i;{0});\n".format( single_model) # Tie DiffCoeff and Tau since they are global parameters ties = [ '='.join([ "f{0}.f0.f1.f1.DiffCoeff".format(di) for di in reversed(range(nWi)) ]), '='.join([ "f{0}.f0.f1.f1.Tau".format(wi) for wi in reversed(range(nWi)) ]) ] global_model += "ties=(" + ','.join(ties) + ')' # tie Radius # Now relate each domain(i.e. spectrum) to each single-spectrum model domain_model = dict() domain_index = 0 for wi in selected_wi: if domain_index == 0: domain_model.update({ "InputWorkspace": data.name(), "WorkspaceIndex": str(wi), "StartX": str(minE), "EndX": str(maxE) }) else: di = str(domain_index) domain_model.update({ "InputWorkspace_" + di: data.name(), "WorkspaceIndex_" + di: str(wi), "StartX_" + di: str(minE), "EndX_" + di: str(maxE) }) domain_index += 1 # Invoke the Fit algorithm using global_model and domain_model: output_workspace = "glofit_" + data.name() fit_output = sm.Fit(Function=global_model, Output=output_workspace, CreateOutput=True, MaxIterations=500, **domain_model) chi2 = fit_output.OutputChi2overDoF params = fit_output.OutputParameters curves = fit_output.OutputWorkspace # Validate self._success = True try: self.assertTrue(chi2 < 1) # goodness of fit self.assertTrue(abs(params.row(6)["Value"] - 1.58) / 1.58 < 0.1) # optimal DiffCoeff self.assertTrue( abs(params.row(7)["Value"] - 1.16) / 1.16 < 0.1) # optimal Tau # check curves are correctly generated by calculating their Chi^2 residuals = np.empty(0) for i in range(curves.size()): curveset = curves[i] # contains data, model, and residuals dataY = curveset.dataY(0) dataE = curveset.dataE(0) modelY = curveset.dataY(1) residuals = np.append( residuals, ((dataY - modelY) / dataE)**2) # don't trust residuals of curveset otherChi2 = residuals.sum() / len(residuals) self.assertTrue(abs(otherChi2 - chi2) / chi2 < 0.1) except: self._success = False
def PyExec(self): from IndirectCommon import (convertToElasticQ, transposeFitParametersTable) setup_prog = Progress(self, start=0.0, end=0.1, nreports=4) setup_prog.report('generating output name') output_workspace = self._fit_group_name # check if the naming convention used is already correct chopped_name = self._fit_group_name.split('_') if 'WORKSPACE' in chopped_name[-1].upper(): output_workspace = '_'.join(chopped_name[:-1]) option = self._fit_type[:-2] logger.information('Option: ' + option) logger.information('Function: ' + str(self._function)) setup_prog.report('Cropping workspace') # prepare input workspace for fitting tmp_fit_workspace = "__Iqtfit_fit_ws" if self._spec_max is None: crop_alg = self.createChildAlgorithm("CropWorkspace", enableLogging=False) crop_alg.setProperty("InputWorkspace", self._input_ws) crop_alg.setProperty("OutputWorkspace", tmp_fit_workspace) crop_alg.setProperty("XMin", self._start_x) crop_alg.setProperty("XMax", self._end_x) crop_alg.setProperty("StartWorkspaceIndex", self._spec_min) crop_alg.execute() else: crop_alg = self.createChildAlgorithm("CropWorkspace", enableLogging=False) crop_alg.setProperty("InputWorkspace", self._input_ws) crop_alg.setProperty("OutputWorkspace", tmp_fit_workspace) crop_alg.setProperty("XMin", self._start_x) crop_alg.setProperty("XMax", self._end_x) crop_alg.setProperty("StartWorkspaceIndex", self._spec_min) crop_alg.setProperty("EndWorkspaceIndex", self._spec_max) crop_alg.execute() setup_prog.report('Converting to Histogram') convert_to_hist_alg = self.createChildAlgorithm("ConvertToHistogram", enableLogging=False) convert_to_hist_alg.setProperty("InputWorkspace", crop_alg.getProperty("OutputWorkspace").value) convert_to_hist_alg.setProperty("OutputWorkspace", tmp_fit_workspace) convert_to_hist_alg.execute() mtd.addOrReplace(tmp_fit_workspace, convert_to_hist_alg.getProperty("OutputWorkspace").value) setup_prog.report('Convert to Elastic Q') convertToElasticQ(tmp_fit_workspace) # fit multi-domain function to workspace fit_prog = Progress(self, start=0.1, end=0.8, nreports=2) multi_domain_func, kwargs = _create_multi_domain_func(self._function, tmp_fit_workspace) fit_prog.report('Fitting...') ms.Fit(Function=multi_domain_func, InputWorkspace=tmp_fit_workspace, WorkspaceIndex=0, Output=output_workspace, CreateOutput=True, Minimizer=self._minimizer, MaxIterations=self._max_iterations, OutputCompositeMembers=self._do_extract_members, **kwargs) fit_prog.report('Fitting complete') conclusion_prog = Progress(self, start=0.8, end=1.0, nreports=5) conclusion_prog.report('Renaming workspaces') # rename workspaces to match user input rename_alg = self.createChildAlgorithm("RenameWorkspace", enableLogging=False) if output_workspace + "_Workspaces" != self._fit_group_name: rename_alg.setProperty("InputWorkspace", output_workspace + "_Workspaces") rename_alg.setProperty("OutputWorkspace", self._fit_group_name) rename_alg.execute() if output_workspace + "_Parameters" != self._parameter_name: rename_alg.setProperty("InputWorkspace", output_workspace + "_Parameters") rename_alg.setProperty("OutputWorkspace", self._parameter_name) rename_alg.execute() conclusion_prog.report('Transposing parameter table') transposeFitParametersTable(self._parameter_name) # set first column of parameter table to be axis values x_axis = mtd[tmp_fit_workspace].getAxis(1) axis_values = x_axis.extractValues() for i, value in enumerate(axis_values): mtd[self._parameter_name].setCell('axis-1', i, value) # convert parameters to matrix workspace parameter_names = 'A0,Height,Lifetime,Stretching' conclusion_prog.report('Processing indirect fit parameters') pifp_alg = self.createChildAlgorithm("ProcessIndirectFitParameters") pifp_alg.setProperty("InputWorkspace", self._parameter_name) pifp_alg.setProperty("ColumnX", "axis-1") pifp_alg.setProperty("XAxisUnit", "MomentumTransfer") pifp_alg.setProperty("ParameterNames", parameter_names) pifp_alg.setProperty("OutputWorkspace", self._result_name) pifp_alg.execute() result_workspace = pifp_alg.getProperty("OutputWorkspace").value mtd.addOrReplace(self._result_name, result_workspace) # create and add sample logs sample_logs = {'start_x': self._start_x, 'end_x': self._end_x, 'fit_type': self._fit_type[:-2], 'intensities_constrained': self._intensities_constrained, 'beta_constrained': True} conclusion_prog.report('Copying sample logs') copy_log_alg = self.createChildAlgorithm("CopyLogs", enableLogging=False) copy_log_alg.setProperty("InputWorkspace", self._input_ws) copy_log_alg.setProperty("OutputWorkspace", result_workspace) copy_log_alg.execute() copy_log_alg.setProperty("InputWorkspace", self._input_ws) copy_log_alg.setProperty("OutputWorkspace", self._fit_group_name) copy_log_alg.execute() log_names = [item for item in sample_logs] log_values = [sample_logs[item] for item in sample_logs] conclusion_prog.report('Adding sample logs') add_sample_log_multi = self.createChildAlgorithm("AddSampleLogMultiple", enableLogging=False) add_sample_log_multi.setProperty("Workspace", result_workspace.name()) add_sample_log_multi.setProperty("LogNames", log_names) add_sample_log_multi.setProperty("LogValues", log_values) add_sample_log_multi.execute() add_sample_log_multi.setProperty("Workspace", self._fit_group_name) add_sample_log_multi.setProperty("LogNames", log_names) add_sample_log_multi.setProperty("LogValues", log_values) add_sample_log_multi.execute() delete_alg = self.createChildAlgorithm("DeleteWorkspace", enableLogging=False) delete_alg.setProperty("Workspace", tmp_fit_workspace) delete_alg.execute() if self._do_extract_members: ms.ExtractQENSMembers(InputWorkspace=self._input_ws, ResultWorkspace=self._fit_group_name, OutputWorkspace=self._fit_group_name.rsplit('_', 1)[0] + "_Members") self.setProperty('OutputResultWorkspace', result_workspace) self.setProperty('OutputParameterWorkspace', self._parameter_name) self.setProperty('OutputWorkspaceGroup', self._fit_group_name) conclusion_prog.report('Algorithm complete')
def mainExec(self): """ Main execution body """ # Load data optionally if self.loaddata is True: # Load data file api.LoadAscii(Filename=self.datafilename, OutputWorkspace=self.datawsname, Unit='TOF') # Load .irf file and .hkl file optionally if self.loadinfofile is True: if dir(self).count('latticesize') == 0 or self.latticesize is None: raise NotImplementedError( "Lattice size is not defined. Unable to use option 'LoadInfo'" ) api.CreateLeBailFitInput( FullprofParameterFile=self.irffilename, MaxHKL=[13, 13, 13], LatticeConstant=float(self.latticesize), Bank=self.bankid, GenerateBraggReflections=True, InstrumentParameterWorkspace=str(self.inputparamws), BraggPeakParameterWorkspace=str(self.inputbraggws)) # Process background optionally if self.process_bkgd is True: # [Background] # Remove peaks and get pure background (hopefully) api.ProcessBackground(Options='SelectBackgroundPoints', InputWorkspace=self.dataws, OutputWorkspace=self.bkgdwsname, LowerBound=self.startx, UpperBound=self.endx, BackgroundType=self.backgroundtype, BackgroundPoints=self.usrbkgdpoints, NoiseTolerance='0.10000000000000001') # Fit background points functionstr = "name=%s,n=%d" % (self.backgroundtype, self.backgroundorder) for iborder in range(self.backgroundorder + 1): functionstr = "%s,A%d=%.5f" % (functionstr, iborder, 0.0) api.Fit(Function=functionstr, InputWorkspace=self.bkgdwsname, Output=self.bkgdwsname, MaxIterations='1000', Minimizer='Levenberg-MarquardtMD', CreateOutput='1', StartX=self.startx, EndX=self.endx) # [Le Bail calculation] self.log().debug("Fit range: %f , %f, Outputworkspace = %s" % (self.startx, self.endx, self.outwsname)) api.LeBailFit( Function='Calculation', InputWorkspace=self.dataws, OutputWorkspace=self.outwsname, InputParameterWorkspace=self.inputparamws, OutputParameterWorkspace=str(self.inputparamws), InputHKLWorkspace=self.inputbraggws, OutputPeaksWorkspace=str(self.inputbraggws), FitRegion='%f, %f' % (self.startx, self.endx), BackgroundType=self.backgroundtype, UseInputPeakHeights=False, PeakRadius='7', BackgroundParametersWorkspace=self.bkgdtablews, PeakType=self.profiletype, ) return
def do_fitting_benchmark_one_problem(prob, minimizers, use_errors=True, count=0, previous_name="none"): """ One problem with potentially several starting points, returns a list (start points) of lists (minimizers). @param prob :: fitting problem @param minimizers :: list of minimizers to evaluate/compare @param use_errors :: whether to use observational errors when evaluating accuracy (in the cost function) @param count :: the current count for the number of different start values for a given problem """ wks, cost_function = prepare_wks_cost_function(prob, use_errors) # Each NIST problem generate two results per file - from two different starting points results_fit_problem = [] # Get function definitions for the problem - one for each starting point function_defs = get_function_definitions(prob) # search for lowest chi2 min_sum_err_sq = 1.e20 # Loop over the different starting points for user_func in function_defs: results_problem_start = [] for minimizer_name in minimizers: t_start = time.clock() status, chi2, fit_wks, params, errors = run_fit( wks, prob, function=user_func, minimizer=minimizer_name, cost_function=cost_function) t_end = time.clock() print("*** with minimizer {0}, Status: {1}, chi2: {2}".format( minimizer_name, status, chi2)) print(" params: {0}, errors: {1}".format(params, errors)) def sum_of_squares(values): return np.sum(np.square(values)) if fit_wks: sum_err_sq = sum_of_squares(fit_wks.readY(2)) # print " output simulated values: {0}".format(fit_wks.readY(1)) if sum_err_sq < min_sum_err_sq: tmp = msapi.ConvertToPointData(fit_wks) best_fit = data(minimizer_name, tmp.readX(1), tmp.readY(1)) min_sum_err_sq = sum_err_sq else: sum_err_sq = float("inf") print(" WARNING: no output fit workspace") print(" sum sq: {0}".format(sum_err_sq)) result = test_result.FittingTestResult() result.problem = prob result.fit_status = status result.fit_chi2 = chi2 result.params = params result.errors = errors result.sum_err_sq = sum_err_sq # If the fit has failed, also set the runtime to NaN result.runtime = t_end - t_start if not np.isnan(chi2) else np.nan print("Result object: {0}".format(result)) results_problem_start.append(result) results_fit_problem.append(results_problem_start) # make plots fig = plot() best_fit.markers = '' best_fit.linestyle = '-' best_fit.colour = 'green' best_fit.order_data() fig.add_data(best_fit) tmp = msapi.ConvertToPointData(wks) xData = tmp.readX(0) yData = tmp.readY(0) eData = tmp.readE(0) raw = data("Data", xData, yData, eData) raw.showError = True raw.linestyle = '' fig.add_data(raw) fig.labels['y'] = "Arbitrary units" fig.labels['x'] = "Time ($\mu s$)" if prob.name == previous_name: count += 1 else: count = 1 previous_name = prob.name #fig.labels['y']="something " fig.labels['title'] = prob.name[:-4] + " " + str(count) fig.title_size = 10 fit_result = msapi.Fit(user_func, wks, Output='ws_fitting_test', Minimizer='Levenberg-Marquardt', CostFunction='Least squares', IgnoreInvalidData=True, StartX=prob.start_x, EndX=prob.end_x, MaxIterations=0) tmp = msapi.ConvertToPointData(fit_result.OutputWorkspace) xData = tmp.readX(1) yData = tmp.readY(1) startData = data("Start Guess", xData, yData) startData.order_data() startData.colour = "blue" startData.markers = '' startData.linestyle = "-" start_fig = plot() start_fig.add_data(raw) start_fig.add_data(startData) start_fig.labels['x'] = "Time ($\mu s$)" start_fig.labels['y'] = "Arbitrary units" title = user_func[27:-1] title = splitByString(title, 30) # remove the extension (e.g. .nxs) if there is one run_ID = prob.name k = -1 k = run_ID.rfind(".") if k != -1: run_ID = run_ID[:k] start_fig.labels['title'] = run_ID + " " + str(count) + "\n" + title start_fig.title_size = 10 fig.make_scatter_plot("Fit for " + run_ID + " " + str(count) + ".pdf") start_fig.make_scatter_plot("start for " + run_ID + " " + str(count) + ".pdf") return results_fit_problem
"WorkspaceIndex": str(wi), "StartX": str(-4.95), "EndX": str(4.95) }) else: domain_model.update({ "InputWorkspace_" + str(wi): 'QENS_data', "WorkspaceIndex_" + str(wi): str(wi), "StartX_" + str(wi): str(minE), "EndX_" + str(wi): str(maxE) }) # Perform fitting mapi.Fit(Function=global_model, **domain_model, CreateOutput=True, MaxIteractions=500, Output='fit') """ As a result of the fit, three workspaces are created: 'fit'+"_Parameters" : optimized parameters and Chi-square 'fit'+"_NormalisedCovarianceMatrix" : correlations between parameters 'fit'+"_Workspace" : data, fit, residuals, and model """ paramTable = mapi.mtd['fit_Parameters'] # print results for i in range(4): print(f'Workspace {i}:') print(f'scale: {paramTable.column(1)[3 * i]:.2f}')