Skip to content

Commit

Permalink
Merge 32b8230 into a8f13ce
Browse files Browse the repository at this point in the history
  • Loading branch information
AtomAnu committed Aug 1, 2019
2 parents a8f13ce + 32b8230 commit 049e2b0
Show file tree
Hide file tree
Showing 19 changed files with 369 additions and 51 deletions.
5 changes: 3 additions & 2 deletions example_scripts/example_runScripts.py
Expand Up @@ -76,8 +76,9 @@
# "Muon_data" works for mantid minimizers
# problem_sets = ["Neutron_data", "NIST/average_difficulty"]
# problem_sets = ["CUTEst", "Muon_data", "Neutron_data", "NIST/average_difficulty", "NIST/high_difficulty", "NIST/low_difficulty"]
# problem_sets = ["CUTEst", "NIST/average_difficulty", "NIST/high_difficulty", "NIST/low_difficulty"]
problem_sets = ['CUTEst']

problem_sets = ["NIST/low_difficulty"]

for sub_dir in problem_sets:
# generate group label/name used for problem set
label = sub_dir.replace('/', '_')
Expand Down
3 changes: 2 additions & 1 deletion example_scripts/example_runScripts_mantid.py
Expand Up @@ -85,7 +85,8 @@
# ADD WHICH PROBLEM SETS TO TEST AGAINST HERE
# Do this, in this example file, by selecting sub-folders in benchmark_probs_dir
# "Muon_data" works for mantid minimizers
problem_sets = ["CUTEst", "Muon_data", "Neutron_data", "NIST/average_difficulty", "NIST/high_difficulty", "NIST/low_difficulty"]
# problem_sets = ["CUTEst", "Muon_data", "Neutron_data", "NIST/average_difficulty", "NIST/high_difficulty", "NIST/low_difficulty"]
problem_sets = ['Muon_data', 'CUTEst']

for sub_dir in problem_sets:
# generate group label/name used for problem set
Expand Down
1 change: 1 addition & 0 deletions fitbenchmarking/fitbenchmark_one_problem.py
Expand Up @@ -60,6 +60,7 @@ def fitbm_one_prob(user_input, problem):
# scipy does not currently support the GEM problem
if 'GEM' in problem.name and user_input.software == 'scipy':
break

results_problem, best_fit = \
fit_one_function_def(user_input.software, problem, data_struct,
function, user_input.minimizers, cost_function)
Expand Down
9 changes: 9 additions & 0 deletions fitbenchmarking/fitting/mantid/externals.py
Expand Up @@ -39,7 +39,16 @@ def gen_func_obj(function_name, params_set):
@returns :: mantid function object that can be called in python
"""
params_set = (params_set.split(', ties'))[0]
params_set_list = params_set.split(',')

# attr_list = ''
# for param in params_set_list:
# if param.startswith('BinWidth'):
# attr_list += param + ','
# attr_list = attr_list[:-1]

exec "function_object = msapi." + function_name + "("+ params_set +")"
# exec "function_object = msapi." + function_name + "("+ attr_list +")"
return function_object


Expand Down
84 changes: 74 additions & 10 deletions fitbenchmarking/fitting/mantid/func_def.py
Expand Up @@ -26,6 +26,9 @@
from __future__ import (absolute_import, division, print_function)

from utils.logging_setup import logger
from mantid.api import *
from mantid.fitfunctions import *
import numpy as np


def function_definitions(problem):
Expand All @@ -41,22 +44,20 @@ def function_definitions(problem):

problem_type = extract_problem_type(problem)

if problem_type == 'NIST':
# NIST data requires prior formatting

if isinstance((problem.get_function())[0][0], FunctionWrapper):
function_defs = [problem.get_function()[0][0]]
elif problem_type == 'NIST':
nb_start_vals = len(problem.starting_values[0][1])
function_defs = parse_nist_function_definitions(problem, nb_start_vals)
elif problem_type == 'FitBenchmark'.upper():
# Native FitBenchmark format does not require any processing
function_defs = []
function_defs.append(problem.equation)
function_defs = parse_function_definitions(problem, nb_start_vals)
else:
raise NameError('Currently data types supported are FitBenchmark'
' and nist, data type supplied was {}'.format(problem_type))

return function_defs


def parse_nist_function_definitions(problem, nb_start_vals):
def parse_function_definitions(problem, nb_start_vals):
"""
Helper function that parses the NIST function definitions and
transforms them into a mantid-readable format.
Expand All @@ -75,11 +76,74 @@ def parse_nist_function_definitions(problem, nb_start_vals):
start_val_str += ('{0}={1},'.format(param[0], param[1][start_idx]))
# Eliminate trailing comma
start_val_str = start_val_str[:-1]
function_defs.append("name=UserFunction,Formula={0},{1}".
format(problem.equation, start_val_str))
function_defs.append("name=fitFunction,{}".
format(start_val_str))

