From b45b6db17aa3ccf58b7fc741f64213c1eac24e0a Mon Sep 17 00:00:00 2001 From: Matthew Andrew <matthew.andrew@tessella.com> Date: Mon, 20 Jan 2020 16:44:40 +0000 Subject: [PATCH] Updated temperature function model Re #26881 --- .../Common/ConvolutionFunctionModel.h | 5 +- .../common/src/ConvolutionFunctionModel.cpp | 165 ++++++++---------- .../test/ConvolutionFunctionModelTest.h | 54 ++++-- 3 files changed, 121 insertions(+), 103 deletions(-) diff --git a/qt/widgets/common/inc/MantidQtWidgets/Common/ConvolutionFunctionModel.h b/qt/widgets/common/inc/MantidQtWidgets/Common/ConvolutionFunctionModel.h index 21f7788b9ae..3ffd339a488 100644 --- a/qt/widgets/common/inc/MantidQtWidgets/Common/ConvolutionFunctionModel.h +++ b/qt/widgets/common/inc/MantidQtWidgets/Common/ConvolutionFunctionModel.h @@ -49,7 +49,10 @@ public: private: void findComponentPrefixes(); - void findConvolutionPrefixes(const IFunction_sptr &fun); + // void findConvolutionPrefixes(const IFunction_sptr &fun); + void iterateThroughFunction(IFunction *func, + const QString &prefix); + void setPrefix(IFunction *func, const QString &prefix); CompositeFunction_sptr createInnerFunction(std::string peaksFunction, bool hasDeltaFunction, bool isQDependent, double q, diff --git a/qt/widgets/common/src/ConvolutionFunctionModel.cpp b/qt/widgets/common/src/ConvolutionFunctionModel.cpp index f5a0d1f378d..1754c2841f1 100644 --- a/qt/widgets/common/src/ConvolutionFunctionModel.cpp +++ b/qt/widgets/common/src/ConvolutionFunctionModel.cpp @@ -24,25 +24,28 @@ using namespace Mantid::API; namespace { -bool isConvolution(const IFunction_sptr &fun) { - return fun->name() == "Convolution"; -} +bool isConvolution(const IFunction *fun) { return fun->name() == "Convolution"; } -bool isResolution(const IFunction_sptr &fun) { - return fun->name() == "Resolution"; -} +bool isResolution(const IFunction *fun) { return fun->name() == "Resolution"; } -bool isDeltaFunction(const IFunction_sptr &fun) { +bool isDeltaFunction(const IFunction *fun) { return fun->name() == "DeltaFunction"; } -bool isProductFunction(const IFunction_sptr &fun) { - return fun->name() == "ProductFunction"; +bool isTempFunction(const IFunction *fun) { + return fun->name() == "UserFunction"; } -bool isBackground(const IFunction_sptr &fun) { +bool isBackground(const IFunction *fun) { return static_cast<bool>( - boost::dynamic_pointer_cast<const IBackgroundFunction>(fun)); + dynamic_cast<const IBackgroundFunction*>(fun)); +} + +bool isPeakFunction(const IFunction *fun) { + if(dynamic_cast<const CompositeFunction*>(fun)){ + return false; + } + return true; } } // namespace @@ -81,17 +84,17 @@ void ConvolutionFunctionModel::setModel( for (int i = 0; i < nf; ++i) { CompositeFunction_sptr domainFunction; auto qValue = qValues.empty() ? 0.0 : qValues[i]; - domainFunction = createInnerFunction(peaks, hasDeltaFunction, isQDependent, - qValue, hasTempCorrection); + auto innerFunction = createInnerFunction( + peaks, hasDeltaFunction, isQDependent, qValue, hasTempCorrection); auto workspace = resolutionWorkspaces.empty() ? "" : resolutionWorkspaces[i].first; auto workspaceIndex = resolutionWorkspaces.empty() ? 0 : resolutionWorkspaces[i].second; auto resolutionFunction = createResolutionFunction(workspace, workspaceIndex); - domainFunction = - createConvolutionFunction(resolutionFunction, domainFunction); - domainFunction = addBackground(domainFunction, background); + auto convolutionFunction = + createConvolutionFunction(resolutionFunction, innerFunction); + domainFunction = addBackground(convolutionFunction, background); fitFunction->addFunction(domainFunction); fitFunction->setDomainIndex(i, i); @@ -142,13 +145,23 @@ CompositeFunction_sptr ConvolutionFunctionModel::createInnerFunction( innerFunction->setAttribute("Q", attr); } } + + if (hasTempCorrection) { + innerFunction = addTempCorrection(innerFunction); + } + if (hasDeltaFunction) { auto deltaFunction = FunctionFactory::Instance().createFunction("DeltaFunction"); - innerFunction->addFunction(deltaFunction); - } - if (hasTempCorrection) { - innerFunction = addTempCorrection(innerFunction); + if (!hasTempCorrection) { + innerFunction->addFunction(deltaFunction); + } else { + CompositeFunction_sptr innerFunctionNew = + boost::make_shared<CompositeFunction>(); + innerFunctionNew->addFunction(deltaFunction); + innerFunctionNew->addFunction(innerFunction); + return innerFunctionNew; + } } return innerFunction; @@ -208,92 +221,62 @@ void ConvolutionFunctionModel::findComponentPrefixes() { m_convolutionPrefix.reset(); m_deltaFunctionPrefix.reset(); m_tempFunctionPrefix.reset(); - m_peakPrefixes.reset(); + m_peakPrefixes = QStringList(); m_resolutionWorkspace.clear(); m_resolutionWorkspaceIndex = 0; + auto function = getCurrentFunction(); - if (!function) + if(!function) return; - if (function->nFunctions() == 0) { - if (!isConvolution(function)) { - throw std::runtime_error("Model doesn't contain a convolution."); - } - m_convolutionPrefix = ""; - return; - } - if (isConvolution(function)) { - m_convolutionPrefix = ""; - findConvolutionPrefixes(function); - return; - } - for (size_t i = 0; i < function->nFunctions(); ++i) { - auto const fun = function->getFunction(i); - if (isBackground(fun)) { - if (m_backgroundPrefix) { - throw std::runtime_error("Model cannot have more than one background."); - } - m_backgroundPrefix = QString("f%1.").arg(i); - } else if (isConvolution(fun)) { - if (m_convolutionPrefix) { - throw std::runtime_error( - "Model cannot have more than one convolution."); - } - m_convolutionPrefix = QString("f%1.").arg(i); - findConvolutionPrefixes(fun); - } + iterateThroughFunction(function.get(), QString()); + + if (m_peakPrefixes->isEmpty()) { + m_peakPrefixes.reset(); } if (!m_convolutionPrefix) { throw std::runtime_error("Model doesn't contain a convolution."); } } -void ConvolutionFunctionModel::findConvolutionPrefixes( - const IFunction_sptr &fun) { - auto const nf = fun->nFunctions(); - if (nf == 0) +void ConvolutionFunctionModel::iterateThroughFunction(IFunction *func, + const QString &prefix) { + auto numberOfSubFunction = func->nFunctions(); + + setPrefix(func, prefix); + if (numberOfSubFunction == 0) { return; - auto const resolution = fun->getFunction(0); - if (!isResolution(resolution)) { - throw std::runtime_error( - "Model's resolution function must have type Resolution."); } - m_resolutionWorkspace = resolution->getAttribute("Workspace").asString(); - m_resolutionWorkspaceIndex = - resolution->getAttribute("WorkspaceIndex").asInt(); - if (nf == 1) - return; - auto model = fun->getFunction(1); - QString convolutionPrefix = "f1."; - if (isProductFunction(model)) { - model = model->getFunction(1); - convolutionPrefix = "f1.f1."; - m_tempFunctionPrefix = *m_convolutionPrefix + "f1.f0."; + for (size_t k = 0; k < numberOfSubFunction; ++k) { + iterateThroughFunction(func->getFunction(k).get(), + prefix + QString("f%1.").arg(k)); } - auto const nm = model->nFunctions(); - if (nm == 0) { - auto const prefix = *m_convolutionPrefix + convolutionPrefix; - if (isDeltaFunction(model)) { - m_deltaFunctionPrefix = prefix; - } else { - m_peakPrefixes = QStringList(prefix); - } - } else { - m_peakPrefixes = QStringList(); - for (size_t j = 0; j < model->nFunctions(); ++j) { - auto const prefix = - *m_convolutionPrefix + convolutionPrefix + QString("f%1.").arg(j); - if (isDeltaFunction(model->getFunction(j))) { - m_deltaFunctionPrefix = prefix; - } else { - m_peakPrefixes->append(prefix); - } +} + +void ConvolutionFunctionModel::setPrefix(IFunction *func, + const QString &prefix) { + if (isBackground(func)) { + if (m_backgroundPrefix) { + throw std::runtime_error("Model cannot have more than one background."); } - if (m_peakPrefixes->isEmpty()) { - m_peakPrefixes.reset(); + m_backgroundPrefix = prefix; + } else if (isConvolution(func)) { + if (func->nFunctions() != 0 && func->getFunction(0)->name() != "Resolution") { + throw std::runtime_error( + "Model's resolution function must have type Resolution."); + } else if (func->nFunctions() == 0) { + m_resolutionWorkspace = ""; + m_resolutionWorkspaceIndex = 0; } - } - if (!m_convolutionPrefix) { - throw std::runtime_error("Model doesn't contain a convolution."); + m_convolutionPrefix = prefix; + } else if (isDeltaFunction(func)) { + m_deltaFunctionPrefix = prefix; + } else if (isTempFunction(func)) { + m_tempFunctionPrefix = prefix; + } else if (isResolution(func)) { + m_resolutionWorkspace = func->getAttribute("Workspace").asString(); + m_resolutionWorkspaceIndex = func->getAttribute("WorkspaceIndex").asInt(); + } else if (isPeakFunction(func)) { + m_peakPrefixes->append(prefix); } } diff --git a/qt/widgets/common/test/ConvolutionFunctionModelTest.h b/qt/widgets/common/test/ConvolutionFunctionModelTest.h index 5022c152da5..73558d05631 100644 --- a/qt/widgets/common/test/ConvolutionFunctionModelTest.h +++ b/qt/widgets/common/test/ConvolutionFunctionModelTest.h @@ -31,6 +31,11 @@ public: TS_ASSERT(!model.getFitFunction()); } + void test_clear() { + ConvolutionFunctionModel model; + model.clear(); + } + void test_no_convolution() { ConvolutionFunctionModel model; TS_ASSERT_THROWS_EQUALS( @@ -92,7 +97,7 @@ public: ConvolutionFunctionModel model; TS_ASSERT_THROWS_NOTHING( model.setFunctionString("name=LinearBackground;(composite=Convolution;" - "name=Resolution;name=Gaussian)")); + "name=Resolution;name=Lorentzian)")); TS_ASSERT_EQUALS(model.backgroundPrefix()->toStdString(), "f0."); TS_ASSERT_EQUALS(model.convolutionPrefix()->toStdString(), "f1."); TS_ASSERT_EQUALS(model.resolutionWorkspace(), ""); @@ -399,21 +404,21 @@ public: "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( " + "Resolution,Workspace=abc,WorkspaceIndex=1,X=(),Y=();(name=" + "DeltaFunction,Height=1,Centre=0;(composite=ProductFunction,NumDeriv=" + "false;name=UserFunction,Formula=x*11.606/Temp/(1-exp( " "-(x*11.606/" "Temp))),Temp=100,ties=(Temp=100);(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," + "PeakCentre=0,FWHM=0;name=Lorentzian,Amplitude=1,PeakCentre=0,FWHM=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=DeltaFunction,Height=1,Centre=0;(composite=ProductFunction," "NumDeriv=false;name=UserFunction,Formula=x*11.606/Temp/(1-exp( " "-(x*11.606/" "Temp))),Temp=100,ties=(Temp=100);(name=Lorentzian,Amplitude=1," - "PeakCentre=0,FWHM=0;name=Lorentzian,Amplitude=1,PeakCentre=0,FWHM=0;" - "name=DeltaFunction,Height=1,Centre=0))))"); + "PeakCentre=0,FWHM=0;name=Lorentzian,Amplitude=1,PeakCentre=0,FWHM=0)))" + "))"); } void test_component_prefixes_set_correctly_without_temp_correction() { @@ -521,6 +526,33 @@ public: TS_ASSERT_EQUALS(model.tempFunctionPrefix().value().toStdString(), "f1.f1.f0."); } + + void test_component_prefixes_if_temp_and_delta_set() { + 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", + 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.peakPrefixes().value()[0].toStdString(), + "f1.f1.f1.f1."); + TS_ASSERT_EQUALS(model.tempFunctionPrefix().value().toStdString(), + "f1.f1.f1.f0."); + TS_ASSERT_EQUALS(model.deltaFunctionPrefix().value().toStdString(), + "f1.f1.f0."); + } }; #endif // MANTIDWIDGETS_CONVOLUTIONFUNCTIONMODELTEST_H_ -- GitLab