Skip to content

Commit

Permalink
Add Example1DFunction. Refs #970
Browse files Browse the repository at this point in the history
  • Loading branch information
martyngigg committed Apr 19, 2013
1 parent d28ca82 commit f0b0b13
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"""
This example implements a simple Linear function that could be used as a background.
It uses the generic concept of a 1D function, which has no concept that the function
may have a peak-like attributes such as a centre, width or fwhm. If your function can be defined
to have meaningful concepts such as this then see ExamplePeakFunction.
1D functions do not have to have a derivative defined, if they do not then they will use a numerical
derivative
"""
from mantid.api import IFunction1D, FunctionFactory
from mantid import logger
import math
import numpy as np

class Example1DFunction(IFunction1D):

def category(self):
"""
Optional method to return the category that this
function should be listed under. Multiple categories
should be separated with a semi-colon(;). Sub-categories
can be specified using a \\ separator, e.g. Category\\Sub-category
"""
return "Examples"

def init(self):
"""
Declare parameters that participate in the fitting (declareParameter)
and attributes that are constants to be passed (declareAttribute) in
and do not participate in the fit. Attributes must have type=int,float,string,bool
See ExamplePeakFunction for more on attributes
"""
# Active fitting parameters
self.declareParameter("A0")
self.declareParameter("A1")

def function1D(self, xvals):
"""
Computes the function on the set of values given and returns
the answer as a numpy array of floats
"""
return self.getParameterValue("A0") + self.getParameterValue("A1")*xvals

def functionDeriv1D(self, xvals, jacobian):
"""
Computes the partial derivatives of the function on the set of values given
and the sets these values in the given jacobian. The Jacobian is essentially
a matrix where jacobian.set(iy,ip,value) takes 3 parameters:
iy = The index of the data value whose partial derivative this corresponds to
ip = The index of the parameter value whose partial derivative this corresponds to
value = The value of the derivative
"""
i = 0
for x in xvals:
jacobian.set(i,0,1);
jacobian.set(i,1,x);
i += 1

# Required to have Mantid recognise the new function
FunctionFactory.subscribe(Example1DFunction)
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
##

set ( TEST_PY_FILES
Example1DFunctionTest.py
ExamplePeakFunctionTest.py
)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import unittest
from mantid.kernel import *
from mantid.api import *
from mantid.simpleapi import Fit
import testhelpers

class _InternalMakeLinear(PythonAlgorithm):

def PyInit(self):
self.declareProperty("A0", -1.0, validator=FloatBoundedValidator(lower=0))
self.declareProperty("A1", -1.0, validator=FloatBoundedValidator(lower=0))
self.declareProperty(MatrixWorkspaceProperty("OutputWorkspace", "", direction = Direction.Output))

def PyExec(self):
import random
nbins=4000

wspace = WorkspaceFactory.create("Workspace2D",NVectors=1,XLength=nbins,YLength=nbins)

a0 = self.getProperty("A0").value
a1 = self.getProperty("A1").value

# Noise parameter
amplitude = 100

prog_reporter = Progress(self,start=0.0,end=1.0,nreports=nbins)
for i in range(0,nbins):
x_value = 5.0 + 5.5*i;
nominal_y = a0 +a1*x_value
# add some noise
nominal_y += random.random()*amplitude

wspace.dataX(0)[i] = x_value
wspace.dataY(0)[i] = nominal_y
wspace.dataE(0)[i] = 1
prog_reporter.report("Setting %dth bin in workspace" % (i-1))

self.setProperty("OutputWorkspace", wspace) # Stores the workspace as the given name

class Example1DFunctionTest(unittest.TestCase):

def test_function_has_been_registered(self):
try:
FunctionFactory.createFunction("ExamplePeakFunction")
except RuntimeError, exc:
self.fail("Could not create ExamplePeakFunction function: %s" % str(exc))

def test_fit_succeeds_with_expected_answer(self):
AlgorithmFactory.subscribe(_InternalMakeLinear)
alg = testhelpers.run_algorithm("_InternalMakeLinear", A0=1.0,A1=0.75,OutputWorkspace='_test_linear')
input_ws = alg.getProperty("OutputWorkspace").value

func_string="name=Example1DFunction,A0=0.0,A1=0.0"
Fit(Function=func_string,InputWorkspace="_test_linear",StartX=1000,EndX=6000,CreateOutput=1,MaxIterations=2)

mtd.remove('_test_linear')
mtd.remove('_test_linear_NormalisedCovarianceMatrix')
mtd.remove('_test_linear_Parameters')
mtd.remove('_test_linear_Workspace')

if __name__ == '__main__':
unittest.main()

0 comments on commit f0b0b13

Please sign in to comment.