From 08b55d4c4747df1e6e2f3de3b802d1c6430b0ec0 Mon Sep 17 00:00:00 2001 From: Anthony Lim <anthony.lim@stfc.ac.uk> Date: Tue, 22 May 2018 13:55:54 +0100 Subject: [PATCH] refs #22423 ConvertFitFunction clang format --- .../API/inc/MantidAPI/FunctionProperty.h | 3 +- Framework/API/src/FunctionProperty.cpp | 17 +- .../MDAlgorithms/src/EvaluateMDFunction.cpp | 2 +- .../ConvertFitFunctionForMuonTFAsymmetry.h | 18 +- .../ConvertFitFunctionForMuonTFAsymmetry.cpp | 650 +++++++++--------- ...ConvertFitFunctionForMuonTFAsymmetryTest.h | 390 ++++++----- .../api/src/Exports/FunctionProperty.cpp | 18 +- 7 files changed, 564 insertions(+), 534 deletions(-) diff --git a/Framework/API/inc/MantidAPI/FunctionProperty.h b/Framework/API/inc/MantidAPI/FunctionProperty.h index 7a8035e9d95..0e777d97022 100644 --- a/Framework/API/inc/MantidAPI/FunctionProperty.h +++ b/Framework/API/inc/MantidAPI/FunctionProperty.h @@ -45,7 +45,8 @@ class MANTID_API_DLL FunctionProperty : public Kernel::PropertyWithValue<boost::shared_ptr<IFunction>> { public: /// Constructor. - FunctionProperty(const std::string &name, const unsigned int direction = Kernel::Direction::Input); + FunctionProperty(const std::string &name, + const unsigned int direction = Kernel::Direction::Input); /// Copy constructor FunctionProperty(const FunctionProperty &right); diff --git a/Framework/API/src/FunctionProperty.cpp b/Framework/API/src/FunctionProperty.cpp index a94dc4e1abf..815a820de4d 100644 --- a/Framework/API/src/FunctionProperty.cpp +++ b/Framework/API/src/FunctionProperty.cpp @@ -8,11 +8,11 @@ namespace API { * Sets the property names but initialises the function pointer to null. * @param name :: The name to assign to the property */ -FunctionProperty::FunctionProperty(const std::string &name,const unsigned int direction) +FunctionProperty::FunctionProperty(const std::string &name, + const unsigned int direction) : Kernel::PropertyWithValue<boost::shared_ptr<IFunction>>( name, boost::shared_ptr<IFunction>(), - Kernel::IValidator_sptr(new Kernel::NullValidator()), - direction) {} + Kernel::IValidator_sptr(new Kernel::NullValidator()), direction) {} /// Copy constructor FunctionProperty::FunctionProperty(const FunctionProperty &right) @@ -82,12 +82,11 @@ std::string FunctionProperty::setValue(const std::string &value) { * @returns A user level description of the problem or "" if it is valid. */ std::string FunctionProperty::isValid() const { - if (direction() == Kernel::Direction::Output) { - return ""; - } - else { - return isDefault() ? "Function is empty." : ""; - } + if (direction() == Kernel::Direction::Output) { + return ""; + } else { + return isDefault() ? "Function is empty." : ""; + } } /** Indicates if the function has not been created yet. diff --git a/Framework/MDAlgorithms/src/EvaluateMDFunction.cpp b/Framework/MDAlgorithms/src/EvaluateMDFunction.cpp index 4bfad98779e..caa5606c7d8 100644 --- a/Framework/MDAlgorithms/src/EvaluateMDFunction.cpp +++ b/Framework/MDAlgorithms/src/EvaluateMDFunction.cpp @@ -44,7 +44,7 @@ void EvaluateMDFunction::init() { "InputWorkspace", "", Direction::Input), "An input workspace that provides dimensions for the output."); declareProperty( - Kernel::make_unique<API::FunctionProperty>("Function",Direction::InOut), + Kernel::make_unique<API::FunctionProperty>("Function", Direction::InOut), "Parameters defining the fitting function and its initial values"); declareProperty( Kernel::make_unique<WorkspaceProperty<API::IMDHistoWorkspace>>( diff --git a/Framework/Muon/inc/MantidMuon/ConvertFitFunctionForMuonTFAsymmetry.h b/Framework/Muon/inc/MantidMuon/ConvertFitFunctionForMuonTFAsymmetry.h index f15635e81b6..7873f0b3d65 100644 --- a/Framework/Muon/inc/MantidMuon/ConvertFitFunctionForMuonTFAsymmetry.h +++ b/Framework/Muon/inc/MantidMuon/ConvertFitFunctionForMuonTFAsymmetry.h @@ -15,7 +15,8 @@ To be used as part of TF asymmetry calculations Required Properties: <UL> <LI> InputFunction - The function we want to change </LI> -<LI> NormalisationTable - The name of the table workspace that contains the normalization constants +<LI> NormalisationTable - The name of the table workspace that contains the +normalization constants </LI> <LI> WorkspaceList - The workspaces we are interested in </LI> <LI> Mode - If constructing or destructing the TF asymmetry function </LI> @@ -56,7 +57,8 @@ public: /// Summary of algorithms purpose const std::string summary() const override { return "This algorithm converts adds/removes " - "the normalisation to the fit function for calculating the TF asymmetry."; + "the normalisation to the fit function for calculating the TF " + "asymmetry."; } /// Algorithm's version for identification overriding a virtual method @@ -65,7 +67,7 @@ public: const std::string category() const override { return "Muon"; } /// Algorithm's seeAlso const std::vector<std::string> seeAlso() const override { - return{ "Fit", "EstimateMuonAsymmetryFromCounts","CalculateMuonAsymmetry"}; + return {"Fit", "EstimateMuonAsymmetryFromCounts", "CalculateMuonAsymmetry"}; } private: @@ -73,9 +75,13 @@ private: void init() override; void exec() override; std::map<std::string, std::string> validateInputs() override; - Mantid::API::IFunction_sptr getTFAsymmFitFunction(const Mantid::API::IFunction_sptr &original, const std::vector<double> norms); - Mantid::API::IFunction_sptr extractFromTFAsymmFitFunction(const Mantid::API::IFunction_sptr &original); - Mantid::API::IFunction_sptr extractUserFunction(const Mantid::API::IFunction_sptr &TFFunc); + Mantid::API::IFunction_sptr + getTFAsymmFitFunction(const Mantid::API::IFunction_sptr &original, + const std::vector<double> norms); + Mantid::API::IFunction_sptr + extractFromTFAsymmFitFunction(const Mantid::API::IFunction_sptr &original); + Mantid::API::IFunction_sptr + extractUserFunction(const Mantid::API::IFunction_sptr &TFFunc); void setOutput(const Mantid::API::IFunction_sptr &function); std::vector<double> getNorms(); }; diff --git a/Framework/Muon/src/ConvertFitFunctionForMuonTFAsymmetry.cpp b/Framework/Muon/src/ConvertFitFunctionForMuonTFAsymmetry.cpp index befc0337f83..b4943a69c08 100644 --- a/Framework/Muon/src/ConvertFitFunctionForMuonTFAsymmetry.cpp +++ b/Framework/Muon/src/ConvertFitFunctionForMuonTFAsymmetry.cpp @@ -20,328 +20,338 @@ #include <vector> namespace { - constexpr double MICROSECONDS_PER_SECOND{ 1000000.0 }; - constexpr double MUON_LIFETIME_MICROSECONDS{ - Mantid::PhysicalConstants::MuonLifetime * MICROSECONDS_PER_SECOND }; - constexpr bool FIX = false; // fix function needs false to work - const std::string INSERT_FUNCTION{"f0.f1.f1." }; - - std::string trimTie(const std::string stringTie) { - auto index = stringTie.find_first_of("."); - std::string domain = stringTie.substr(0,index); - std::string userFunc = stringTie.substr(9+index, std::string::npos); - return domain+userFunc; - } - - std::string rmInsertFunction(const std::string originalTie) { - auto stringTie = originalTie; - // check the tie only exists in the user function (f) - auto seperator = stringTie.find_first_of("="); - // the wrapped name added 9 characters - auto LHName = stringTie.substr(0, seperator); - LHName = trimTie(LHName); - // this one includes = sign - auto RHName = stringTie.substr(seperator, std::string::npos); - RHName = trimTie(RHName); - - return LHName+ RHName; - } - - template <typename T1> - int findName(const std::vector<std::string> &colNames, const T1 &name) { - for (size_t j = 0; j < colNames.size(); j++) { - if (colNames[j] == name) { - return static_cast<int>(j); - } - } - return -1; - } +constexpr double MICROSECONDS_PER_SECOND{1000000.0}; +constexpr double MUON_LIFETIME_MICROSECONDS{ + Mantid::PhysicalConstants::MuonLifetime * MICROSECONDS_PER_SECOND}; +constexpr bool FIX = false; // fix function needs false to work +const std::string INSERT_FUNCTION{"f0.f1.f1."}; + +std::string trimTie(const std::string stringTie) { + auto index = stringTie.find_first_of("."); + std::string domain = stringTie.substr(0, index); + std::string userFunc = stringTie.substr(9 + index, std::string::npos); + return domain + userFunc; +} + +std::string rmInsertFunction(const std::string originalTie) { + auto stringTie = originalTie; + // check the tie only exists in the user function (f) + auto seperator = stringTie.find_first_of("="); + // the wrapped name added 9 characters + auto LHName = stringTie.substr(0, seperator); + LHName = trimTie(LHName); + // this one includes = sign + auto RHName = stringTie.substr(seperator, std::string::npos); + RHName = trimTie(RHName); + + return LHName + RHName; +} +template <typename T1> +int findName(const std::vector<std::string> &colNames, const T1 &name) { + for (size_t j = 0; j < colNames.size(); j++) { + if (colNames[j] == name) { + return static_cast<int>(j); + } + } + return -1; +} } namespace Mantid { - namespace Algorithms { - - using namespace Kernel; - using namespace API; - using std::size_t; - - // Register the class into the algorithm factory - DECLARE_ALGORITHM(ConvertFitFunctionForMuonTFAsymmetry) - - /** Initialisation method. Declares properties to be used in algorithm. - * - */ - void ConvertFitFunctionForMuonTFAsymmetry::init() { - declareProperty(make_unique<FunctionProperty>("InputFunction"), - "The fitting function to be converted."); - // table of name, norms - // if construct -> read relevant norms into sorted list - declareProperty( - make_unique<API::WorkspaceProperty<API::ITableWorkspace>>( - "NormalisationTable", "", Direction::Input), - "Name of the table containing the normalisations for the asymmetries."); - // list of workspaces - declareProperty(Kernel::make_unique<Kernel::ArrayProperty<std::string>>( - "WorkspaceList", boost::make_shared<API::ADSValidator>()), - "An ordered list of workspaces (to get the initial values for the normalisations)."); - - std::vector<std::string> allowedModes{ "Construct", "Extract" }; - auto modeVal = boost::make_shared<Kernel::CompositeValidator>(); - modeVal->add(boost::make_shared<Kernel::StringListValidator>(allowedModes)); - modeVal->add(boost::make_shared<Kernel::MandatoryValidator<std::string>>()); - declareProperty("Mode", "Construct", modeVal, - "Mode to run in. Construct will convert the" - "input function into one suitable for calculating the" - " TF Asymmetry. Extract will find the original user function" - " from a function that is suitable for TF Asymmetry calculations."); - - declareProperty(make_unique<FunctionProperty>("OutputFunction",Direction::Output), - "The converted fitting function."); - } - - /* - * Validate the input parameters - * @returns map with keys corresponding to properties with errors and values - * containing the error messages. - */ - std::map<std::string, std::string> - ConvertFitFunctionForMuonTFAsymmetry::validateInputs() { - // create the map - std::map<std::string, std::string> result; - // check norm table is correct - API::ITableWorkspace_const_sptr tabWS = getProperty("NormalisationTable"); - - if (tabWS->columnCount() == 0) { - result["NormalisationTable"] = "Please provide a non-empty NormalisationTable."; - } - - // NormalisationTable should have three columns: (norm, name, method) - if (tabWS->columnCount() != 3) { - result["NormalisationTable"] = "NormalisationTable must have three columns"; - } - auto names = tabWS->getColumnNames(); - int normCount = 0; - int wsNamesCount = 0; - for (const std::string &name : names) { - - if (name == "norm") { - normCount += 1; - } - - if (name == "name") { - wsNamesCount += 1; - } - } - if (normCount == 0) { - result["NormalisationTable"] = "NormalisationTable needs norm column"; - } - if (wsNamesCount == 0) { - result["NormalisationTable"] = "NormalisationTable needs a name column"; - } - if (normCount > 1) { - result["NormalisationTable"] = - "NormalisationTable has " + std::to_string(normCount) + " norm columns"; - } - if (wsNamesCount > 1) { - result["PhaseTable"] = "PhaseTable has " + std::to_string(wsNamesCount) + - " name columns"; - } - // Check units, should be microseconds - return result; - } - - /** Executes the algorithm - * - */ - void ConvertFitFunctionForMuonTFAsymmetry::exec() { - IFunction_sptr inputFitFunction =getProperty("InputFunction"); - auto mode = getPropertyValue("Mode"); - if (mode == "Construct") { - std::vector<double> norms = getNorms(); - auto outputFitFunction = getTFAsymmFitFunction(inputFitFunction, norms); - setOutput(outputFitFunction); - } - else { - try { - auto outputFitFunction = extractFromTFAsymmFitFunction(inputFitFunction); - setOutput(outputFitFunction); - } - catch(...){ - throw std::runtime_error("The input function was not of the form N*(1+f)+A*exp(-lambda*t)"); - } - - } - } - - void ConvertFitFunctionForMuonTFAsymmetry::setOutput( - const Mantid::API::IFunction_sptr &function) { - IFunction_sptr outputFitFunction = function; - const std::vector<std::string> wsNames = getProperty("WorkspaceList"); - if( wsNames.size()==1){ - // if single domain func, strip off multi domain - auto TFFunc = boost::dynamic_pointer_cast<CompositeFunction>(function); - outputFitFunction = TFFunc->getFunction(0); - } - setProperty("OutputFunction", outputFitFunction); - } - /** Extracts the user's original function f from the normalisation function N(1+f)+expDecay - * and adds in the ties - * @param original :: [input] normalisation function - * @return :: user function - */ - Mantid::API::IFunction_sptr ConvertFitFunctionForMuonTFAsymmetry::extractFromTFAsymmFitFunction( - const Mantid::API::IFunction_sptr &original) { - - auto multi = boost::make_shared<MultiDomainFunction>(); - IFunction_sptr tmp = original; - - size_t numDomains = original->getNumberDomains(); - for (size_t j = 0; j < numDomains; j++) { - auto TFFunc = boost::dynamic_pointer_cast<CompositeFunction>(original); - if (numDomains >1){ - // get correct domain - tmp = TFFunc->getFunction(j); - multi->setDomainIndex(j, j); - } - IFunction_sptr userFunc = extractUserFunction(tmp); - multi->addFunction(userFunc); - } - // if multi data set we need to do the ties manually - if (numDomains > 1) { - auto originalNames = original->getParameterNames(); - for (auto name : originalNames) { - auto index = original->parameterIndex(name); - auto originalTie = original->getTie(index); - if (originalTie) { - auto stringTie = originalTie->asString(); - // check the tie only exists in the user function (f) - auto start = stringTie.find_first_of(".")+1; - auto end = stringTie.find_first_of("="); - // the wrapped name added 9 characters - auto LHName = stringTie.substr(start, 9); - // need to do in 2 steps - auto RHName = stringTie.substr(end, std::string::npos); - - start = RHName.find_first_of(".")+1; - RHName = RHName.substr(start,9); - if (LHName == INSERT_FUNCTION && LHName == RHName) { - //get new tie - auto newTie = rmInsertFunction(stringTie); - multi->addTies(newTie); - } - } - } - } - - return boost::dynamic_pointer_cast<IFunction>(multi); - - } - /** Extracts the user's original function f from the normalisation function N(1+f)+expDecay - * @param original :: [input] normalisation function - * @return :: user function - */ - - IFunction_sptr ConvertFitFunctionForMuonTFAsymmetry::extractUserFunction(const IFunction_sptr &TFFuncIn) { - // N(1+g) + exp - auto TFFunc = boost::dynamic_pointer_cast<CompositeFunction>(TFFuncIn); - - // getFunction(0) -> N(1+g) - TFFunc = boost::dynamic_pointer_cast<CompositeFunction>(TFFunc->getFunction(0)); - - // getFunction(1) -> 1+g - TFFunc = boost::dynamic_pointer_cast<CompositeFunction>(TFFunc->getFunction(1)); - - // getFunction(1) -> g - return TFFunc->getFunction(1); - } - - /** Get the nomralisation constants from the table - * the order is the same as the workspace list - * @return :: vector of normals - */ - std::vector<double> ConvertFitFunctionForMuonTFAsymmetry::getNorms() { - API::ITableWorkspace_sptr table = getProperty("NormalisationTable"); - const std::vector<std::string> wsNames = getProperty("WorkspaceList"); - - std::vector<double> norms(wsNames.size() ,0); - auto colNames = table->getColumnNames(); - auto wsNamesIndex = findName(colNames, "name"); - auto normIndex = findName(colNames, "norm"); - - for (size_t row = 0; row < table->rowCount(); row++) { - for (size_t wsPosition = 0; wsPosition < wsNames.size();wsPosition++) { - std::string wsName = wsNames[wsPosition]; - std::replace(wsName.begin(), wsName.end(), ' ', ';'); - if (table->String(row, wsNamesIndex) == wsName) { - norms[wsPosition] = table->Double(row, normIndex); - } - } - } - - return norms; - } - /** Gets the fitting function for TFAsymmetry fit - * @param original :: The user function f - * @param norms :: vector of normalization constants - * @returns :: The normalisation function N(1+f) +ExpDecay - */ - Mantid::API::IFunction_sptr ConvertFitFunctionForMuonTFAsymmetry::getTFAsymmFitFunction( - const Mantid::API::IFunction_sptr &original, const std::vector<double> norms) { - auto multi = boost::make_shared<MultiDomainFunction>(); - auto tmp = boost::dynamic_pointer_cast<MultiDomainFunction>(original); - size_t numDomains = original->getNumberDomains(); - for (size_t j = 0; j < numDomains; j++) { - IFunction_sptr userFunc; - auto constant = FunctionFactory::Instance().createInitialized( - "name = FlatBackground, A0 = 1.0; ties=(f0.A0=1)"); - if (numDomains == 1) { - userFunc = original; - } - else { - userFunc = tmp->getFunction(j); - multi->setDomainIndex(j, j); - } - auto inBrace = boost::make_shared<CompositeFunction>(); - inBrace->addFunction(constant); - inBrace->addFunction(userFunc); - auto norm = FunctionFactory::Instance().createInitialized( - "composite=CompositeFunction,NumDeriv=true;name = FlatBackground, A0 " - "=" + - std::to_string(norms[j])); - auto product = boost::dynamic_pointer_cast<CompositeFunction>( - FunctionFactory::Instance().createFunction("ProductFunction")); - product->addFunction(norm); - product->addFunction(inBrace); - auto composite = boost::dynamic_pointer_cast<CompositeFunction>( - FunctionFactory::Instance().createFunction("CompositeFunction")); - constant = FunctionFactory::Instance().createInitialized( - "name = ExpDecayMuon, A = 0.0, Lambda = -" + std::to_string(MUON_LIFETIME_MICROSECONDS) + ";ties = (f0.A = 0.0, f0.Lambda = -" + std::to_string(MUON_LIFETIME_MICROSECONDS) + ")"); - composite->addFunction(product); - composite->addFunction(constant); - multi->addFunction(composite); - } - // if multi data set we need to do the ties manually - if (numDomains > 1) { - auto originalNames = original->getParameterNames(); - for (auto name : originalNames) { - auto index = original->parameterIndex(name); - auto originalTie = original->getTie(index); - if (originalTie) { - auto stringTie = originalTie->asString(); - // change name to reflect new postion - auto insertPosition = stringTie.find_first_of("."); - stringTie.insert(insertPosition + 1, INSERT_FUNCTION); - // need to change the other side of = - insertPosition = stringTie.find_first_of("="); - insertPosition = stringTie.find_first_of(".", insertPosition); - stringTie.insert(insertPosition + 1, INSERT_FUNCTION); - multi->addTies(stringTie); - } - } - } - - return boost::dynamic_pointer_cast<IFunction>(multi); - } - } // namespace Algorithm +namespace Algorithms { + +using namespace Kernel; +using namespace API; +using std::size_t; + +// Register the class into the algorithm factory +DECLARE_ALGORITHM(ConvertFitFunctionForMuonTFAsymmetry) + +/** Initialisation method. Declares properties to be used in algorithm. + * + */ +void ConvertFitFunctionForMuonTFAsymmetry::init() { + declareProperty(make_unique<FunctionProperty>("InputFunction"), + "The fitting function to be converted."); + // table of name, norms + // if construct -> read relevant norms into sorted list + declareProperty( + make_unique<API::WorkspaceProperty<API::ITableWorkspace>>( + "NormalisationTable", "", Direction::Input), + "Name of the table containing the normalisations for the asymmetries."); + // list of workspaces + declareProperty(Kernel::make_unique<Kernel::ArrayProperty<std::string>>( + "WorkspaceList", boost::make_shared<API::ADSValidator>()), + "An ordered list of workspaces (to get the initial values " + "for the normalisations)."); + + std::vector<std::string> allowedModes{"Construct", "Extract"}; + auto modeVal = boost::make_shared<Kernel::CompositeValidator>(); + modeVal->add(boost::make_shared<Kernel::StringListValidator>(allowedModes)); + modeVal->add(boost::make_shared<Kernel::MandatoryValidator<std::string>>()); + declareProperty( + "Mode", "Construct", modeVal, + "Mode to run in. Construct will convert the" + "input function into one suitable for calculating the" + " TF Asymmetry. Extract will find the original user function" + " from a function that is suitable for TF Asymmetry calculations."); + + declareProperty( + make_unique<FunctionProperty>("OutputFunction", Direction::Output), + "The converted fitting function."); +} + +/* +* Validate the input parameters +* @returns map with keys corresponding to properties with errors and values +* containing the error messages. +*/ +std::map<std::string, std::string> +ConvertFitFunctionForMuonTFAsymmetry::validateInputs() { + // create the map + std::map<std::string, std::string> result; + // check norm table is correct + API::ITableWorkspace_const_sptr tabWS = getProperty("NormalisationTable"); + + if (tabWS->columnCount() == 0) { + result["NormalisationTable"] = + "Please provide a non-empty NormalisationTable."; + } + + // NormalisationTable should have three columns: (norm, name, method) + if (tabWS->columnCount() != 3) { + result["NormalisationTable"] = "NormalisationTable must have three columns"; + } + auto names = tabWS->getColumnNames(); + int normCount = 0; + int wsNamesCount = 0; + for (const std::string &name : names) { + + if (name == "norm") { + normCount += 1; + } + + if (name == "name") { + wsNamesCount += 1; + } + } + if (normCount == 0) { + result["NormalisationTable"] = "NormalisationTable needs norm column"; + } + if (wsNamesCount == 0) { + result["NormalisationTable"] = "NormalisationTable needs a name column"; + } + if (normCount > 1) { + result["NormalisationTable"] = + "NormalisationTable has " + std::to_string(normCount) + " norm columns"; + } + if (wsNamesCount > 1) { + result["PhaseTable"] = + "PhaseTable has " + std::to_string(wsNamesCount) + " name columns"; + } + // Check units, should be microseconds + return result; +} + +/** Executes the algorithm + * + */ +void ConvertFitFunctionForMuonTFAsymmetry::exec() { + IFunction_sptr inputFitFunction = getProperty("InputFunction"); + auto mode = getPropertyValue("Mode"); + if (mode == "Construct") { + std::vector<double> norms = getNorms(); + auto outputFitFunction = getTFAsymmFitFunction(inputFitFunction, norms); + setOutput(outputFitFunction); + } else { + try { + auto outputFitFunction = extractFromTFAsymmFitFunction(inputFitFunction); + setOutput(outputFitFunction); + } catch (...) { + throw std::runtime_error( + "The input function was not of the form N*(1+f)+A*exp(-lambda*t)"); + } + } +} + +void ConvertFitFunctionForMuonTFAsymmetry::setOutput( + const Mantid::API::IFunction_sptr &function) { + IFunction_sptr outputFitFunction = function; + const std::vector<std::string> wsNames = getProperty("WorkspaceList"); + if (wsNames.size() == 1) { + // if single domain func, strip off multi domain + auto TFFunc = boost::dynamic_pointer_cast<CompositeFunction>(function); + outputFitFunction = TFFunc->getFunction(0); + } + setProperty("OutputFunction", outputFitFunction); +} +/** Extracts the user's original function f from the normalisation function +* N(1+f)+expDecay +* and adds in the ties +* @param original :: [input] normalisation function +* @return :: user function +*/ +Mantid::API::IFunction_sptr +ConvertFitFunctionForMuonTFAsymmetry::extractFromTFAsymmFitFunction( + const Mantid::API::IFunction_sptr &original) { + + auto multi = boost::make_shared<MultiDomainFunction>(); + IFunction_sptr tmp = original; + + size_t numDomains = original->getNumberDomains(); + for (size_t j = 0; j < numDomains; j++) { + auto TFFunc = boost::dynamic_pointer_cast<CompositeFunction>(original); + if (numDomains > 1) { + // get correct domain + tmp = TFFunc->getFunction(j); + multi->setDomainIndex(j, j); + } + IFunction_sptr userFunc = extractUserFunction(tmp); + multi->addFunction(userFunc); + } + // if multi data set we need to do the ties manually + if (numDomains > 1) { + auto originalNames = original->getParameterNames(); + for (auto name : originalNames) { + auto index = original->parameterIndex(name); + auto originalTie = original->getTie(index); + if (originalTie) { + auto stringTie = originalTie->asString(); + // check the tie only exists in the user function (f) + auto start = stringTie.find_first_of(".") + 1; + auto end = stringTie.find_first_of("="); + // the wrapped name added 9 characters + auto LHName = stringTie.substr(start, 9); + // need to do in 2 steps + auto RHName = stringTie.substr(end, std::string::npos); + + start = RHName.find_first_of(".") + 1; + RHName = RHName.substr(start, 9); + if (LHName == INSERT_FUNCTION && LHName == RHName) { + // get new tie + auto newTie = rmInsertFunction(stringTie); + multi->addTies(newTie); + } + } + } + } + + return boost::dynamic_pointer_cast<IFunction>(multi); +} +/** Extracts the user's original function f from the normalisation function + * N(1+f)+expDecay + * @param original :: [input] normalisation function + * @return :: user function + */ + +IFunction_sptr ConvertFitFunctionForMuonTFAsymmetry::extractUserFunction( + const IFunction_sptr &TFFuncIn) { + // N(1+g) + exp + auto TFFunc = boost::dynamic_pointer_cast<CompositeFunction>(TFFuncIn); + + // getFunction(0) -> N(1+g) + TFFunc = + boost::dynamic_pointer_cast<CompositeFunction>(TFFunc->getFunction(0)); + + // getFunction(1) -> 1+g + TFFunc = + boost::dynamic_pointer_cast<CompositeFunction>(TFFunc->getFunction(1)); + + // getFunction(1) -> g + return TFFunc->getFunction(1); +} + +/** Get the nomralisation constants from the table +* the order is the same as the workspace list +* @return :: vector of normals +*/ +std::vector<double> ConvertFitFunctionForMuonTFAsymmetry::getNorms() { + API::ITableWorkspace_sptr table = getProperty("NormalisationTable"); + const std::vector<std::string> wsNames = getProperty("WorkspaceList"); + + std::vector<double> norms(wsNames.size(), 0); + auto colNames = table->getColumnNames(); + auto wsNamesIndex = findName(colNames, "name"); + auto normIndex = findName(colNames, "norm"); + + for (size_t row = 0; row < table->rowCount(); row++) { + for (size_t wsPosition = 0; wsPosition < wsNames.size(); wsPosition++) { + std::string wsName = wsNames[wsPosition]; + std::replace(wsName.begin(), wsName.end(), ' ', ';'); + if (table->String(row, wsNamesIndex) == wsName) { + norms[wsPosition] = table->Double(row, normIndex); + } + } + } + + return norms; +} +/** Gets the fitting function for TFAsymmetry fit +* @param original :: The user function f +* @param norms :: vector of normalization constants +* @returns :: The normalisation function N(1+f) +ExpDecay +*/ +Mantid::API::IFunction_sptr +ConvertFitFunctionForMuonTFAsymmetry::getTFAsymmFitFunction( + const Mantid::API::IFunction_sptr &original, + const std::vector<double> norms) { + auto multi = boost::make_shared<MultiDomainFunction>(); + auto tmp = boost::dynamic_pointer_cast<MultiDomainFunction>(original); + size_t numDomains = original->getNumberDomains(); + for (size_t j = 0; j < numDomains; j++) { + IFunction_sptr userFunc; + auto constant = FunctionFactory::Instance().createInitialized( + "name = FlatBackground, A0 = 1.0; ties=(f0.A0=1)"); + if (numDomains == 1) { + userFunc = original; + } else { + userFunc = tmp->getFunction(j); + multi->setDomainIndex(j, j); + } + auto inBrace = boost::make_shared<CompositeFunction>(); + inBrace->addFunction(constant); + inBrace->addFunction(userFunc); + auto norm = FunctionFactory::Instance().createInitialized( + "composite=CompositeFunction,NumDeriv=true;name = FlatBackground, A0 " + "=" + + std::to_string(norms[j])); + auto product = boost::dynamic_pointer_cast<CompositeFunction>( + FunctionFactory::Instance().createFunction("ProductFunction")); + product->addFunction(norm); + product->addFunction(inBrace); + auto composite = boost::dynamic_pointer_cast<CompositeFunction>( + FunctionFactory::Instance().createFunction("CompositeFunction")); + constant = FunctionFactory::Instance().createInitialized( + "name = ExpDecayMuon, A = 0.0, Lambda = -" + + std::to_string(MUON_LIFETIME_MICROSECONDS) + + ";ties = (f0.A = 0.0, f0.Lambda = -" + + std::to_string(MUON_LIFETIME_MICROSECONDS) + ")"); + composite->addFunction(product); + composite->addFunction(constant); + multi->addFunction(composite); + } + // if multi data set we need to do the ties manually + if (numDomains > 1) { + auto originalNames = original->getParameterNames(); + for (auto name : originalNames) { + auto index = original->parameterIndex(name); + auto originalTie = original->getTie(index); + if (originalTie) { + auto stringTie = originalTie->asString(); + // change name to reflect new postion + auto insertPosition = stringTie.find_first_of("."); + stringTie.insert(insertPosition + 1, INSERT_FUNCTION); + // need to change the other side of = + insertPosition = stringTie.find_first_of("="); + insertPosition = stringTie.find_first_of(".", insertPosition); + stringTie.insert(insertPosition + 1, INSERT_FUNCTION); + multi->addTies(stringTie); + } + } + } + + return boost::dynamic_pointer_cast<IFunction>(multi); +} +} // namespace Algorithm } // namespace Mantid diff --git a/Framework/Muon/test/ConvertFitFunctionForMuonTFAsymmetryTest.h b/Framework/Muon/test/ConvertFitFunctionForMuonTFAsymmetryTest.h index fbd9bc459de..0a0defb532d 100644 --- a/Framework/Muon/test/ConvertFitFunctionForMuonTFAsymmetryTest.h +++ b/Framework/Muon/test/ConvertFitFunctionForMuonTFAsymmetryTest.h @@ -16,13 +16,12 @@ using Mantid::Algorithms::ConvertFitFunctionForMuonTFAsymmetry; const std::string outputName = "EstimateMuonAsymmetryFromCounts_Output"; -namespace{ +namespace { -const std::string NORM_PARAM {"f0.f0.f0.A0"}; +const std::string NORM_PARAM{"f0.f0.f0.A0"}; const std::string OFFSET_PARAM{"f0.f1.f0.A0"}; -const std::string USER_FUNC {"f0.f1.f1."}; -const std::string EXP_PARAM {"f1.A"}; - +const std::string USER_FUNC{"f0.f1.f1."}; +const std::string EXP_PARAM{"f1.A"}; struct yData { double operator()(const double x, size_t) { @@ -38,28 +37,27 @@ struct eData { MatrixWorkspace_sptr createWorkspace() { MatrixWorkspace_sptr ws = WorkspaceCreationHelper::create2DWorkspaceFromFunction( - yData(), 1, 0.0, 1.0, - (1.0 / 50.), true, eData()); + yData(), 1, 0.0, 1.0, (1.0 / 50.), true, eData()); return ws; } - -ITableWorkspace_sptr genTable(){ -ITableWorkspace_sptr table = WorkspaceFactory::Instance().createTable(); -table->addColumn("double","norm"); -table->addColumn("str","name"); -table->addColumn("str","method"); -std::vector<std::string> names= {"ws1","ws2","ws3"}; -for (size_t j =0;j<names.size();j++){ -TableRow row = table->appendRow(); -row<<double(j+1)<<names[j]<<"test"; -} -return table; +ITableWorkspace_sptr genTable() { + ITableWorkspace_sptr table = WorkspaceFactory::Instance().createTable(); + table->addColumn("double", "norm"); + table->addColumn("str", "name"); + table->addColumn("str", "method"); + std::vector<std::string> names = {"ws1", "ws2", "ws3"}; + for (size_t j = 0; j < names.size(); j++) { + TableRow row = table->appendRow(); + row << double(j + 1) << names[j] << "test"; + } + return table; } -IAlgorithm_sptr setUpAlg(std::vector<std::string> wsNames, const IFunction_sptr &func) { - IAlgorithm_sptr asymmAlg = - AlgorithmManager::Instance().create("ConvertFitFunctionForMuonTFAsymmetry"); +IAlgorithm_sptr setUpAlg(std::vector<std::string> wsNames, + const IFunction_sptr &func) { + IAlgorithm_sptr asymmAlg = AlgorithmManager::Instance().create( + "ConvertFitFunctionForMuonTFAsymmetry"); asymmAlg->initialize(); asymmAlg->setChild(true); asymmAlg->setProperty("WorkspaceList", wsNames); @@ -69,31 +67,30 @@ IAlgorithm_sptr setUpAlg(std::vector<std::string> wsNames, const IFunction_sptr return asymmAlg; } - -void genData(){ - auto ws1 = createWorkspace(); - AnalysisDataService::Instance().addOrReplace("ws1",ws1); - AnalysisDataService::Instance().addOrReplace("ws2",ws1); - AnalysisDataService::Instance().addOrReplace("ws3",ws1); +void genData() { + auto ws1 = createWorkspace(); + AnalysisDataService::Instance().addOrReplace("ws1", ws1); + AnalysisDataService::Instance().addOrReplace("ws2", ws1); + AnalysisDataService::Instance().addOrReplace("ws3", ws1); } -IFunction_sptr doFit(const IFunction_sptr &func, int iterations,std::vector<std::string> wsNames){ - - IAlgorithm_sptr fit = AlgorithmManager::Instance().create("Fit"); +IFunction_sptr doFit(const IFunction_sptr &func, int iterations, + std::vector<std::string> wsNames) { + + IAlgorithm_sptr fit = AlgorithmManager::Instance().create("Fit"); fit->initialize(); - fit->setProperty("Function",func); + fit->setProperty("Function", func); fit->setProperty("InputWorkspace", wsNames[0]); - if(wsNames.size()>1){ - - fit->setProperty("InputWorkspace_1", wsNames[1]); + if (wsNames.size() > 1) { + + fit->setProperty("InputWorkspace_1", wsNames[1]); } - fit->setProperty("Output","fit"); - fit->setProperty("MaxIterations",iterations); + fit->setProperty("Output", "fit"); + fit->setProperty("MaxIterations", iterations); fit->execute(); std::string funcString = fit->getPropertyValue("Function"); return FunctionFactory::Instance().createInitialized(funcString); -} - +} } class ConvertFitFunctionForMuonTFAsymmetryTest : public CxxTest::TestSuite { @@ -101,7 +98,7 @@ public: // This pair of boilerplate methods prevent the suite being created statically // This means the constructor isn't called when running other tests static ConvertFitFunctionForMuonTFAsymmetryTest *createSuite() { - return new ConvertFitFunctionForMuonTFAsymmetryTest(); + return new ConvertFitFunctionForMuonTFAsymmetryTest(); } static void destroySuite(ConvertFitFunctionForMuonTFAsymmetryTest *suite) { delete suite; @@ -112,16 +109,18 @@ public: void testInit() { genData(); std::vector<std::string> wsNames = {"ws1"}; - IFunction_sptr func = FunctionFactory::Instance().createInitialized("name=LinearBackground,A0=0,A1=2;ties =(f0.A1=2)"); - IAlgorithm_sptr alg = setUpAlg(wsNames,func); + IFunction_sptr func = FunctionFactory::Instance().createInitialized( + "name=LinearBackground,A0=0,A1=2;ties =(f0.A1=2)"); + IAlgorithm_sptr alg = setUpAlg(wsNames, func); TS_ASSERT(alg->isInitialized()) } void test_Execute() { genData(); std::vector<std::string> wsNames = {"ws1"}; - IFunction_sptr func = FunctionFactory::Instance().createInitialized("name=LinearBackground,A0=0,A1=2;ties =(f0.A1=2)"); - IAlgorithm_sptr alg = setUpAlg(wsNames,func); + IFunction_sptr func = FunctionFactory::Instance().createInitialized( + "name=LinearBackground,A0=0,A1=2;ties =(f0.A1=2)"); + IAlgorithm_sptr alg = setUpAlg(wsNames, func); TS_ASSERT(alg->isInitialized()) TS_ASSERT_THROWS_NOTHING(alg->execute()); TS_ASSERT(alg->isExecuted()); @@ -130,314 +129,329 @@ public: void test_1D() { genData(); std::vector<std::string> wsNames = {"ws1"}; - IFunction_sptr func = FunctionFactory::Instance().createInitialized("name=LinearBackground,A0=0,A1=2;"); - IAlgorithm_sptr alg = setUpAlg(wsNames,func); + IFunction_sptr func = FunctionFactory::Instance().createInitialized( + "name=LinearBackground,A0=0,A1=2;"); + IAlgorithm_sptr alg = setUpAlg(wsNames, func); TS_ASSERT(alg->isInitialized()) TS_ASSERT_THROWS_NOTHING(alg->execute()); TS_ASSERT(alg->isExecuted()); IFunction_sptr normFunc = alg->getProperty("OutputFunction"); - auto outFunc = doFit(normFunc,0,wsNames); - TS_ASSERT_DELTA(outFunc->getParameter(OFFSET_PARAM),1.,0.0001); - TS_ASSERT_DELTA(outFunc->getParameter(EXP_PARAM),0.0,0.0001); - TS_ASSERT_DELTA(outFunc->getParameter(USER_FUNC+"A1"),2.0,0.0001); - } - + auto outFunc = doFit(normFunc, 0, wsNames); + TS_ASSERT_DELTA(outFunc->getParameter(OFFSET_PARAM), 1., 0.0001); + TS_ASSERT_DELTA(outFunc->getParameter(EXP_PARAM), 0.0, 0.0001); + TS_ASSERT_DELTA(outFunc->getParameter(USER_FUNC + "A1"), 2.0, 0.0001); + } void test_1DFix() { genData(); std::vector<std::string> wsNames = {"ws1"}; - IFunction_sptr func = FunctionFactory::Instance().createInitialized("name=LinearBackground,A0=0,A1=2;ties =(f0.A1=2)"); - IAlgorithm_sptr alg = setUpAlg(wsNames,func); + IFunction_sptr func = FunctionFactory::Instance().createInitialized( + "name=LinearBackground,A0=0,A1=2;ties =(f0.A1=2)"); + IAlgorithm_sptr alg = setUpAlg(wsNames, func); TS_ASSERT(alg->isInitialized()) TS_ASSERT_THROWS_NOTHING(alg->execute()); TS_ASSERT(alg->isExecuted()); IFunction_sptr normFunc = alg->getProperty("OutputFunction"); - auto outFunc = doFit(normFunc,200,wsNames); - TS_ASSERT_DELTA(outFunc->getParameter(OFFSET_PARAM),1.,0.0001); - TS_ASSERT_DELTA(outFunc->getParameter(EXP_PARAM),0.0,0.0001); - TS_ASSERT_DELTA(outFunc->getParameter(USER_FUNC+"A1"),2.0,0.0001); - TS_ASSERT_DIFFERS(outFunc->getParameter(USER_FUNC+"A0"),0.0); - + auto outFunc = doFit(normFunc, 200, wsNames); + TS_ASSERT_DELTA(outFunc->getParameter(OFFSET_PARAM), 1., 0.0001); + TS_ASSERT_DELTA(outFunc->getParameter(EXP_PARAM), 0.0, 0.0001); + TS_ASSERT_DELTA(outFunc->getParameter(USER_FUNC + "A1"), 2.0, 0.0001); + TS_ASSERT_DIFFERS(outFunc->getParameter(USER_FUNC + "A0"), 0.0); } void test_1DTie() { genData(); std::vector<std::string> wsNames = {"ws1"}; - IFunction_sptr func = FunctionFactory::Instance().createInitialized("name=LinearBackground,A0=0,A1=2;name=LinearBackground,A0=0,A1=4;ties =(f0.A1=f1.A1)"); - IAlgorithm_sptr alg = setUpAlg(wsNames,func); + IFunction_sptr func = FunctionFactory::Instance().createInitialized( + "name=LinearBackground,A0=0,A1=2;name=LinearBackground,A0=0,A1=4;ties " + "=(f0.A1=f1.A1)"); + IAlgorithm_sptr alg = setUpAlg(wsNames, func); TS_ASSERT(alg->isInitialized()) TS_ASSERT_THROWS_NOTHING(alg->execute()); TS_ASSERT(alg->isExecuted()); IFunction_sptr normFunc = alg->getProperty("OutputFunction"); - auto outFunc = doFit(normFunc,200,wsNames); - TS_ASSERT_DELTA(outFunc->getParameter(OFFSET_PARAM),1.,0.0001); - TS_ASSERT_DELTA(outFunc->getParameter(EXP_PARAM),0.0,0.0001); - TS_ASSERT_EQUALS(outFunc->getParameter(USER_FUNC+"f0.A1"),outFunc->getParameter(USER_FUNC+"f1.A1")); - TS_ASSERT_DIFFERS(outFunc->getParameter(USER_FUNC+"f0.A0"),func->getParameter("f0.A0")); - TS_ASSERT_DIFFERS(outFunc->getParameter(USER_FUNC+"f1.A0"),func->getParameter("f1.A0")); - + auto outFunc = doFit(normFunc, 200, wsNames); + TS_ASSERT_DELTA(outFunc->getParameter(OFFSET_PARAM), 1., 0.0001); + TS_ASSERT_DELTA(outFunc->getParameter(EXP_PARAM), 0.0, 0.0001); + TS_ASSERT_EQUALS(outFunc->getParameter(USER_FUNC + "f0.A1"), + outFunc->getParameter(USER_FUNC + "f1.A1")); + TS_ASSERT_DIFFERS(outFunc->getParameter(USER_FUNC + "f0.A0"), + func->getParameter("f0.A0")); + TS_ASSERT_DIFFERS(outFunc->getParameter(USER_FUNC + "f1.A0"), + func->getParameter("f1.A0")); } // tests for multi domain void test_2D() { genData(); - std::vector<std::string> wsNames = {"ws1","ws2"}; + std::vector<std::string> wsNames = {"ws1", "ws2"}; std::string multiFuncString = "composite=MultiDomainFunction,NumDeriv=1;"; multiFuncString += "name=LinearBackground, $domains=i,A0=0,A1=1;"; multiFuncString += "name=LinearBackground, $domains=i,A0=2,A1=3;"; - IFunction_sptr multiFunc = FunctionFactory::Instance().createInitialized(multiFuncString); + IFunction_sptr multiFunc = + FunctionFactory::Instance().createInitialized(multiFuncString); - IAlgorithm_sptr alg = setUpAlg(wsNames,multiFunc); + IAlgorithm_sptr alg = setUpAlg(wsNames, multiFunc); TS_ASSERT(alg->isInitialized()) TS_ASSERT_THROWS_NOTHING(alg->execute()); TS_ASSERT(alg->isExecuted()); - IFunction_sptr normFunc = doFit(alg->getProperty("OutputFunction"),0,wsNames); - - TS_ASSERT_DELTA(normFunc->getParameter("f0."+NORM_PARAM),1.,0.0001); - TS_ASSERT_DELTA(normFunc->getParameter("f0."+OFFSET_PARAM),1.,0.0001); - TS_ASSERT_DELTA(normFunc->getParameter("f0."+EXP_PARAM),0.0,0.0001); - - TS_ASSERT_DELTA(normFunc->getParameter("f0."+USER_FUNC+"A0"),0.0,0.0001); - TS_ASSERT_DELTA(normFunc->getParameter("f0."+USER_FUNC+"A1"),1.0,0.0001); - - - TS_ASSERT_DELTA(normFunc->getParameter("f1."+NORM_PARAM),2.,0.0001); - TS_ASSERT_DELTA(normFunc->getParameter("f1."+OFFSET_PARAM),1.,0.0001); - TS_ASSERT_DELTA(normFunc->getParameter("f1."+EXP_PARAM),0.0,0.0001); - - TS_ASSERT_DELTA(normFunc->getParameter("f1."+USER_FUNC+"A0"),2.0,0.0001); - TS_ASSERT_DELTA(normFunc->getParameter("f1."+USER_FUNC+"A1"),3.0,0.0001); - + IFunction_sptr normFunc = + doFit(alg->getProperty("OutputFunction"), 0, wsNames); + + TS_ASSERT_DELTA(normFunc->getParameter("f0." + NORM_PARAM), 1., 0.0001); + TS_ASSERT_DELTA(normFunc->getParameter("f0." + OFFSET_PARAM), 1., 0.0001); + TS_ASSERT_DELTA(normFunc->getParameter("f0." + EXP_PARAM), 0.0, 0.0001); + + TS_ASSERT_DELTA(normFunc->getParameter("f0." + USER_FUNC + "A0"), 0.0, + 0.0001); + TS_ASSERT_DELTA(normFunc->getParameter("f0." + USER_FUNC + "A1"), 1.0, + 0.0001); + + TS_ASSERT_DELTA(normFunc->getParameter("f1." + NORM_PARAM), 2., 0.0001); + TS_ASSERT_DELTA(normFunc->getParameter("f1." + OFFSET_PARAM), 1., 0.0001); + TS_ASSERT_DELTA(normFunc->getParameter("f1." + EXP_PARAM), 0.0, 0.0001); + + TS_ASSERT_DELTA(normFunc->getParameter("f1." + USER_FUNC + "A0"), 2.0, + 0.0001); + TS_ASSERT_DELTA(normFunc->getParameter("f1." + USER_FUNC + "A1"), 3.0, + 0.0001); } void test_2DFix() { genData(); - std::vector<std::string> wsNames = {"ws1","ws2"}; + std::vector<std::string> wsNames = {"ws1", "ws2"}; std::string multiFuncString = "composite=MultiDomainFunction,NumDeriv=1;"; multiFuncString += "name=LinearBackground, $domains=i,A0=0,A1=1.5;"; multiFuncString += "name=LinearBackground, $domains=i,A0=2,A1=3;"; - IFunction_sptr multiFunc = FunctionFactory::Instance().createInitialized(multiFuncString); + IFunction_sptr multiFunc = + FunctionFactory::Instance().createInitialized(multiFuncString); multiFunc->addTies("f0.A1=1.5"); - IAlgorithm_sptr alg = setUpAlg(wsNames,multiFunc); + IAlgorithm_sptr alg = setUpAlg(wsNames, multiFunc); TS_ASSERT(alg->isInitialized()) TS_ASSERT_THROWS_NOTHING(alg->execute()); TS_ASSERT(alg->isExecuted()); - IFunction_sptr normFunc = doFit(alg->getProperty("OutputFunction"),200,wsNames); + IFunction_sptr normFunc = + doFit(alg->getProperty("OutputFunction"), 200, wsNames); - TS_ASSERT_DIFFERS(normFunc->getParameter("f0."+NORM_PARAM),1.); - TS_ASSERT_DELTA(normFunc->getParameter( "f0."+OFFSET_PARAM),1.,0.0001); - TS_ASSERT_DELTA(normFunc->getParameter( "f0."+EXP_PARAM),0.0,0.0001); + TS_ASSERT_DIFFERS(normFunc->getParameter("f0." + NORM_PARAM), 1.); + TS_ASSERT_DELTA(normFunc->getParameter("f0." + OFFSET_PARAM), 1., 0.0001); + TS_ASSERT_DELTA(normFunc->getParameter("f0." + EXP_PARAM), 0.0, 0.0001); - TS_ASSERT_DIFFERS(normFunc->getParameter("f0."+USER_FUNC+"A0"),0.0); - TS_ASSERT_DELTA(normFunc->getParameter( "f0."+USER_FUNC+"A1"),1.5,0.0001); - + TS_ASSERT_DIFFERS(normFunc->getParameter("f0." + USER_FUNC + "A0"), 0.0); + TS_ASSERT_DELTA(normFunc->getParameter("f0." + USER_FUNC + "A1"), 1.5, + 0.0001); - TS_ASSERT_DIFFERS(normFunc->getParameter("f1."+NORM_PARAM),2.); - TS_ASSERT_DELTA(normFunc->getParameter( "f1."+OFFSET_PARAM),1.,0.0001); - TS_ASSERT_DELTA(normFunc->getParameter( "f1."+EXP_PARAM),0.0,0.0001); + TS_ASSERT_DIFFERS(normFunc->getParameter("f1." + NORM_PARAM), 2.); + TS_ASSERT_DELTA(normFunc->getParameter("f1." + OFFSET_PARAM), 1., 0.0001); + TS_ASSERT_DELTA(normFunc->getParameter("f1." + EXP_PARAM), 0.0, 0.0001); - TS_ASSERT_DIFFERS(normFunc->getParameter("f1."+USER_FUNC+"A0"),2.0); - TS_ASSERT_DIFFERS(normFunc->getParameter("f1."+USER_FUNC+"A1"),3.0); - + TS_ASSERT_DIFFERS(normFunc->getParameter("f1." + USER_FUNC + "A0"), 2.0); + TS_ASSERT_DIFFERS(normFunc->getParameter("f1." + USER_FUNC + "A1"), 3.0); } void test_2DTie() { genData(); - std::vector<std::string> wsNames = {"ws1","ws2"}; + std::vector<std::string> wsNames = {"ws1", "ws2"}; std::string multiFuncString = "composite=MultiDomainFunction,NumDeriv=1;"; multiFuncString += "name=LinearBackground, $domains=i,A0=0,A1=1.5;"; multiFuncString += "name=LinearBackground, $domains=i,A0=2,A1=3;"; - IFunction_sptr multiFunc = FunctionFactory::Instance().createInitialized(multiFuncString); + IFunction_sptr multiFunc = + FunctionFactory::Instance().createInitialized(multiFuncString); multiFunc->addTies("f0.A1=f1.A1"); - IAlgorithm_sptr alg = setUpAlg(wsNames,multiFunc); + IAlgorithm_sptr alg = setUpAlg(wsNames, multiFunc); TS_ASSERT(alg->isInitialized()) TS_ASSERT_THROWS_NOTHING(alg->execute()); TS_ASSERT(alg->isExecuted()); - IFunction_sptr normFunc = doFit(alg->getProperty("OutputFunction"),200,wsNames); + IFunction_sptr normFunc = + doFit(alg->getProperty("OutputFunction"), 200, wsNames); - TS_ASSERT_DIFFERS(normFunc->getParameter("f0."+NORM_PARAM),1.); - TS_ASSERT_DELTA(normFunc->getParameter( "f0."+OFFSET_PARAM),1.,0.0001); - TS_ASSERT_DELTA(normFunc->getParameter( "f0."+EXP_PARAM),0.0,0.0001); + TS_ASSERT_DIFFERS(normFunc->getParameter("f0." + NORM_PARAM), 1.); + TS_ASSERT_DELTA(normFunc->getParameter("f0." + OFFSET_PARAM), 1., 0.0001); + TS_ASSERT_DELTA(normFunc->getParameter("f0." + EXP_PARAM), 0.0, 0.0001); - TS_ASSERT_DIFFERS(normFunc->getParameter("f0."+USER_FUNC+"A0"),0.0); - TS_ASSERT_EQUALS(normFunc->getParameter( "f0."+USER_FUNC+"A1"),normFunc->getParameter("f1."+USER_FUNC+"A1")); - + TS_ASSERT_DIFFERS(normFunc->getParameter("f0." + USER_FUNC + "A0"), 0.0); + TS_ASSERT_EQUALS(normFunc->getParameter("f0." + USER_FUNC + "A1"), + normFunc->getParameter("f1." + USER_FUNC + "A1")); - TS_ASSERT_DIFFERS(normFunc->getParameter("f1."+NORM_PARAM),2.); - TS_ASSERT_DELTA(normFunc->getParameter( "f1."+OFFSET_PARAM),1.,0.0001); - TS_ASSERT_DELTA(normFunc->getParameter( "f1."+EXP_PARAM),0.0,0.0001); + TS_ASSERT_DIFFERS(normFunc->getParameter("f1." + NORM_PARAM), 2.); + TS_ASSERT_DELTA(normFunc->getParameter("f1." + OFFSET_PARAM), 1., 0.0001); + TS_ASSERT_DELTA(normFunc->getParameter("f1." + EXP_PARAM), 0.0, 0.0001); - TS_ASSERT_DIFFERS(normFunc->getParameter("f1."+USER_FUNC+"A0"),2.0); - + TS_ASSERT_DIFFERS(normFunc->getParameter("f1." + USER_FUNC + "A0"), 2.0); } // test extract void test_1DExtract() { genData(); std::vector<std::string> wsNames = {"ws1"}; - IFunction_sptr func = FunctionFactory::Instance().createInitialized("name=LinearBackground,A0=0,A1=2;"); - IAlgorithm_sptr alg = setUpAlg(wsNames,func); + IFunction_sptr func = FunctionFactory::Instance().createInitialized( + "name=LinearBackground,A0=0,A1=2;"); + IAlgorithm_sptr alg = setUpAlg(wsNames, func); TS_ASSERT(alg->isInitialized()) TS_ASSERT_THROWS_NOTHING(alg->execute()); TS_ASSERT(alg->isExecuted()); IFunction_sptr normFunc = alg->getProperty("OutputFunction"); alg = setUpAlg(wsNames, normFunc); - alg->setProperty("Mode","Extract"); + alg->setProperty("Mode", "Extract"); TS_ASSERT(alg->isInitialized()); TS_ASSERT_THROWS_NOTHING(alg->execute()); TS_ASSERT(alg->isExecuted()); IFunction_sptr outFunc = alg->getProperty("OutputFunction"); - - //auto outFunc = doFit(normFunc,0,wsNames); - TS_ASSERT_DELTA(outFunc->getParameter("A0"),0.0,0.0001); - TS_ASSERT_DELTA(outFunc->getParameter("A1"),2.0,0.0001); - } - + // auto outFunc = doFit(normFunc,0,wsNames); + TS_ASSERT_DELTA(outFunc->getParameter("A0"), 0.0, 0.0001); + TS_ASSERT_DELTA(outFunc->getParameter("A1"), 2.0, 0.0001); + } void test_1DFixExtract() { genData(); std::vector<std::string> wsNames = {"ws1"}; - IFunction_sptr func = FunctionFactory::Instance().createInitialized("name=LinearBackground,A0=0,A1=2;ties =(f0.A1=2)"); - IAlgorithm_sptr alg = setUpAlg(wsNames,func); + IFunction_sptr func = FunctionFactory::Instance().createInitialized( + "name=LinearBackground,A0=0,A1=2;ties =(f0.A1=2)"); + IAlgorithm_sptr alg = setUpAlg(wsNames, func); TS_ASSERT(alg->isInitialized()) TS_ASSERT_THROWS_NOTHING(alg->execute()); TS_ASSERT(alg->isExecuted()); IFunction_sptr normFunc = alg->getProperty("OutputFunction"); - - auto outFunc = doFit(normFunc,200,wsNames); + + auto outFunc = doFit(normFunc, 200, wsNames); alg = setUpAlg(wsNames, outFunc); - alg->setProperty("Mode","Extract"); + alg->setProperty("Mode", "Extract"); TS_ASSERT(alg->isInitialized()); TS_ASSERT_THROWS_NOTHING(alg->execute()); TS_ASSERT(alg->isExecuted()); IFunction_sptr extractFunc = alg->getProperty("OutputFunction"); - - TS_ASSERT_DELTA(extractFunc->getParameter("A1"),2.0,0.0001); - TS_ASSERT_EQUALS(outFunc->getParameter(USER_FUNC+"A0"),extractFunc->getParameter("A0")); - + TS_ASSERT_DELTA(extractFunc->getParameter("A1"), 2.0, 0.0001); + TS_ASSERT_EQUALS(outFunc->getParameter(USER_FUNC + "A0"), + extractFunc->getParameter("A0")); } void test_1DTieExtract() { genData(); std::vector<std::string> wsNames = {"ws1"}; - IFunction_sptr func = FunctionFactory::Instance().createInitialized("name=LinearBackground,A0=0,A1=2;name=LinearBackground,A0=0,A1=4;ties =(f0.A1=f1.A1)"); - IAlgorithm_sptr alg = setUpAlg(wsNames,func); + IFunction_sptr func = FunctionFactory::Instance().createInitialized( + "name=LinearBackground,A0=0,A1=2;name=LinearBackground,A0=0,A1=4;ties " + "=(f0.A1=f1.A1)"); + IAlgorithm_sptr alg = setUpAlg(wsNames, func); TS_ASSERT(alg->isInitialized()) TS_ASSERT_THROWS_NOTHING(alg->execute()); TS_ASSERT(alg->isExecuted()); IFunction_sptr normFunc = alg->getProperty("OutputFunction"); - auto outFunc = doFit(normFunc,200,wsNames); - + auto outFunc = doFit(normFunc, 200, wsNames); + alg = setUpAlg(wsNames, outFunc); - alg->setProperty("Mode","Extract"); + alg->setProperty("Mode", "Extract"); TS_ASSERT(alg->isInitialized()); TS_ASSERT_THROWS_NOTHING(alg->execute()); TS_ASSERT(alg->isExecuted()); IFunction_sptr extractFunc = alg->getProperty("OutputFunction"); - - TS_ASSERT_EQUALS(extractFunc->getParameter("f0.A1"),extractFunc->getParameter("f1.A1")); - TS_ASSERT_DIFFERS(extractFunc->getParameter("f0.A0"),func->getParameter("f0.A0")); - TS_ASSERT_DIFFERS(extractFunc->getParameter("f1.A0"),func->getParameter("f1.A0")); - + + TS_ASSERT_EQUALS(extractFunc->getParameter("f0.A1"), + extractFunc->getParameter("f1.A1")); + TS_ASSERT_DIFFERS(extractFunc->getParameter("f0.A0"), + func->getParameter("f0.A0")); + TS_ASSERT_DIFFERS(extractFunc->getParameter("f1.A0"), + func->getParameter("f1.A0")); } - // tests for multi domain + // tests for multi domain void test_2DExtract() { genData(); - std::vector<std::string> wsNames = {"ws1","ws2"}; + std::vector<std::string> wsNames = {"ws1", "ws2"}; std::string multiFuncString = "composite=MultiDomainFunction,NumDeriv=1;"; multiFuncString += "name=LinearBackground, $domains=i,A0=0,A1=1;"; multiFuncString += "name=LinearBackground, $domains=i,A0=2,A1=3;"; - IFunction_sptr multiFunc = FunctionFactory::Instance().createInitialized(multiFuncString); + IFunction_sptr multiFunc = + FunctionFactory::Instance().createInitialized(multiFuncString); - IAlgorithm_sptr alg = setUpAlg(wsNames,multiFunc); + IAlgorithm_sptr alg = setUpAlg(wsNames, multiFunc); TS_ASSERT(alg->isInitialized()) TS_ASSERT_THROWS_NOTHING(alg->execute()); TS_ASSERT(alg->isExecuted()); - IFunction_sptr normFunc = doFit(alg->getProperty("OutputFunction"),0,wsNames); + IFunction_sptr normFunc = + doFit(alg->getProperty("OutputFunction"), 0, wsNames); alg = setUpAlg(wsNames, normFunc); - alg->setProperty("Mode","Extract"); + alg->setProperty("Mode", "Extract"); TS_ASSERT(alg->isInitialized()); TS_ASSERT_THROWS_NOTHING(alg->execute()); TS_ASSERT(alg->isExecuted()); IFunction_sptr extractFunc = alg->getProperty("OutputFunction"); - - TS_ASSERT_DELTA(extractFunc->getParameter("f0.A0"),0.0,0.0001); - TS_ASSERT_DELTA(extractFunc->getParameter("f0.A1"),1.0,0.0001); - - TS_ASSERT_DELTA(extractFunc->getParameter("f1.A0"),2.0,0.0001); - TS_ASSERT_DELTA(extractFunc->getParameter("f1.A1"),3.0,0.0001); - + + TS_ASSERT_DELTA(extractFunc->getParameter("f0.A0"), 0.0, 0.0001); + TS_ASSERT_DELTA(extractFunc->getParameter("f0.A1"), 1.0, 0.0001); + + TS_ASSERT_DELTA(extractFunc->getParameter("f1.A0"), 2.0, 0.0001); + TS_ASSERT_DELTA(extractFunc->getParameter("f1.A1"), 3.0, 0.0001); } - void test_2DFixExtract() { + void test_2DFixExtract() { genData(); - std::vector<std::string> wsNames = {"ws1","ws2"}; + std::vector<std::string> wsNames = {"ws1", "ws2"}; std::string multiFuncString = "composite=MultiDomainFunction,NumDeriv=1;"; multiFuncString += "name=LinearBackground, $domains=i,A0=0,A1=1.5;"; multiFuncString += "name=LinearBackground, $domains=i,A0=2,A1=3;"; - IFunction_sptr multiFunc = FunctionFactory::Instance().createInitialized(multiFuncString); + IFunction_sptr multiFunc = + FunctionFactory::Instance().createInitialized(multiFuncString); multiFunc->addTies("f0.A1=1.5"); - IAlgorithm_sptr alg = setUpAlg(wsNames,multiFunc); + IAlgorithm_sptr alg = setUpAlg(wsNames, multiFunc); TS_ASSERT(alg->isInitialized()) TS_ASSERT_THROWS_NOTHING(alg->execute()); TS_ASSERT(alg->isExecuted()); - IFunction_sptr normFunc = doFit(alg->getProperty("OutputFunction"),200,wsNames); + IFunction_sptr normFunc = + doFit(alg->getProperty("OutputFunction"), 200, wsNames); alg = setUpAlg(wsNames, normFunc); - alg->setProperty("Mode","Extract"); + alg->setProperty("Mode", "Extract"); TS_ASSERT(alg->isInitialized()); TS_ASSERT_THROWS_NOTHING(alg->execute()); TS_ASSERT(alg->isExecuted()); IFunction_sptr extractFunc = alg->getProperty("OutputFunction"); - - - TS_ASSERT_DIFFERS(extractFunc->getParameter("f0.A0"),0.0); - TS_ASSERT_DELTA( extractFunc->getParameter( "f0.A1"),1.5,0.0001); - - TS_ASSERT_DIFFERS(extractFunc->getParameter("f1.A0"),2.0); - TS_ASSERT_DIFFERS(extractFunc->getParameter("f1.A1"),3.0); - - } + TS_ASSERT_DIFFERS(extractFunc->getParameter("f0.A0"), 0.0); + TS_ASSERT_DELTA(extractFunc->getParameter("f0.A1"), 1.5, 0.0001); + + TS_ASSERT_DIFFERS(extractFunc->getParameter("f1.A0"), 2.0); + TS_ASSERT_DIFFERS(extractFunc->getParameter("f1.A1"), 3.0); + } void test_2DTieExtract() { genData(); - std::vector<std::string> wsNames = {"ws1","ws2"}; + std::vector<std::string> wsNames = {"ws1", "ws2"}; std::string multiFuncString = "composite=MultiDomainFunction,NumDeriv=1;"; multiFuncString += "name=LinearBackground, $domains=i,A0=0,A1=1.5;"; multiFuncString += "name=LinearBackground, $domains=i,A0=2,A1=3;"; - IFunction_sptr multiFunc = FunctionFactory::Instance().createInitialized(multiFuncString); + IFunction_sptr multiFunc = + FunctionFactory::Instance().createInitialized(multiFuncString); multiFunc->addTies("f0.A1=f1.A1"); - IAlgorithm_sptr alg = setUpAlg(wsNames,multiFunc); + IAlgorithm_sptr alg = setUpAlg(wsNames, multiFunc); TS_ASSERT(alg->isInitialized()) TS_ASSERT_THROWS_NOTHING(alg->execute()); TS_ASSERT(alg->isExecuted()); - IFunction_sptr normFunc = doFit(alg->getProperty("OutputFunction"),200,wsNames); + IFunction_sptr normFunc = + doFit(alg->getProperty("OutputFunction"), 200, wsNames); alg = setUpAlg(wsNames, normFunc); - alg->setProperty("Mode","Extract"); + alg->setProperty("Mode", "Extract"); TS_ASSERT(alg->isInitialized()); TS_ASSERT_THROWS_NOTHING(alg->execute()); TS_ASSERT(alg->isExecuted()); IFunction_sptr extractFunc = alg->getProperty("OutputFunction"); - - TS_ASSERT_DIFFERS(extractFunc->getParameter("f0.A0"),0.0); - TS_ASSERT_EQUALS( extractFunc->getParameter("f0.A1"),extractFunc->getParameter("f1.A1")); - - TS_ASSERT_DIFFERS(extractFunc->getParameter("f1.A0"),2.0); - + + TS_ASSERT_DIFFERS(extractFunc->getParameter("f0.A0"), 0.0); + TS_ASSERT_EQUALS(extractFunc->getParameter("f0.A1"), + extractFunc->getParameter("f1.A1")); + + TS_ASSERT_DIFFERS(extractFunc->getParameter("f1.A0"), 2.0); } - + private: MatrixWorkspace_sptr input; }; diff --git a/Framework/PythonInterface/mantid/api/src/Exports/FunctionProperty.cpp b/Framework/PythonInterface/mantid/api/src/Exports/FunctionProperty.cpp index c0558c39190..839738cd391 100644 --- a/Framework/PythonInterface/mantid/api/src/Exports/FunctionProperty.cpp +++ b/Framework/PythonInterface/mantid/api/src/Exports/FunctionProperty.cpp @@ -10,14 +10,14 @@ using Mantid::PythonInterface::PropertyWithValueExporter; using namespace boost::python; void export_FunctionProperty() { - // FuncitonProperty has base PropertyWithValue<boost::shared_ptr<IFunction>> - // which must be exported - using HeldType = boost::shared_ptr<IFunction>; - PropertyWithValueExporter<HeldType>::define("FunctionPropertyWithValue"); + // FuncitonProperty has base PropertyWithValue<boost::shared_ptr<IFunction>> + // which must be exported + using HeldType = boost::shared_ptr<IFunction>; + PropertyWithValueExporter<HeldType>::define("FunctionPropertyWithValue"); - class_<FunctionProperty, bases<PropertyWithValue<HeldType>>, - boost::noncopyable>("FunctionProperty", no_init) - .def(init<const std::string &, const unsigned int>( - (arg("self"), arg("name"), arg("direction") = Direction::Input), - "Constructs a FunctionProperty with the given name")); + class_<FunctionProperty, bases<PropertyWithValue<HeldType>>, + boost::noncopyable>("FunctionProperty", no_init) + .def(init<const std::string &, const unsigned int>( + (arg("self"), arg("name"), arg("direction") = Direction::Input), + "Constructs a FunctionProperty with the given name")); } \ No newline at end of file -- GitLab