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 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
Beispiel #3
0
    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_fitbenchmark_data_problem_entries()
        self._parsed_func = self._parse_function()

        fitting_problem.name = self._entries['name']

        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]

        # String containing the function name(s) and the starting parameter
        # values for each function
        self._mantid_equation = self._entries['function']

        fitting_problem.functions = self._fitbenchmark_func_definitions()

        # Print number of equations until better way of doing this is looked at
        equation_count = len(self._parsed_func)
        fitting_problem.equation = '{} Functions'.format(equation_count)

        fitting_problem.starting_values = self._get_starting_values()

        # start and end values in x range
        if 'fit_parameters' in self._entries:
            start_x, end_x = self._get_x_range()
            fitting_problem.start_x = start_x
            fitting_problem.end_x = end_x

        return fitting_problem
    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 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 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
Beispiel #7
0
    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