param_names = [row[0] for row in problem.starting_values]

class fitFunction(IFunction1D):
def init(self):

for param in param_names:
self.declareParameter(param)

def function1D(self, xdata):

fit_param = np.zeros(len(param_names))
fit_param.setflags(write=1)
for param in param_names:
fit_param[param_names.index(param)] = self.getParameterValue(param)

return problem.eval_f(xdata, fit_param)

FunctionFactory.subscribe(fitFunction)

return function_defs

# def parse_fitbenchmark_function_definition(problem):
# """
#
# :param problem:
# :return:
# """
#
# function_list = (problem.equation).split(';')
# func_params_list = [(function.split(','))[1:] for function in function_list]
# formatted_param_list = ['f'+str(func_params_list.index(func_params))+'.'+param for func_params in func_params_list for param in func_params]
#
# param_names = [(param.split('='))[0] for param in formatted_param_list]
# param_values = [(param.split('='))[1] for param in formatted_param_list]
#
# class fitFunction(IFunction1D):
# def init(self):
#
# for param in param_names:
# if not param.endswith('BinWidth'):
# self.declareParameter(param)
#
# def function1D(self, xdata):
#
# fit_param = ''
# for param in param_names:
# if not param.endswith('BinWidth'):
# fit_param += param + '=' + str(self.getParameterValue(param)) +','
# fit_param = fit_param[:-1]
#
# return problem.eval_f(xdata, fit_param)
#
# FunctionFactory.subscribe(fitFunction)
#
# function_defs = []
# start_val_str = ''
# for param, value in zip(param_names, param_values):
# if not param.endswith('BinWidth'):
# start_val_str += param + '=' + str(value) + ','
# start_val_str = start_val_str[:-1]
# function_defs.append("name=fitFunction,{}".format(start_val_str))
#
# return function_defs


