diff --git a/qt/scientific_interfaces/Indirect/IndirectFunctionBrowser/ConvFunctionModel.cpp b/qt/scientific_interfaces/Indirect/IndirectFunctionBrowser/ConvFunctionModel.cpp index 5c2c92e1784a76e4df2a49133823a2c01235e574..01fd001365d8cb9dbc12466eb1a60436c6a4bc67 100644 --- a/qt/scientific_interfaces/Indirect/IndirectFunctionBrowser/ConvFunctionModel.cpp +++ b/qt/scientific_interfaces/Indirect/IndirectFunctionBrowser/ConvFunctionModel.cpp @@ -23,6 +23,7 @@ ConvFunctionModel::ConvFunctionModel() {} void ConvFunctionModel::clearData() { m_fitType = FitType::None; m_hasDeltaFunction = false; + m_hasTempCorrection = false; m_backgroundType = BackgroundType::None; m_model.clear(); } @@ -30,7 +31,7 @@ void ConvFunctionModel::clearData() { void ConvFunctionModel::setModel() { m_model.setModel(buildBackgroundFunctionString(), m_fitResolutions, buildPeaksFunctionString(), m_hasDeltaFunction, m_qValues, - m_isQDependentFunction); + m_isQDependentFunction, m_hasTempCorrection); m_model.setGlobalParameters(makeGlobalList()); } @@ -553,6 +554,8 @@ boost::optional<QString> ConvFunctionModel::getPrefix(ParamID name) const { return m_model.backgroundPrefix(); } else if (name == ParamID::DELTA_HEIGHT) { return m_model.deltaFunctionPrefix(); + } else if (name == ParamID::TEMPERATURE) { + return m_model.tempFunctionPrefix(); } else { auto const prefixes = m_model.peakPrefixes(); if (!prefixes) @@ -601,6 +604,9 @@ void ConvFunctionModel::applyParameterFunction( applyToFitType(m_fitType, paramFun); applyToBackground(m_backgroundType, paramFun); applyToDelta(m_hasDeltaFunction, paramFun); + auto tempType = m_hasTempCorrection ? TempCorrectionType::Exponential + : TempCorrectionType::None; + applyToTemp(tempType, paramFun); } boost::optional<ParamID> diff --git a/qt/scientific_interfaces/Indirect/IndirectFunctionBrowser/ConvTemplateBrowser.cpp b/qt/scientific_interfaces/Indirect/IndirectFunctionBrowser/ConvTemplateBrowser.cpp index a76e388835ac037b95de345b5b828dfd54d6cb4b..b2786374cb6fe7932f670d04af4f99aecce90011 100644 --- a/qt/scientific_interfaces/Indirect/IndirectFunctionBrowser/ConvTemplateBrowser.cpp +++ b/qt/scientific_interfaces/Indirect/IndirectFunctionBrowser/ConvTemplateBrowser.cpp @@ -290,6 +290,7 @@ void ConvTemplateBrowser::createDeltaFunctionProperties() { void ConvTemplateBrowser::createTempCorrectionProperties() { m_tempCorrectionOn = m_boolManager->addProperty("Temp Correction"); m_temperature = m_parameterManager->addProperty("Temperature"); + m_parameterManager->setDescription(m_temperature, "Temperature"); m_parameterMap[m_temperature] = ParamID::TEMPERATURE; m_parameterReverseMap[ParamID::TEMPERATURE] = m_temperature; } diff --git a/qt/scientific_interfaces/Indirect/IndirectFunctionBrowser/ConvTypes.cpp b/qt/scientific_interfaces/Indirect/IndirectFunctionBrowser/ConvTypes.cpp index d8ba2c649a8f4c8378f2c2cca6f61a9c18d97b94..b0450895a46ca4d6293e53bdb38350e930995ab9 100644 --- a/qt/scientific_interfaces/Indirect/IndirectFunctionBrowser/ConvTypes.cpp +++ b/qt/scientific_interfaces/Indirect/IndirectFunctionBrowser/ConvTypes.cpp @@ -56,6 +56,7 @@ std::map<ParamID, QString> g_paramName{ {ParamID::TW_TAU, "Tau"}, {ParamID::TW_CENTRE, "Centre"}, {ParamID::DELTA_HEIGHT, "Height"}, + {ParamID::TEMPERATURE, "Temp"}, {ParamID::SE_HEIGHT, "Height"}, {ParamID::SE_TAU, "Tau"}, {ParamID::SE_BETA, "Beta"}, @@ -141,6 +142,17 @@ std::map<bool, TemplateSubTypeDescriptor> TemplateSubTypeImpl<bool>::g_typeMap{ {ParamID::DELTA_HEIGHT, ParamID::DELTA_HEIGHT}}}, }; +template <> +std::map<TempCorrectionType, TemplateSubTypeDescriptor> + TemplateSubTypeImpl<TempCorrectionType>::g_typeMap{ + {TempCorrectionType::None, + {"None", "", {ParamID::NONE, ParamID::NONE}}}, + {TempCorrectionType::Exponential, + {"Temp Correction", + "UserFunction", + {ParamID::TEMPERATURE, ParamID::TEMPERATURE}}}, + }; + QString paramName(ParamID id) { return g_paramName.at(id); } void applyToFitType(FitType fitType, @@ -163,6 +175,13 @@ void applyToDelta(bool hasDeltaFunction, paramFun); } +void applyToTemp(TempCorrectionType tempCorrectionType, + const std::function<void(ParamID)> ¶mFun) { + applyToParamIDRange(TempSubType::g_typeMap[tempCorrectionType].blocks.front(), + TempSubType::g_typeMap[tempCorrectionType].blocks.back(), + paramFun); +} + } // namespace ConvTypes } // namespace IDA } // namespace CustomInterfaces diff --git a/qt/scientific_interfaces/Indirect/IndirectFunctionBrowser/ConvTypes.h b/qt/scientific_interfaces/Indirect/IndirectFunctionBrowser/ConvTypes.h index 006484eec8066e2c2751ae9ea37b36bb4e22f682..c18b496c0f8202f3a3d750115f2cfd0ce55a9636 100644 --- a/qt/scientific_interfaces/Indirect/IndirectFunctionBrowser/ConvTypes.h +++ b/qt/scientific_interfaces/Indirect/IndirectFunctionBrowser/ConvTypes.h @@ -42,9 +42,10 @@ extern std::unordered_map<std::string, FitType> FitTypeStringToEnum; enum class BackgroundType { None, Flat, Linear }; +enum class TempCorrectionType { None, Exponential }; + enum class ParamID { NONE, - TEMPERATURE, LOR1_AMPLITUDE, LOR1_PEAKCENTRE, LOR1_FWHM, @@ -59,6 +60,7 @@ enum class ParamID { TW_TAU, TW_CENTRE, DELTA_HEIGHT, + TEMPERATURE, SE_HEIGHT, SE_TAU, SE_BETA, @@ -189,12 +191,19 @@ struct DeltaSubType : public TemplateSubTypeImpl<bool> { QString name() const override { return "Delta"; } }; +struct TempSubType : public TemplateSubTypeImpl<TempCorrectionType> { + QString name() const override { return "TempCorrection"; } +}; + void applyToFitType(FitType fitType, const std::function<void(ParamID)> ¶mFun); void applyToBackground(BackgroundType bgType, const std::function<void(ParamID)> ¶mFun); void applyToDelta(bool deltaType, const std::function<void(ParamID)> ¶mFun); +void applyToTemp(TempCorrectionType tempCorrectionType, + const std::function<void(ParamID)> ¶mFun); + } // namespace ConvTypes } // namespace IDA } // namespace CustomInterfaces diff --git a/qt/widgets/common/inc/MantidQtWidgets/Common/ConvolutionFunctionModel.h b/qt/widgets/common/inc/MantidQtWidgets/Common/ConvolutionFunctionModel.h index c083fe01a12a9e4c0054ad26b4ec8692d750b655..21f7788b9ae7caec938cce2a7b85853010fbc00f 100644 --- a/qt/widgets/common/inc/MantidQtWidgets/Common/ConvolutionFunctionModel.h +++ b/qt/widgets/common/inc/MantidQtWidgets/Common/ConvolutionFunctionModel.h @@ -29,7 +29,8 @@ public: setModel(const std::string &background, const std::vector<std::pair<std::string, int>> &resolutionWorkspaces, const std::string &peaks, bool hasDeltaFunction, - const std::vector<double> &qValues, const bool isQDependent); + const std::vector<double> &qValues, const bool isQDependent, + bool hasTempCorrection); boost::optional<QString> backgroundPrefix() const { return m_backgroundPrefix; } @@ -39,6 +40,9 @@ public: boost::optional<QString> deltaFunctionPrefix() const { return m_deltaFunctionPrefix; } + boost::optional<QString> tempFunctionPrefix() const { + return m_tempFunctionPrefix; + } boost::optional<QStringList> peakPrefixes() const { return m_peakPrefixes; } std::string resolutionWorkspace() const { return m_resolutionWorkspace; } int resolutionWorkspaceIndex() const { return m_resolutionWorkspaceIndex; } @@ -46,9 +50,24 @@ public: private: void findComponentPrefixes(); void findConvolutionPrefixes(const IFunction_sptr &fun); + CompositeFunction_sptr createInnerFunction(std::string peaksFunction, + bool hasDeltaFunction, + bool isQDependent, double q, + bool hasTempCorrection); + CompositeFunction_sptr + addTempCorrection(CompositeFunction_sptr peaksFunction); + IFunction_sptr createTemperatureCorrection(double correction); + CompositeFunction_sptr + createConvolutionFunction(IFunction_sptr resolutionFunction, + IFunction_sptr innerFunction); + IFunction_sptr createResolutionFunction(std::string workspaceName, + int workspaceIndex); + CompositeFunction_sptr addBackground(CompositeFunction_sptr domainFunction, + std::string background); boost::optional<QString> m_backgroundPrefix; boost::optional<QString> m_convolutionPrefix; boost::optional<QString> m_deltaFunctionPrefix; + boost::optional<QString> m_tempFunctionPrefix; boost::optional<QStringList> m_peakPrefixes; std::string m_resolutionWorkspace; int m_resolutionWorkspaceIndex; diff --git a/qt/widgets/common/src/ConvolutionFunctionModel.cpp b/qt/widgets/common/src/ConvolutionFunctionModel.cpp index 346caa8139ea4d837c4ac0c3eda52889a6ec3d09..19d126d1fd8ab2221a523be6c68229be5dad5b81 100644 --- a/qt/widgets/common/src/ConvolutionFunctionModel.cpp +++ b/qt/widgets/common/src/ConvolutionFunctionModel.cpp @@ -35,6 +35,10 @@ bool isDeltaFunction(const IFunction_sptr &fun) { return fun->name() == "DeltaFunction"; } +bool isProductFunction(const IFunction_sptr &fun) { + return fun->name() == "ProductFunction"; +} + bool isBackground(const IFunction_sptr &fun) { return static_cast<bool>( boost::dynamic_pointer_cast<const IBackgroundFunction>(fun)); @@ -68,47 +72,133 @@ void ConvolutionFunctionModel::setModel( const std::string &background, const std::vector<std::pair<std::string, int>> &resolutionWorkspaces, const std::string &peaks, bool hasDeltaFunction, - const std::vector<double> &qValues, const bool isQDependent) { + const std::vector<double> &qValues, const bool isQDependent, + bool hasTempCorrection) { + std::string resolution, convolution, function, modifiedPeaks; auto fitFunction = boost::make_shared<MultiDomainFunction>(); auto const nf = m_numberDomains > 0 ? static_cast<int>(m_numberDomains) : 1; for (int i = 0; i < nf; ++i) { - if (isQDependent) { - auto qValue = qValues.empty() ? 0.0 : qValues[i]; - IFunction::Attribute attr(qValue); - auto peaksFunction = FunctionFactory::Instance().createInitialized(peaks); - peaksFunction->setAttribute("Q", attr); - modifiedPeaks = peaksFunction->asString(); - } else { - modifiedPeaks = peaks; - } - auto const model = hasDeltaFunction ? "name=DeltaFunction;" + modifiedPeaks - : modifiedPeaks; + CompositeFunction_sptr domainFunction; + auto qValue = qValues.empty() ? 0.0 : qValues[i]; + domainFunction = createInnerFunction(peaks, hasDeltaFunction, isQDependent, + qValue, hasTempCorrection); auto workspace = resolutionWorkspaces.empty() ? "" : resolutionWorkspaces[i].first; - resolution = workspace.empty() - ? "name=Resolution" - : "name=Resolution,Workspace=\"" + workspace + - "\",WorkspaceIndex=" + - std::to_string(resolutionWorkspaces[i].second); - convolution = "composite=Convolution;" + resolution + ";" + model; - function = background.empty() ? convolution - : background + ";(" + convolution + ")"; - auto domainFunction = - FunctionFactory::Instance().createInitialized(function); - + auto resolutionFunction = + createResolutionFunction(workspace, resolutionWorkspaces[i].second); + domainFunction = + createConvolutionFunction(resolutionFunction, domainFunction); + domainFunction = addBackground(domainFunction, background); fitFunction->addFunction(domainFunction); fitFunction->setDomainIndex(i, i); } - setFunction(fitFunction); } +CompositeFunction_sptr +ConvolutionFunctionModel::addBackground(CompositeFunction_sptr domainFunction, + std::string background) { + if (background.empty()) + return domainFunction; + + auto backgroundFunction = + FunctionFactory::Instance().createInitialized(background); + auto functionWithBackground = boost::make_shared<CompositeFunction>(); + functionWithBackground->addFunction(backgroundFunction); + functionWithBackground->addFunction(domainFunction); + + return functionWithBackground; +} + +CompositeFunction_sptr ConvolutionFunctionModel::createInnerFunction( + std::string peaksFunction, bool hasDeltaFunction, bool isQDependent, + double qValue, bool hasTempCorrection) { + auto functionSpecified = !peaksFunction.empty(); + CompositeFunction_sptr innerFunction = + boost::make_shared<CompositeFunction>(); + if (functionSpecified) { + auto peakFunction = + FunctionFactory::Instance().createInitialized(peaksFunction); + auto peakFunctionComposite = + boost::dynamic_pointer_cast<CompositeFunction>(peakFunction); + if (peakFunctionComposite) { + innerFunction = peakFunctionComposite; + } else { + innerFunction->addFunction(peakFunction); + } + if (isQDependent) { + IFunction::Attribute attr(qValue); + innerFunction->setAttribute("Q", attr); + } + } + if (hasDeltaFunction) { + auto deltaFunction = + FunctionFactory::Instance().createFunction("DeltaFunction"); + innerFunction->addFunction(deltaFunction); + } + if (hasTempCorrection && (functionSpecified || hasDeltaFunction)) { + innerFunction = addTempCorrection(innerFunction); + } + + return innerFunction; +} + +CompositeFunction_sptr ConvolutionFunctionModel::addTempCorrection( + CompositeFunction_sptr peaksFunction) { + CompositeFunction_sptr productFunction = + boost::dynamic_pointer_cast<CompositeFunction>( + FunctionFactory::Instance().createFunction("ProductFunction")); + auto tempFunction = createTemperatureCorrection(100.0); + productFunction->addFunction(tempFunction); + productFunction->addFunction(peaksFunction); + return productFunction; +} + +IFunction_sptr +ConvolutionFunctionModel::createTemperatureCorrection(double correction) { + // create user function for the exponential correction + // (x*temp) / 1-exp(-(x*temp)) + auto tempFunc = FunctionFactory::Instance().createFunction("UserFunction"); + // 11.606 is the conversion factor from meV to K + std::string formula = "((x*11.606)/Temp) / (1 - exp(-((x*11.606)/Temp)))"; + IFunction::Attribute att(formula); + tempFunc->setAttribute("Formula", att); + tempFunc->setParameter("Temp", correction); + tempFunc->fixParameter("Temp", true); + return tempFunc; +} + +CompositeFunction_sptr ConvolutionFunctionModel::createConvolutionFunction( + IFunction_sptr resolutionFunction, IFunction_sptr innerFunction) { + CompositeFunction_sptr convolution = + boost::dynamic_pointer_cast<CompositeFunction>( + FunctionFactory::Instance().createFunction("Convolution")); + convolution->addFunction(resolutionFunction); + + if (innerFunction->nFunctions() > 0) + convolution->addFunction(innerFunction); + + return convolution; +} + +IFunction_sptr +ConvolutionFunctionModel::createResolutionFunction(std::string workspaceName, + int workspaceIndex) { + std::string resolution = + workspaceName.empty() + ? "name=Resolution" + : "name=Resolution,Workspace=\"" + workspaceName + + "\",WorkspaceIndex=" + std::to_string(workspaceIndex); + return FunctionFactory::Instance().createInitialized(resolution); +} + void ConvolutionFunctionModel::findComponentPrefixes() { m_backgroundPrefix.reset(); m_convolutionPrefix.reset(); m_deltaFunctionPrefix.reset(); + m_tempFunctionPrefix.reset(); m_peakPrefixes.reset(); m_resolutionWorkspace.clear(); m_resolutionWorkspaceIndex = 0; @@ -163,10 +253,16 @@ void ConvolutionFunctionModel::findConvolutionPrefixes( resolution->getAttribute("WorkspaceIndex").asInt(); if (nf == 1) return; - auto const model = fun->getFunction(1); + auto model = fun->getFunction(1); + QString convolutionPrefix = "f1."; + if (isProductFunction(model)) { + model = model->getFunction(1); + convolutionPrefix = "f1.f1."; + m_tempFunctionPrefix = *m_convolutionPrefix + "f1.f0."; + } auto const nm = model->nFunctions(); if (nm == 0) { - auto const prefix = *m_convolutionPrefix + "f1."; + auto const prefix = *m_convolutionPrefix + convolutionPrefix; if (isDeltaFunction(model)) { m_deltaFunctionPrefix = prefix; } else { @@ -175,7 +271,8 @@ void ConvolutionFunctionModel::findConvolutionPrefixes( } else { m_peakPrefixes = QStringList(); for (size_t j = 0; j < model->nFunctions(); ++j) { - auto const prefix = *m_convolutionPrefix + QString("f1.f%1.").arg(j); + auto const prefix = + *m_convolutionPrefix + convolutionPrefix + QString("f%1.").arg(j); if (isDeltaFunction(model->getFunction(j))) { m_deltaFunctionPrefix = prefix; } else { diff --git a/qt/widgets/common/test/ConvolutionFunctionModelTest.h b/qt/widgets/common/test/ConvolutionFunctionModelTest.h index 29504a6d14ace64496bec54b0b498713a6f9b855..8c2fa79659d47351ec61aa63e9819601b07c313a 100644 --- a/qt/widgets/common/test/ConvolutionFunctionModelTest.h +++ b/qt/widgets/common/test/ConvolutionFunctionModelTest.h @@ -13,6 +13,7 @@ #include "MantidAPI/IFunction.h" #include "MantidQtWidgets/Common/ConvolutionFunctionModel.h" #include <cxxtest/TestSuite.h> +#include <iostream> using namespace MantidQt::MantidWidgets; using namespace Mantid::API; @@ -255,7 +256,8 @@ public: fitResolutions.emplace_back(pair1); fitResolutions.emplace_back(pair2); - model.setModel("", fitResolutions, "", false, std::vector<double>(), false); + model.setModel("", fitResolutions, "", false, std::vector<double>(), false, + false); auto fitFunctionAsString = model.getFitFunction()->asString(); TS_ASSERT_EQUALS( @@ -266,6 +268,213 @@ public: "true,NumDeriv=true,$domains=i;name=Resolution,Workspace=abc," "WorkspaceIndex=2,X=(),Y=())"); } + + void test_setModel_with_delta_function_correct() { + auto algo = FrameworkManager::Instance().createAlgorithm("CreateWorkspace"); + algo->initialize(); + algo->setPropertyValue("DataX", "1,2,3"); + algo->setPropertyValue("DataY", "1,2,3"); + algo->setPropertyValue("OutputWorkspace", "abc"); + algo->execute(); + ConvolutionFunctionModel model; + model.setNumberDomains(2); + auto pair1 = std::make_pair<std::string, int>("abc", 1); + auto pair2 = std::make_pair<std::string, int>("abc", 2); + auto fitResolutions = std::vector<std::pair<std::string, int>>(); + fitResolutions.emplace_back(pair1); + fitResolutions.emplace_back(pair2); + + model.setModel("", fitResolutions, "", true, std::vector<double>(), false, + false); + + auto fitFunctionAsString = model.getFitFunction()->asString(); + std::cout << fitFunctionAsString << std::endl; + TS_ASSERT_EQUALS( + fitFunctionAsString, + "composite=MultiDomainFunction,NumDeriv=true;(composite=Convolution," + "FixResolution=true,NumDeriv=true,$domains=i;name=Resolution,Workspace=" + "abc,WorkspaceIndex=1,X=(),Y=();name=DeltaFunction,Height=1,Centre=0);(" + "composite=Convolution,FixResolution=" + "true,NumDeriv=true,$domains=i;name=Resolution,Workspace=abc," + "WorkspaceIndex=2,X=(),Y=();name=DeltaFunction,Height=1,Centre=0)"); + } + + void test_setModel_with_delta_function_TeixeiraWaterSQE_correct() { + auto algo = FrameworkManager::Instance().createAlgorithm("CreateWorkspace"); + algo->initialize(); + algo->setPropertyValue("DataX", "1,2,3"); + algo->setPropertyValue("DataY", "1,2,3"); + algo->setPropertyValue("OutputWorkspace", "abc"); + algo->execute(); + ConvolutionFunctionModel model; + model.setNumberDomains(2); + auto pair1 = std::make_pair<std::string, int>("abc", 1); + auto pair2 = std::make_pair<std::string, int>("abc", 2); + auto fitResolutions = std::vector<std::pair<std::string, int>>(); + fitResolutions.emplace_back(pair1); + fitResolutions.emplace_back(pair2); + + model.setModel("name=FlatBackground", fitResolutions, + "name=TeixeiraWaterSQE", true, std::vector<double>(), false, + false); + + auto fitFunctionAsString = model.getFitFunction()->asString(); + std::cout << fitFunctionAsString << std::endl; + TS_ASSERT_EQUALS( + fitFunctionAsString, + "composite=MultiDomainFunction,NumDeriv=true;(composite=" + "CompositeFunction,NumDeriv=false,$domains=i;name=FlatBackground,A0=0;(" + "composite=Convolution,FixResolution=true,NumDeriv=true;name=" + "Resolution,Workspace=abc,WorkspaceIndex=1,X=(),Y=();(name=" + "TeixeiraWaterSQE,Q=8.9884656743115785e+307,WorkspaceIndex=2147483647," + "Height=1,DiffCoeff=2.3,Tau=1.25,Centre=0;name=DeltaFunction,Height=1," + "Centre=0)));(composite=CompositeFunction,NumDeriv=false,$domains=i;" + "name=FlatBackground,A0=0;(composite=Convolution,FixResolution=true," + "NumDeriv=true;name=Resolution,Workspace=abc,WorkspaceIndex=2,X=(),Y=()" + ";(name=TeixeiraWaterSQE,Q=8.9884656743115785e+307,WorkspaceIndex=" + "2147483647,Height=1,DiffCoeff=2.3,Tau=1.25,Centre=0;name=" + "DeltaFunction,Height=1,Centre=0)))"); + } + + void test_setModel_with_delta_function_TwoLorenztian_correct() { + auto algo = FrameworkManager::Instance().createAlgorithm("CreateWorkspace"); + algo->initialize(); + algo->setPropertyValue("DataX", "1,2,3"); + algo->setPropertyValue("DataY", "1,2,3"); + algo->setPropertyValue("OutputWorkspace", "abc"); + algo->execute(); + ConvolutionFunctionModel model; + model.setNumberDomains(2); + auto pair1 = std::make_pair<std::string, int>("abc", 1); + auto pair2 = std::make_pair<std::string, int>("abc", 2); + auto fitResolutions = std::vector<std::pair<std::string, int>>(); + fitResolutions.emplace_back(pair1); + fitResolutions.emplace_back(pair2); + + model.setModel("name=FlatBackground", fitResolutions, + "(name=Lorentzian;name=Lorentzian)", true, + std::vector<double>(), false, false); + + auto fitFunctionAsString = model.getFitFunction()->asString(); + std::cout << fitFunctionAsString << std::endl; + TS_ASSERT_EQUALS( + fitFunctionAsString, + "composite=MultiDomainFunction,NumDeriv=true;(composite=" + "CompositeFunction,NumDeriv=false,$domains=i;name=FlatBackground,A0=0;(" + "composite=Convolution,FixResolution=true,NumDeriv=true;name=" + "Resolution,Workspace=abc,WorkspaceIndex=1,X=(),Y=();(name=Lorentzian," + "Amplitude=1,PeakCentre=0,FWHM=0;name=Lorentzian,Amplitude=1," + "PeakCentre=0,FWHM=0;name=DeltaFunction,Height=1,Centre=0)));(" + "composite=CompositeFunction,NumDeriv=false,$domains=i;name=" + "FlatBackground,A0=0;(composite=Convolution,FixResolution=true," + "NumDeriv=true;name=Resolution,Workspace=abc,WorkspaceIndex=2,X=(),Y=()" + ";(name=Lorentzian,Amplitude=1,PeakCentre=0,FWHM=0;name=Lorentzian," + "Amplitude=1,PeakCentre=0,FWHM=0;name=DeltaFunction,Height=1,Centre=0))" + ")"); + } + + void test_setModel_with_delta_function_TwoLorenztian_correctWithTemp() { + auto algo = FrameworkManager::Instance().createAlgorithm("CreateWorkspace"); + algo->initialize(); + algo->setPropertyValue("DataX", "1,2,3"); + algo->setPropertyValue("DataY", "1,2,3"); + algo->setPropertyValue("OutputWorkspace", "abc"); + algo->execute(); + ConvolutionFunctionModel model; + model.setNumberDomains(2); + auto pair1 = std::make_pair<std::string, int>("abc", 1); + auto pair2 = std::make_pair<std::string, int>("abc", 2); + auto fitResolutions = std::vector<std::pair<std::string, int>>(); + fitResolutions.emplace_back(pair1); + fitResolutions.emplace_back(pair2); + + model.setModel("name=FlatBackground", fitResolutions, + "(name=Lorentzian;name=Lorentzian)", true, + std::vector<double>(), false, true); + + auto fitFunctionAsString = model.getFitFunction()->asString(); + std::cout << fitFunctionAsString << std::endl; + TS_ASSERT_EQUALS( + fitFunctionAsString, + "composite=MultiDomainFunction,NumDeriv=true;(composite=" + "CompositeFunction,NumDeriv=false,$domains=i;name=FlatBackground,A0=0;(" + "composite=Convolution,FixResolution=true,NumDeriv=true;name=" + "Resolution,Workspace=abc,WorkspaceIndex=1,X=(),Y=();(composite=" + "ProductFunction,NumDeriv=false;name=UserFunction,Formula=(x*11.606/" + "Temp)/(1-exp( " + "-(x*11.606/" + "Temp))),Temp=0;(name=Lorentzian,Amplitude=1,PeakCentre=0,FWHM=0;name=" + "Lorentzian,Amplitude=1,PeakCentre=0,FWHM=0;name=DeltaFunction,Height=" + "1,Centre=0))));(composite=CompositeFunction,NumDeriv=false,$domains=i;" + "name=FlatBackground,A0=0;(composite=Convolution,FixResolution=true," + "NumDeriv=true;name=Resolution,Workspace=abc,WorkspaceIndex=2,X=(),Y=()" + ";(composite=ProductFunction,NumDeriv=false;name=UserFunction,Formula=(" + "x*11.606/Temp)/(1-exp( " + "-(x*11.606/" + "Temp))),Temp=0;(name=Lorentzian,Amplitude=1,PeakCentre=0,FWHM=0;name=" + "Lorentzian,Amplitude=1,PeakCentre=0,FWHM=0;name=DeltaFunction,Height=" + "1,Centre=0))))"); + } + + void test_component_prefixes_set_correctly_without_temp_correction() { + auto algo = FrameworkManager::Instance().createAlgorithm("CreateWorkspace"); + algo->initialize(); + algo->setPropertyValue("DataX", "1,2,3"); + algo->setPropertyValue("DataY", "1,2,3"); + algo->setPropertyValue("OutputWorkspace", "abc"); + algo->execute(); + ConvolutionFunctionModel model; + model.setNumberDomains(2); + auto pair1 = std::make_pair<std::string, int>("abc", 1); + auto pair2 = std::make_pair<std::string, int>("abc", 2); + auto fitResolutions = std::vector<std::pair<std::string, int>>(); + fitResolutions.emplace_back(pair1); + fitResolutions.emplace_back(pair2); + + model.setModel("name=FlatBackground", fitResolutions, + "(name=Lorentzian;name=Lorentzian)", true, + std::vector<double>(), false, false); + + TS_ASSERT_EQUALS(model.backgroundPrefix().value().toStdString(), "f0."); + TS_ASSERT_EQUALS(model.convolutionPrefix().value().toStdString(), "f1."); + TS_ASSERT_EQUALS(model.deltaFunctionPrefix().value().toStdString(), + "f1.f1.f2."); + TS_ASSERT_EQUALS(model.peakPrefixes().value()[0].toStdString(), + "f1.f1.f0."); + TS_ASSERT_EQUALS(model.peakPrefixes().value()[1].toStdString(), + "f1.f1.f1."); + } + + void test_component_prefixes_set_correctly_with_temp_correction() { + auto algo = FrameworkManager::Instance().createAlgorithm("CreateWorkspace"); + algo->initialize(); + algo->setPropertyValue("DataX", "1,2,3"); + algo->setPropertyValue("DataY", "1,2,3"); + algo->setPropertyValue("OutputWorkspace", "abc"); + algo->execute(); + ConvolutionFunctionModel model; + model.setNumberDomains(2); + auto pair1 = std::make_pair<std::string, int>("abc", 1); + auto pair2 = std::make_pair<std::string, int>("abc", 2); + auto fitResolutions = std::vector<std::pair<std::string, int>>(); + fitResolutions.emplace_back(pair1); + fitResolutions.emplace_back(pair2); + + model.setModel("name=FlatBackground", fitResolutions, + "(name=Lorentzian;name=Lorentzian)", true, + std::vector<double>(), false, true); + + TS_ASSERT_EQUALS(model.backgroundPrefix().value().toStdString(), "f0."); + TS_ASSERT_EQUALS(model.convolutionPrefix().value().toStdString(), "f1."); + TS_ASSERT_EQUALS(model.deltaFunctionPrefix().value().toStdString(), + "f1.f1.f1.f2."); + TS_ASSERT_EQUALS(model.peakPrefixes().value()[0].toStdString(), + "f1.f1.f1.f0."); + TS_ASSERT_EQUALS(model.peakPrefixes().value()[1].toStdString(), + "f1.f1.f1.f1."); + TS_ASSERT_EQUALS(model.tempFunctionPrefix().value().toStdString(), + "f1.f1.f0."); + } }; #endif // MANTIDWIDGETS_CONVOLUTIONFUNCTIONMODELTEST_H_