def test_eval_r(self): """ Test that eval_r is correct """ fitting_problem = FittingProblem() self.assertRaises(exceptions.FittingProblemError, fitting_problem.eval_r, params=[1, 2, 3], x=2) fitting_problem.function = lambda x, p1: x + p1 x_val = np.array([1, 8, 11]) y_val = np.array([6, 10, 20]) eval_result = fitting_problem.eval_r(x=x_val, y=y_val, params=[5]) self.assertTrue(all(eval_result == np.array([0, -3, 4]))) e_val = np.array([2, 4, 1]) eval_result = fitting_problem.eval_r(x=x_val, y=y_val, e=e_val, params=[5]) self.assertTrue(all(eval_result == np.array([0, -0.75, 4]))) fitting_problem.data_x = np.array([20, 21, 22]) fitting_problem.data_y = np.array([20, 30, 35]) eval_result = fitting_problem.eval_r(params=[5]) self.assertTrue(all(eval_result == np.array([-5, 4, 8]))) fitting_problem.data_e = np.array([2, 5, 10]) eval_result = fitting_problem.eval_r(params=[5]) self.assertTrue(all(eval_result == np.array([-2.5, 0.8, 0.8])))
def test_sanitised_name(self): fitting_problem = FittingProblem() expected = "test_1" fitting_problem.name = "test 1" self.assertEqual(fitting_problem.sanitised_name, expected) fitting_problem.name = "test,1" self.assertEqual(fitting_problem.sanitised_name, expected)
def generate_mock_results(): """ Generates results to test against :return: best results calculated using the chi_sq value, list of results and the options :rtype: tuple(list of best results, list of list fitting results, Options object) """ software = 'scipy_ls' options = Options() options.software = [software] num_min = len(options.minimizers[options.software[0]]) data_x = np.array([[1, 4, 5], [2, 1, 5]]) data_y = np.array([[1, 2, 1], [2, 2, 2]]) data_e = np.array([[1, 1, 1], [1, 2, 1]]) func = [fitting_function_1, fitting_function_2] problems = [FittingProblem(options), FittingProblem(options)] params_in = [[[.3, .11], [.04, 2], [3, 1], [5, 0]], [[4, 2], [3, .006], [.3, 10], [9, 0]]] starting_values = [{"a": .3, "b": .11}, {"a": 0, "b": 0}] error_in = [[1, 0, 2, 0], [0, 1, 3, 1]] link_in = [['link1', 'link2', 'link3', 'link4'], ['link5', 'link6', 'link7', 'link8']] min_chi_sq = [1, 1] acc_in = [[1, 5, 2, 1.54], [7, 3, 5, 1]] min_runtime = [4.2e-5, 5.0e-14] runtime_in = [[1e-2, 2.2e-3, 4.2e-5, 9.8e-1], [3.0e-10, 5.0e-14, 1e-7, 4.3e-12]] results_out = [] for i, p in enumerate(problems): p.data_x = data_x[i] p.data_y = data_y[i] p.data_e = data_e[i] p.function = func[i] p.name = "prob_{}".format(i) results = [] for j in range(num_min): p.starting_values = starting_values cost_func = NLLSCostFunc(p) jac = Scipy(cost_func) jac.method = '2-point' r = FittingResult(options=options, cost_func=cost_func, jac=jac, initial_params=starting_values, params=params_in[i][j]) r.chi_sq = acc_in[i][j] r.runtime = runtime_in[i][j] r.error_flag = error_in[i][j] r.support_page_link = link_in[i][j] r.minimizer = options.minimizers[software][j] results.append(r) results_out.append(results) return results_out, options, min_chi_sq, min_runtime
def setUp(self): """ Setting up nonlinear least squares cost function tests """ self.options = Options() fitting_problem = FittingProblem(self.options) self.cost_function = NLLSCostFunc(fitting_problem) fitting_problem.function = lambda x, p1: x + p1 self.x_val = np.array([1, 8, 11]) self.y_val = np.array([6, 10, 20])
def parse(self): """ Parse the NIST problem file into a Fitting Problem. :return: The fully parsed fitting problem :rtype: fitbenchmarking.parsing.fitting_problem.FittingProblem """ fitting_problem = FittingProblem() equation, data, starting_values, name = self._parse_line_by_line() data = self._parse_data(data) fitting_problem.data_x = data[:, 1] fitting_problem.data_y = data[:, 0] if len(data[0, :]) > 2: fitting_problem.data_e = data[:, 2] fitting_problem.name = name # String containing a mathematical expression fitting_problem.equation = self._parse_equation(equation) fitting_problem.starting_values = starting_values fitting_problem.function = \ nist_func_definition(function=fitting_problem.equation, param_names=starting_values[0].keys()) return fitting_problem
def test_get_function_params(self): """ Tests that the function params is formatted correctly """ fitting_problem = FittingProblem(self.options) expected_function_def = 'a=1, b=2.0, c=3.3, d=4.99999' fitting_problem.starting_values = [ OrderedDict([('a', 0), ('b', 0), ('c', 0), ('d', 0)]) ] params = [1, 2.0, 3.3, 4.99999] function_def = fitting_problem.get_function_params(params=params) self.assertEqual(function_def, expected_function_def)
def test_get_function_def(self): """ Tests that the function def is formatted correctly """ fitting_problem = FittingProblem() expected_function_def = \ 'test_function | a=1, b=2.0, c=3.3, d=4.99999999' fitting_problem.equation = 'test_function' fitting_problem.starting_values = [['a', [0]], ['b', [0]], ['c', [0]], ['d', [0]]] params = [1, 2.0, 3.3, 4.99999999] function_def = fitting_problem.get_function_def(params=params) self.assertEqual(function_def, expected_function_def)
def setUp(self): """ Setting up tests """ options = Options() options.cost_func_type = "nlls" self.fitting_problem = FittingProblem(options) self.fitting_problem.function = f self.fitting_problem.jacobian = J self.fitting_problem.data_x = np.array([1, 2, 3, 4, 5]) self.fitting_problem.data_y = np.array([1, 2, 4, 8, 16]) self.cost_func = NLLSCostFunc(self.fitting_problem) self.params = [6, 0.1] self.actual = J(x=self.fitting_problem.data_x, p=self.params)
def generate_mock_results(self): """ Generates results to test against :return: A list of results objects along with expected values for normallised accuracy and runtimes :rtype: tuple(list of FittingResults, list of list of float, list of list of float) """ self.num_problems = 4 self.num_minimizers = 2 results = [] options = Options() problem = FittingProblem(options) problem.starting_values = [{'a': 1, 'b': 2, 'c': 3}] acc_in = [[1, 5], [7, 3], [10, 8], [2, 3]] runtime_in = [[float('Inf'), 2.2e-3], [3.0e-10, 5.0e-14], [6.9e-7, 4.3e-5], [1.6e-13, 1.8e-13]] acc_expected = [] runtime_expected = [] for i in range(self.num_problems): acc_results = acc_in[i][:] acc_expected.append(list(acc_results) / np.min(acc_results)) runtime_results = runtime_in[i][:] runtime_expected.append( list(runtime_results) / np.min(runtime_results)) prob_results = [] cost_func = NLLSCostFunc(problem) jac = Scipy(cost_func) jac.method = "2-point" for j in range(self.num_minimizers): minimizer = 'min_{}'.format(j) prob_results.append( FittingResult(options=options, cost_func=cost_func, jac=jac, initial_params=[1, 2, 3], params=[1, 2, 3], chi_sq=acc_results[j], runtime=runtime_results[j], minimizer=minimizer)) results.append(prob_results) return results, acc_expected, runtime_expected
def setUp(self): self.opts = Options() self.opts.use_errors = True self.prob = FittingProblem(self.opts) self.prob.data_x = np.array([1, 2, 4, 3, 5]) self.prob.sorted_index = np.array([0, 1, 3, 2, 4]) self.prob.data_y = np.array([4, 3, 5, 2, 1]) self.prob.data_e = np.array([0.5, 0.2, 0.3, 0.1, 0.4]) self.prob.starting_values = [{'x': 1, 'y': 2}] self.prob.name = 'full name' self.prob.eval_model = lambda y, x: y[0] * x + y[1] cost_func = NLLSCostFunc(self.prob) jac = Scipy(cost_func) jac.method = "2-point" self.fr = FittingResult(options=self.opts, cost_func=cost_func, jac=jac, chi_sq=1.0, initial_params=[1.8], params=[1.2], runtime=2.0, minimizer='fit', error_flag=1) self.opts = Options() self.opts.use_errors = True self.dir = TemporaryDirectory() self.plot = plots.Plot(best_result=self.fr, options=self.opts, figures_dir=self.dir.name)
def test_eval_model_raise_error(self): """ Test that eval_model raises and error """ fitting_problem = FittingProblem(self.options) self.assertRaises(exceptions.FittingProblemError, fitting_problem.eval_model, x=2, params=[1, 2, 3])
def setUp(self): """ Setting up tests """ options = Options() options.cost_func_type = "nlls" self.fitting_problem = FittingProblem(options) self.cost_func = NLLSCostFunc(self.fitting_problem) self.jacobian = Jacobian(self.cost_func)
def setup_nist_expected_problem(self): prob = FittingProblem() prob.name = 'Misra1a' prob.equation = 'b1*(1-exp(-b2*x))' prob.starting_values = [['b1', [500.0, 250.0]], ['b2', [0.0001, 0.0005]]] data_pattern = self.setup_misra1a_expected_data_points() prob.data_x = data_pattern[:, 1] prob.data_y = data_pattern[:, 0] prob.ref_residual_sum_sq = 1.2455138894e-01 return prob
def parse(self): """ Get data into a Fitting Problem via cutest. :return: The fully parsed fitting problem :rtype: fitbenchmarking.parsing.fitting_problem.FittingProblem """ self.mastsif_dir = TemporaryDirectory() # set the MASTSIF environment variable so that pycutest # can find the sif files os.environ["MASTSIF"] = self.mastsif_dir.name self._num_params = None # get just the short filename (minus the .SIF) fp = FittingProblem(self.options) # Collect x and create new file with blank y fname, fp.data_x, fp.data_y, fp.data_e = self._setup_data() self._p = _import_problem(fname) fp.name = self._p.name fp.function = self._function # self._p.objcons fp.jacobian = self._jacobian # self._p.lagjac fp.equation = None fp.starting_values = self._get_starting_values() fp.start_x = None fp.end_x = None fp.format = "cutest" # Create a list of x and f (function evaluation) and x and g (Jacobian # evaluation). # If a new x is given we will create and parse a new file self._cache_f = [(fp.data_x, self._p.objcons)] self._cache_g = [(fp.data_x, self._p.lagjac)] return fp
def test_eval_model_correct_evaluation(self): """ Test that eval_model is running the correct function """ fitting_problem = FittingProblem(self.options) fitting_problem.function = lambda x, p1: x + p1 x_val = np.array([1, 8, 11]) eval_result = fitting_problem.eval_model(x=x_val, params=[5]) self.assertTrue(all(eval_result == np.array([6, 13, 16]))) fitting_problem.data_x = np.array([20, 21, 22]) eval_result = fitting_problem.eval_model(params=[5]) self.assertTrue(all(eval_result == np.array([25, 26, 27])))
def parse(self): fitting_problem = FittingProblem() equation, data, starting_values, name = self._parse_line_by_line() data = self._parse_data(data) fitting_problem.data_x = data[:, 1] fitting_problem.data_y = data[:, 0] if len(data[0, :]) > 2: fitting_problem.data_e = data[:, 2] fitting_problem.name = name # String containing a mathematical expression fitting_problem.equation = self._parse_equation(equation) fitting_problem.starting_values = starting_values fitting_problem.functions = \ nist_func_definitions(function=fitting_problem.equation, startvals=fitting_problem.starting_values) return fitting_problem
def test_eval_starting_params(self): """ Test that eval_starting_params returns the correct result """ fitting_problem = FittingProblem() self.assertRaises(exceptions.FittingProblemError, fitting_problem.eval_starting_params, param_set=0) fitting_problem.function = lambda x, p1: x + p1 fitting_problem.starting_values = [ OrderedDict([('p1', 3)]), OrderedDict([('p1', 7)]) ] fitting_problem.data_x = np.array([1]) eval_result = fitting_problem.eval_starting_params(0) self.assertTrue(all(eval_result == np.array([4]))) eval_result = fitting_problem.eval_starting_params(1) self.assertTrue(all(eval_result == np.array([8])))
def test_eval_starting_params(self): """ Test that eval_starting_params returns the correct result """ fitting_problem = FittingProblem() self.assertRaises(AttributeError, fitting_problem.eval_starting_params, function_id=0) fitting_problem.functions = [[lambda x, p1: x + p1, [3]], [lambda x, p1: x + p1 + 10, [7]]] fitting_problem.data_x = np.array([1]) eval_result = fitting_problem.eval_starting_params(0) self.assertTrue(all(eval_result == np.array([4]))) eval_result = fitting_problem.eval_starting_params(1) self.assertTrue(all(eval_result == np.array([18])))
def test_eval_r_norm(self): """ Test that eval_r_norm is correct """ fitting_problem = FittingProblem() fitting_problem.function = lambda x, p1: x + p1 x_val = np.array([1, 8, 11]) y_val = np.array([6, 10, 20]) e_val = np.array([0.5, 10, 0.1]) eval_result = fitting_problem.eval_r_norm(params=[5], x=x_val, y=y_val, e=e_val) self.assertEqual(eval_result, 1600.09) fitting_problem.data_x = x_val fitting_problem.data_y = y_val eval_result = fitting_problem.eval_r_norm(params=[5]) self.assertEqual(eval_result, 25)
def test_eval_f(self): """ Test that eval_f is running the correct function """ fitting_problem = FittingProblem() self.assertRaises(exceptions.FittingProblemError, fitting_problem.eval_f, x=2, params=[1, 2, 3]) fitting_problem.function = lambda x, p1: x + p1 x_val = np.array([1, 8, 11]) eval_result = fitting_problem.eval_f(x=x_val, params=[5]) self.assertTrue(all(eval_result == np.array([6, 13, 16]))) fitting_problem.data_x = np.array([20, 21, 22]) eval_result = fitting_problem.eval_f(params=[5]) self.assertTrue(all(eval_result == np.array([25, 26, 27])))
def test_eval_j(self): """ Test that eval_j is correct """ def f(x, p1, p2): return p1 * np.exp(p2 * x) def J(x, p): return np.column_stack( (-np.exp(p[1] * x), -x * p[0] * np.exp(p[1] * x))) fitting_problem = FittingProblem() fitting_problem.function = f fitting_problem.data_x = np.array([1, 2, 3, 4, 5]) fitting_problem.data_y = np.array([1, 2, 4, 8, 16]) params = [6, 0.1] eval_result = fitting_problem.eval_j(params=params) actual = J(x=fitting_problem.data_x, p=params) self.assertTrue(np.isclose(actual, eval_result).all())
def test_eval_f(self): """ Test that eval_f is running the correct function """ fitting_problem = FittingProblem() self.assertRaises(AttributeError, fitting_problem.eval_f, x=2, params=[1, 2, 3], function_id=0) fitting_problem.functions = [[lambda x, p1: x + p1, [3]], [lambda x, p1: x + p1 + 10, [7]]] x_val = np.array([1]) eval_result = fitting_problem.eval_f(x=x_val, params=[5], function_id=0) self.assertTrue(all(eval_result == np.array([6]))) eval_result = fitting_problem.eval_f(x=x_val, params=[5], function_id=1) self.assertTrue(all(eval_result == np.array([16]))) fitting_problem.data_x = np.array([20, 21, 22]) eval_result = fitting_problem.eval_f(params=[5], function_id=0) self.assertTrue(all(eval_result == np.array([25, 26, 27])))
def test_correct_data_single_fit(self): """ Tests that correct data gives the expected result """ fitting_problem = FittingProblem(self.options) x_data = np.array([-0.5, 0.0, 1.0, 0.5, 1.5, 2.0, 2.5, 3.0, 4.0]) y_data = np.array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]) e_data = np.array([1.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 9.0]) start_x = 0.5 end_x = 2.5 expected_x_data = np.array([0.5, 1.0, 1.5, 2.0, 2.5]) expected_y_data = np.array([3.0, 2.0, 4.0, 5.0, 6.0]) expected_e_data = np.array([40.0, 30.0, 50.0, 60.0, 70.0]) fitting_problem.data_x = x_data fitting_problem.data_y = y_data fitting_problem.data_e = e_data fitting_problem.start_x = start_x fitting_problem.end_x = end_x fitting_problem.correct_data() self.assertTrue( np.isclose(fitting_problem.data_x[fitting_problem.sorted_index], expected_x_data).all()) self.assertTrue( np.isclose(fitting_problem.data_y[fitting_problem.sorted_index], expected_y_data).all()) self.assertTrue( np.isclose(fitting_problem.data_e[fitting_problem.sorted_index], expected_e_data).all()) self.options.cost_func_type = "nlls" fitting_problem.correct_data() self.assertTrue( np.isclose(fitting_problem.data_x[fitting_problem.sorted_index], expected_x_data).all()) self.assertTrue( np.isclose(fitting_problem.data_y[fitting_problem.sorted_index], expected_y_data).all()) self.assertIs(fitting_problem.data_e, None)
def parse(self): """ Parse the Fitbenchmark problem file into a Fitting Problem. :return: The fully parsed fitting problem :rtype: fitbenchmarking.parsing.fitting_problem.FittingProblem """ fitting_problem = FittingProblem() self._entries = self._get_data_problem_entries() software = self._entries['software'].lower() if not (software in import_success and import_success[software][0]): e = import_success[software][1] raise MissingSoftwareError('Requirements are missing for {} parser' ': {}'.format(software, e)) self._parsed_func = self._parse_function() # NAME fitting_problem.name = self._entries['name'] # DATA data_points = self._get_data_points() fitting_problem.data_x = data_points[:, 0] fitting_problem.data_y = data_points[:, 1] if data_points.shape[1] > 2: fitting_problem.data_e = data_points[:, 2] # FUNCTION if software == 'mantid': fitting_problem.function = self._create_mantid_function() elif software == 'sasview': fitting_problem.function = self._create_sasview_function() # EQUATION equation_count = len(self._parsed_func) if equation_count == 1: fitting_problem.equation = self._parsed_func[0]['name'] else: fitting_problem.equation = '{} Functions'.format(equation_count) if software == 'mantid': # String containing the function name(s) and the starting parameter # values for each function fitting_problem._mantid_equation = self._entries['function'] # STARTING VALUES fitting_problem.starting_values = self._get_starting_values() # PARAMETER RANGES vr = self._parse_range('parameter_ranges') fitting_problem.value_ranges = vr if vr != {} else None # FIT RANGES fit_ranges = self._parse_range('fit_ranges') try: fitting_problem.start_x = fit_ranges['x'][0] fitting_problem.end_x = fit_ranges['x'][1] except KeyError: pass return fitting_problem
class TestJacobianClass(TestCase): """ Tests for Jacobian classes """ def setUp(self): """ Setting up tests """ options = Options() options.cost_func_type = "nlls" self.fitting_problem = FittingProblem(options) self.fitting_problem.function = f self.fitting_problem.jacobian = J self.fitting_problem.data_x = np.array([1, 2, 3, 4, 5]) self.fitting_problem.data_y = np.array([1, 2, 4, 8, 16]) self.cost_func = NLLSCostFunc(self.fitting_problem) self.params = [6, 0.1] self.actual = J(x=self.fitting_problem.data_x, p=self.params) def test_scipy_two_point_eval(self): """ Test for ScipyTwoPoint evaluation is correct """ jac = Scipy(self.cost_func) jac.method = '2-point' eval_result = jac.eval(params=self.params) self.assertTrue(np.isclose(self.actual, eval_result).all()) def test_scipy_three_point_eval(self): """ Test for ScipyThreePoint evaluation is correct """ jac = Scipy(self.cost_func) jac.method = '3-point' eval_result = jac.eval(params=self.params) self.assertTrue(np.isclose(self.actual, eval_result).all()) def test_scipy_cs_eval(self): """ Test for ScipyCS evaluation is correct """ jac = Scipy(self.cost_func) jac.method = 'cs' eval_result = jac.eval(params=self.params) self.assertTrue(np.isclose(self.actual, eval_result).all()) def test_analytic_cutest_no_errors(self): """ Test analytic Jacobian """ self.fitting_problem.options.cost_func_type = "nlls" self.fitting_problem.format = "cutest" jac = Analytic(self.cost_func) eval_result = jac.eval(params=self.params) self.assertTrue(np.isclose(self.actual, eval_result).all()) def test_analytic_cutest_weighted(self): """ Test analytic Jacobian """ self.fitting_problem.options.cost_func_type = "weighted_nlls" e = np.array([1, 2, 1, 3, 1]) self.fitting_problem.data_e = e self.fitting_problem.format = "cutest" jac = Analytic(self.cost_func) eval_result = jac.eval(params=self.params) scaled_actual = self.actual / e[:, None] self.assertTrue(np.isclose(scaled_actual, eval_result).all()) def test_analytic_cutest_root(self): """ Test analytic Jacobian """ self.fitting_problem.options.cost_func_type = "root_nlls" self.fitting_problem.format = "cutest" jac = Analytic(self.cost_func) eval_result = jac.eval(params=self.params) scaled_actual = self.actual * \ self.fitting_problem.eval_model(self.params)[:, None] / 2 self.assertTrue(np.isclose(scaled_actual, eval_result).all()) def test_analytic_raise_error(self): """ Test analytic Jacobian raises an exception when problem.jacobian is not callable """ self.fitting_problem.jacobian = None with self.assertRaises(exceptions.NoJacobianError): Analytic(self.cost_func)
def parse(self): """ Parse the NIST problem file into a Fitting Problem. :return: The fully parsed fitting problem :rtype: fitbenchmarking.parsing.fitting_problem.FittingProblem """ fitting_problem = FittingProblem(self.options) equation, data, starting_values, name = self._parse_line_by_line() data = self._parse_data(data) fitting_problem.data_x = data[:, 1] fitting_problem.data_y = data[:, 0] if len(data[0, :]) > 2: fitting_problem.data_e = data[:, 2] fitting_problem.name = name # String containing a mathematical expression fitting_problem.equation = self._parse_equation(equation) fitting_problem.starting_values = starting_values fitting_problem.function = \ nist_func_definition(function=fitting_problem.equation, param_names=starting_values[0].keys()) fitting_problem.format = "nist" try: jacobian = self._parse_jacobian(name) fitting_problem.jacobian = \ nist_jacobian_definition(jacobian=jacobian, param_names=starting_values[0].keys()) except NoJacobianError: LOGGER.warn("WARNING: Could not find analytic Jacobian " "information for {} problem".format(name)) return fitting_problem
def load_expectation(filename): """ Load an expected fitting problem from a json file. :param filename: The path to the expectation file :type filename: string :return: A fitting problem to test against :rtype: fitbenchmarking.parsing.FittingProblem """ with open(filename, 'r') as f: expectation_dict = load(f) expectation = FittingProblem(OPTIONS) expectation.name = expectation_dict['name'] expectation.start_x = expectation_dict['start_x'] expectation.end_x = expectation_dict['end_x'] expectation.data_x = np.array(expectation_dict['data_x']) expectation.data_y = np.array(expectation_dict['data_y']) expectation.data_e = expectation_dict['data_e'] if expectation.data_e is not None: expectation.data_e = np.array(expectation.data_e) expectation.starting_values = expectation_dict['starting_values'] expectation.value_ranges = expectation_dict['value_ranges'] return expectation
def test_correct_data_multi_fit(self): """ Tests correct data on a multifit problem. """ fitting_problem = FittingProblem(self.options) fitting_problem.multifit = True x_data = [ np.array([-0.5, 0.0, 1.0, 0.5, 1.5, 2.0, 2.5, 3.0, 4.0]), np.array([-0.5, 0.0, 1.0, 0.5, 1.4, 2.0, 2.5, 3.0, 4.0]), np.array([-0.5, 0.0, 1.0, 0.5, 1.7, 2.0, 2.5, 3.0, 4.0]) ] y_data = [ np.array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]), np.array([0.0, 1.0, 2.0, 3.0, 24.0, 5.0, 6.0, 7.0, 8.0]), np.array([0.0, 1.0, 2.8, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]) ] e_data = [ np.array([1.0, 20.0, 30.0, 40.0, 50.0, 60.0, 1.0, 6.0, 9.0]), np.array([1.0, 20.0, 30.0, 40.0, 50.0, 60.0, 1.0, 6.0, 9.0]), np.array([1.0, 20.0, 30.0, 40.0, 50.0, 60.0, 1.0, 6.0, 9.0]) ] start_x = [0.5, 1.1, 0.0] end_x = [2.5, 2.6, 1.0] expected_x_data = [ np.array([0.5, 1.0, 1.5, 2.0, 2.5]), np.array([1.4, 2.0, 2.5]), np.array([0.0, 0.5, 1.0]) ] expected_y_data = [ np.array([3.0, 2.0, 4.0, 5.0, 6.0]), np.array([24.0, 5.0, 6.0]), np.array([1.0, 3.0, 2.8]) ] expected_e_data = [ np.array([40.0, 30.0, 50.0, 60.0, 1.0]), np.array([50.0, 60.0, 1.0]), np.array([20.0, 40.0, 30.0]) ] fitting_problem.data_x = x_data fitting_problem.data_y = y_data fitting_problem.data_e = e_data fitting_problem.start_x = start_x fitting_problem.end_x = end_x fitting_problem.correct_data() for i in range(3): self.assertTrue( np.isclose( fitting_problem.data_x[i][fitting_problem.sorted_index[i]], expected_x_data[i]).all()) self.assertTrue( np.isclose( fitting_problem.data_y[i][fitting_problem.sorted_index[i]], expected_y_data[i]).all()) self.assertTrue( np.isclose( fitting_problem.data_e[i][fitting_problem.sorted_index[i]], expected_e_data[i]).all()) self.options.cost_func_type = "nlls" fitting_problem.correct_data() for i in range(3): self.assertTrue( np.isclose( fitting_problem.data_x[i][fitting_problem.sorted_index[i]], expected_x_data[i]).all()) self.assertTrue( np.isclose( fitting_problem.data_y[i][fitting_problem.sorted_index[i]], expected_y_data[i]).all()) self.assertIs(fitting_problem.data_e[i], None)
def test_verify_problem(self): """ Test that verify only passes if all required values are set. """ fitting_problem = FittingProblem(self.options) with self.assertRaises(exceptions.FittingProblemError): fitting_problem.verify() self.fail('verify() passes when no values are set.') fitting_problem.starting_values = [OrderedDict([('p1', 1), ('p2', 2)])] with self.assertRaises(exceptions.FittingProblemError): fitting_problem.verify() self.fail('verify() passes starting values are set.') fitting_problem.data_x = np.array([1, 2, 3, 4, 5]) with self.assertRaises(exceptions.FittingProblemError): fitting_problem.verify() self.fail('verify() passes when data_x is set.') fitting_problem.data_y = np.array([1, 2, 3, 4, 5]) with self.assertRaises(exceptions.FittingProblemError): fitting_problem.verify() self.fail('verify() passes when data_y is set.') fitting_problem.function = lambda x, p1, p2: p1 + p2 try: fitting_problem.verify() except exceptions.FittingProblemError: self.fail('verify() fails when all required values set.') fitting_problem.data_x = [1, 2, 3] with self.assertRaises(exceptions.FittingProblemError): fitting_problem.verify() self.fail('verify() passes for x values not numpy.')
def parse(self): """ Parse the Fitbenchmark problem file into a Fitting Problem. :return: The fully parsed fitting problem :rtype: fitbenchmarking.parsing.fitting_problem.FittingProblem """ # pylint: disable=attribute-defined-outside-init fitting_problem = FittingProblem(self.options) self._entries = self._get_data_problem_entries() software = self._entries['software'].lower() if not (software in import_success and import_success[software][0]): error = import_success[software][1] raise MissingSoftwareError('Requirements are missing for {} parser' ': {}'.format(software, error)) self._parsed_func = self._parse_function() if software == 'mantid' and self._entries['input_file'][0] == '[': fitting_problem.multifit = True # NAME fitting_problem.name = self._entries['name'] # DATA data_points = [_get_data_points(p) for p in self._get_data_file()] # FUNCTION if software == 'mantid': fitting_problem.function = self._create_mantid_function() fitting_problem.format = 'mantid' elif software == 'sasview': fitting_problem.function = self._create_sasview_function() fitting_problem.format = 'sasview' # EQUATION equation_count = len(self._parsed_func) if equation_count == 1: fitting_problem.equation = self._parsed_func[0]['name'] else: fitting_problem.equation = '{} Functions'.format(equation_count) # STARTING VALUES fitting_problem.starting_values = self._get_starting_values() # PARAMETER RANGES vr = _parse_range(self._entries.get('parameter_ranges', '')) fitting_problem.value_ranges = vr if vr != {} else None # FIT RANGES fit_ranges_str = self._entries.get('fit_ranges', '') # this creates a list of strs like '{key: val, ...}' and parses each fit_ranges = [ _parse_range('{' + r.split('}')[0] + '}') for r in fit_ranges_str.split('{')[1:] ] if fitting_problem.multifit: num_files = len(data_points) fitting_problem.data_x = [d[:, 0] for d in data_points] fitting_problem.data_y = [d[:, 1] for d in data_points] fitting_problem.data_e = [ d[:, 2] if d.shape[1] > 2 else None for d in data_points ] if not fit_ranges: fit_ranges = [{} for _ in range(num_files)] fitting_problem.start_x = [ f['x'][0] if 'x' in f else None for f in fit_ranges ] fitting_problem.end_x = [ f['x'][1] if 'x' in f else None for f in fit_ranges ] else: fitting_problem.data_x = data_points[0][:, 0] fitting_problem.data_y = data_points[0][:, 1] if data_points[0].shape[1] > 2: fitting_problem.data_e = data_points[0][:, 2] if fit_ranges and 'x' in fit_ranges[0]: fitting_problem.start_x = fit_ranges[0]['x'][0] fitting_problem.end_x = fit_ranges[0]['x'][1] if software == 'mantid': # String containing the function name(s) and the starting parameter # values for each function. fitting_problem.additional_info['mantid_equation'] \ = self._entries['function'] if fitting_problem.multifit: fitting_problem.additional_info['mantid_ties'] \ = self._parse_ties() return fitting_problem