def extract_problem_type(problem):
"""
This function gets the problem object and figures out the problem type
Expand Down
3 changes: 2 additions & 1 deletion fitbenchmarking/fitting/mantid/main.py
Expand Up @@ -33,6 +33,7 @@
from fitting import misc
from fitting.plotting import plot_helper


MAX_FLOAT = sys.float_info.max


Expand Down Expand Up @@ -67,7 +68,6 @@ def benchmark(problem, wks_created, function, minimizers, cost_function):

return results_problem, best_fit


def fit(problem, wks_created, function, minimizer,
cost_function='Least squares'):
"""
Expand All @@ -86,6 +86,7 @@ def fit(problem, wks_created, function, minimizer,
and how much time it took for the fit to finish (float)
"""


fit_result, t_start, t_end = None, None, None
try:
ignore_invalid = get_ignore_invalid(problem, cost_function)
Expand Down
13 changes: 7 additions & 6 deletions fitbenchmarking/fitting/mantid/tests/test_func_def.py
Expand Up @@ -13,7 +13,7 @@
sys.path.insert(0, main_dir)

from fitting.mantid.func_def import function_definitions
from fitting.mantid.func_def import parse_nist_function_definitions
from fitting.mantid.func_def import parse_function_definitions

from parsing.parse_nist_data import FittingProblem as NISTFittingProblem
from parsing.parse_fitbenchmark_data import FittingProblem as FBFittingProblem
Expand Down Expand Up @@ -101,8 +101,8 @@ def test_functionDefinitions_return_NIST_functions(self):

function_defs = function_definitions(prob)
function_defs_expected = \
["name=UserFunction,Formula=b1*(1-exp(-b2*x)),b1=500.0,b2=0.0001",
"name=UserFunction,Formula=b1*(1-exp(-b2*x)),b1=250.0,b2=0.0005"]
["name=fitFunction,b1=500.0,b2=0.0001",
"name=fitFunction,b1=250.0,b2=0.0005"]

self.assertListEqual(function_defs_expected, function_defs)

Expand All @@ -111,6 +111,7 @@ def test_functionDefinitions_return_neutron_function(self):
prob = self.Neutron_problem()

function_defs = function_definitions(prob)
function_defs = [str(function_defs[0])]
function_defs_expected = \
[("name=LinearBackground,A0=0,A1=0;name=BackToBackExponential,"
"I=597.076,A=1,B=0.05,X0=24027.5,S=22.9096")]
Expand All @@ -122,10 +123,10 @@ def test_parseNistFunctionDefinitions_get_true_function(self):
prob = self.NIST_problem()
nb_start_vals = 2

function_defs = parse_nist_function_definitions(prob, nb_start_vals)
function_defs = parse_function_definitions(prob, nb_start_vals)
function_defs_expected = \
["name=UserFunction,Formula=b1*(1-exp(-b2*x)),b1=500.0,b2=0.0001",
"name=UserFunction,Formula=b1*(1-exp(-b2*x)),b1=250.0,b2=0.0005"]
["name=fitFunction,b1=500.0,b2=0.0001",
"name=fitFunction,b1=250.0,b2=0.0005"]

self.assertListEqual(function_defs_expected, function_defs)

Expand Down
4 changes: 4 additions & 0 deletions fitbenchmarking/fitting/prerequisites.py
Expand Up @@ -65,6 +65,8 @@ def prepare_mantid(problem, use_errors):

wks_mtd, cost_function = \
wks_cost_function(problem, use_errors)

# String containing the function name(s) and the starting parameter values for each function
function_definitions = \
function_definitions(problem)

Expand All @@ -85,6 +87,8 @@ def prepare_scipy(problem, use_errors):

data, cost_function = \
prepare_data(problem, use_errors)

# String containing function evaluation methods and the starting values for each method
function_definitions = function_definitions(problem)
# For problems that have no specified boundaries, set -inf and +inf
if problem.start_x == None and problem.end_x == None:
Expand Down
17 changes: 2 additions & 15 deletions fitbenchmarking/fitting/scipy/func_def.py
Expand Up @@ -26,7 +26,6 @@

import numpy as np
import re
from utils.logging_setup import logger

def function_definitions(problem):
"""
Expand All @@ -35,20 +34,8 @@ def function_definitions(problem):
"""
problem_type = extract_problem_type(problem)

if problem_type == 'NIST':
from fitting.scipy.nist_data_functions import nist_func_definitions
return nist_func_definitions(problem.equation,
problem.starting_values)
elif problem_type == 'FitBenchmark'.upper():
"""
The following import is inserted here to allow fitbenchmarking
to run independently of mantid when solving NIST problems.
FitBenchmark problems require mantid to generate problem function objects.
As mantid is imported in fitbenchmark_data_function, the script should be
imported only in the case of solving FitBenchmark problems
"""
from fitting.scipy.fitbenchmark_data_functions import fitbenchmark_func_definitions
return fitbenchmark_func_definitions(problem.equation)
if problem_type == 'NIST' or problem_type == 'FitBenchmark'.upper():
return problem.get_function()
else:
RuntimeError("Your problem type is not supported yet!")

Expand Down

0 comments on commit 049e2b0

Please sign in to comment.