diff --git a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/TabulatedFunction.h b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/TabulatedFunction.h index 6cfeac21f3cc..4a74e6fc2346 100644 --- a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/TabulatedFunction.h +++ b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/TabulatedFunction.h @@ -102,7 +102,7 @@ class DLLExport TabulatedFunction : public API::ParamFunction, void clear() const; /// Evaluate the function for a list of arguments and given scaling factor - void eval(double scaling, double shift, double *out, const double *xValues, + void eval(double scaling, double shift, double xscale, double *out, const double *xValues, const size_t nData) const; /// Fill in the x and y value containers (m_xData and m_yData) diff --git a/Code/Mantid/Framework/CurveFitting/src/TabulatedFunction.cpp b/Code/Mantid/Framework/CurveFitting/src/TabulatedFunction.cpp index 2a0520aa2b7d..7b102d1427e3 100644 --- a/Code/Mantid/Framework/CurveFitting/src/TabulatedFunction.cpp +++ b/Code/Mantid/Framework/CurveFitting/src/TabulatedFunction.cpp @@ -30,13 +30,14 @@ const int TabulatedFunction::defaultIndexValue = 0; TabulatedFunction::TabulatedFunction() : m_setupFinished(false) { declareParameter("Scaling", 1.0, "A scaling factor"); declareParameter("Shift", 0.0, "Shift in the abscissa"); + declareParameter("XScaling", 1.0, "Scaling factor in X"); declareAttribute("FileName", Attribute("", true)); declareAttribute("Workspace", Attribute("")); declareAttribute("WorkspaceIndex", Attribute(defaultIndexValue)); } /// Evaluate the function for a list of arguments and given scaling factor -void TabulatedFunction::eval(double scaling, double xshift, double *out, +void TabulatedFunction::eval(double scaling, double xshift, double xscale, double *out, const double *xValues, const size_t nData) const { if (nData == 0) return; @@ -46,10 +47,11 @@ void TabulatedFunction::eval(double scaling, double xshift, double *out, if (size() == 0) return; - // shift the domain over which the function is defined + // shift and scale the domain over which the function is defined std::vector xData(m_xData); for (std::vector::iterator it = xData.begin(); it != xData.end(); ++it) { + *it *= xscale; *it += xshift; } @@ -100,7 +102,8 @@ void TabulatedFunction::function1D(double *out, const double *xValues, const size_t nData) const { const double scaling = getParameter("Scaling"); const double xshift = getParameter("Shift"); - eval(scaling, xshift, out, xValues, nData); + const double xscale = getParameter("XScaling"); + eval(scaling, xshift, xscale, out, xValues, nData); } /** @@ -115,24 +118,32 @@ void TabulatedFunction::functionDeriv1D(API::Jacobian *out, const size_t nData) { const double scaling = getParameter("Scaling"); const double xshift = getParameter("Shift"); + const double xscale = getParameter("XScaling"); std::vector tmp(nData); // derivative with respect to Scaling parameter - eval(1.0, xshift, tmp.data(), xValues, nData); + eval(1.0, xshift, xscale, tmp.data(), xValues, nData); for (size_t i = 0; i < nData; ++i) { out->set(i, 0, tmp[i]); } - // There is no unique definition for the partial derivative with respect - // to the Shift parameter. Here we take the central difference, const double dx = (xValues[nData - 1] - xValues[0]) / static_cast(nData); std::vector tmpplus(nData); - eval(scaling, xshift + dx, tmpplus.data(), xValues, nData); std::vector tmpminus(nData); - eval(scaling, xshift - dx, tmpminus.data(), xValues, nData); + + // There is no unique definition for the partial derivative with respect + // to the Shift parameter. Here we take the central difference, + eval(scaling, xshift + dx, xscale, tmpplus.data(), xValues, nData); + eval(scaling, xshift - dx, xscale, tmpminus.data(), xValues, nData); for (size_t i = 0; i < nData; ++i) { out->set(i, 1, (tmpplus[i] - tmpminus[i]) / (2 * dx)); } + + eval(scaling, xshift, xscale + dx, tmpplus.data(), xValues, nData); + eval(scaling, xshift, xscale - dx, tmpminus.data(), xValues, nData); + for (size_t i = 0; i < nData; ++i) { + out->set(i, 2, (tmpplus[i] - tmpminus[i]) / (2 * dx)); + } } /// Clear all data diff --git a/Code/Mantid/Framework/CurveFitting/test/TabulatedFunctionTest.h b/Code/Mantid/Framework/CurveFitting/test/TabulatedFunctionTest.h index 7006f66712b0..609e3d648467 100644 --- a/Code/Mantid/Framework/CurveFitting/test/TabulatedFunctionTest.h +++ b/Code/Mantid/Framework/CurveFitting/test/TabulatedFunctionTest.h @@ -50,7 +50,7 @@ class TabulatedFunctionTest : public CxxTest::TestSuite UserFunction fun; fun.setAttributeValue("Formula","exp(-x*x)"); fun.function( x, y ); - + std::ofstream fil(m_asciiFileName.c_str()); for(size_t i = 0; i < x.size(); ++i) { @@ -58,11 +58,11 @@ class TabulatedFunctionTest : public CxxTest::TestSuite } } - + ~TabulatedFunctionTest() { Poco::File hAscii(m_asciiFileName); - if( hAscii.exists() ) + if( hAscii.exists() ) { hAscii.remove(); } @@ -205,12 +205,14 @@ class TabulatedFunctionTest : public CxxTest::TestSuite TS_ASSERT_EQUALS( fun.getParameter( "Scaling" ), 3.3 ); fun.setParameter( "Shift", 0.0 ); TS_ASSERT_EQUALS( fun.getParameter( "Shift" ), 0.0 ); + fun.setParameter( "XScaling", 1.0 ); + TS_ASSERT_EQUALS( fun.getParameter( "XScaling" ), 1.0 ); FunctionDomain1DVector x(-5.0, 5.0, 83); FunctionValues y( x ); fun.function( x, y ); - Mantid::CurveFitting::Jacobian jac(x.size(),2); + Mantid::CurveFitting::Jacobian jac(x.size(),3); fun.functionDeriv(x, jac); for(size_t i = 0; i < x.size(); ++i) @@ -239,7 +241,7 @@ class TabulatedFunctionTest : public CxxTest::TestSuite void test_factory_create_from_file() { - std::string inif = "name=TabulatedFunction,FileName=\"" + m_nexusFileName + "\",WorkspaceIndex=17,Scaling=2,Shift=0.02"; + std::string inif = "name=TabulatedFunction,FileName=\"" + m_nexusFileName + "\",WorkspaceIndex=17,Scaling=2,Shift=0.02,XScaling=0.2"; auto funf = Mantid::API::FunctionFactory::Instance().createInitialized(inif); TS_ASSERT( funf ); TS_ASSERT_EQUALS( funf->getAttribute("Workspace").asString(), ""); @@ -247,13 +249,14 @@ class TabulatedFunctionTest : public CxxTest::TestSuite TS_ASSERT_EQUALS( funf->getAttribute("FileName").asUnquotedString(), m_nexusFileName); TS_ASSERT_EQUALS( funf->getParameter("Scaling"), 2.0); TS_ASSERT_EQUALS( funf->getParameter("Shift"), 0.02); + TS_ASSERT_EQUALS( funf->getParameter("XScaling"), 0.2); } void test_factory_create_from_workspace() { auto ws = WorkspaceCreationHelper::Create2DWorkspaceFromFunction(Fun(),1,-5.0,5.0,0.1,false); AnalysisDataService::Instance().add( "TABULATEDFUNCTIONTEST_WS", ws ); - std::string inif = "name=TabulatedFunction,Workspace=TABULATEDFUNCTIONTEST_WS,WorkspaceIndex=71,Scaling=3.14,Shift=0.02"; + std::string inif = "name=TabulatedFunction,Workspace=TABULATEDFUNCTIONTEST_WS,WorkspaceIndex=71,Scaling=3.14,Shift=0.02,XScaling=0.2"; auto funf = Mantid::API::FunctionFactory::Instance().createInitialized(inif); TS_ASSERT( funf ); TS_ASSERT_EQUALS( funf->getAttribute("Workspace").asString(), "TABULATEDFUNCTIONTEST_WS"); @@ -261,6 +264,7 @@ class TabulatedFunctionTest : public CxxTest::TestSuite TS_ASSERT_EQUALS( funf->getAttribute("FileName").asUnquotedString(), ""); TS_ASSERT_EQUALS( funf->getParameter("Scaling"), 3.14); TS_ASSERT_EQUALS( funf->getParameter("Shift"), 0.02); + TS_ASSERT_EQUALS( funf->getParameter("XScaling"), 0.2); AnalysisDataService::Instance().clear(); }