Skip to content

Commit

Permalink
Re #9199. MultiDomainCreator creates output workspace
Browse files Browse the repository at this point in the history
  • Loading branch information
mantid-roman committed Mar 25, 2014
1 parent 3dc8d09 commit 589e466
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 12 deletions.
15 changes: 12 additions & 3 deletions Code/Mantid/Framework/API/inc/MantidAPI/IDomainCreator.h
Expand Up @@ -15,6 +15,7 @@ namespace Mantid
{
class FunctionDomain;
class IFunctionValues;
class Workspace;
}

namespace API
Expand Down Expand Up @@ -89,12 +90,20 @@ namespace Mantid
/// @param function :: A pointer to the fitting function
/// @param domain :: The domain containing x-values for the function
/// @param values :: A FunctionValues instance containing the fitting data
virtual void createOutputWorkspace(
/// @param outputWorkspacePropertyName :: Name of the property to declare and set to the created output workspace.
/// If empty do not create the property, just return a pointer
/// @return A shared pointer to the created workspace.
virtual boost::shared_ptr<API::Workspace> createOutputWorkspace(
const std::string& baseName,
API::IFunction_sptr function,
boost::shared_ptr<API::FunctionDomain> domain,
boost::shared_ptr<API::IFunctionValues> values)
{UNUSED_ARG(baseName);UNUSED_ARG(function);UNUSED_ARG(domain);UNUSED_ARG(values);}
boost::shared_ptr<API::IFunctionValues> values,
const std::string& outputWorkspacePropertyName = "OutputWorkspace"
)
{
UNUSED_ARG(baseName);UNUSED_ARG(function);UNUSED_ARG(domain);UNUSED_ARG(values);UNUSED_ARG(outputWorkspacePropertyName);
throw std::logic_error("Method createOutputWorkspace() isn't implemented");
}

/// Initialize the function
/// @param function :: A function to initialize.
Expand Down
2 changes: 2 additions & 0 deletions Code/Mantid/Framework/API/inc/MantidAPI/MultiDomainFunction.h
Expand Up @@ -58,6 +58,8 @@ class MANTID_API_DLL MultiDomainFunction : public CompositeFunction
virtual void iterationStarting();
/// Called at the end of an iteration
virtual void iterationFinished();
/// Create a list of equivalent functions
virtual std::vector<IFunction_sptr> createEquivalentFunctions() const;

/// Associate a function and a domain
void setDomainIndex(size_t funIndex, size_t domainIndex);
Expand Down
52 changes: 52 additions & 0 deletions Code/Mantid/Framework/API/src/MultiDomainFunction.cpp
Expand Up @@ -276,6 +276,58 @@ namespace API
setDomainIndices(i,indx);
}

/**
* Split this function into independent functions. The number of functions in the
* returned vector must be equal to the number
* of domains. The result of evaluation of the i-th function on the i-th domain must be
* the same as if this MultiDomainFunction was evaluated.
*/
std::vector<IFunction_sptr> MultiDomainFunction::createEquivalentFunctions() const
{
size_t nDomains = m_maxIndex + 1;
std::vector<CompositeFunction_sptr> compositeFunctions(nDomains);
for(size_t iFun = 0; iFun < nFunctions(); ++iFun)
{
// find the domains member function must be applied to
std::vector<size_t> domains;
getDomainIndices(iFun, nDomains, domains);

for(auto i = domains.begin(); i != domains.end(); ++i)
{
size_t j = *i;
CompositeFunction_sptr cf = compositeFunctions[j];
if ( !cf )
{
// create a composite function for each domain
cf = CompositeFunction_sptr(new CompositeFunction());
compositeFunctions[j] = cf;
}
// add copies of all functions applied to j-th domain to a single compositefunction
cf->addFunction( FunctionFactory::Instance().createInitialized( getFunction(iFun)->asString() ));
}
}
std::vector<IFunction_sptr> outFunctions(nDomains);
// fill in the output vector
// check functions containing a single member and take it out of the composite
for(size_t i = 0; i < compositeFunctions.size(); ++i)
{
auto fun = compositeFunctions[i];
if ( !fun || fun->nFunctions() == 0 )
{
throw std::runtime_error("There is no function for domain " + boost::lexical_cast<std::string>(i));
}
if ( fun->nFunctions() > 1 )
{
outFunctions[i] = fun;
}
else
{
outFunctions[i] = fun->getFunction(0);
}
}
return outFunctions;
}


} // namespace API
} // namespace Mantid
Expand Up @@ -64,11 +64,12 @@ namespace Mantid
virtual void createDomain(
boost::shared_ptr<API::FunctionDomain>& domain,
boost::shared_ptr<API::IFunctionValues>& values, size_t i0 = 0);
void createOutputWorkspace(
boost::shared_ptr<API::Workspace> createOutputWorkspace(
const std::string& baseName,
API::IFunction_sptr function,
boost::shared_ptr<API::FunctionDomain> domain,
boost::shared_ptr<API::IFunctionValues> values
boost::shared_ptr<API::IFunctionValues> values,
const std::string& outputWorkspacePropertyName
);
/// Return the size of the domain to be created.
virtual size_t getDomainSize() const;
Expand Down
Expand Up @@ -53,6 +53,14 @@ namespace Mantid
virtual void createDomain(
boost::shared_ptr<API::FunctionDomain>& domain,
boost::shared_ptr<API::IFunctionValues>& values, size_t i0 = 0);
/// Create the output workspace
boost::shared_ptr<API::Workspace> createOutputWorkspace(
const std::string& baseName,
API::IFunction_sptr function,
boost::shared_ptr<API::FunctionDomain> domain,
boost::shared_ptr<API::IFunctionValues> values,
const std::string& outputWorkspacePropertyName
);

/// Return the size of the domain to be created.
virtual size_t getDomainSize() const{return 0;}
Expand Down
20 changes: 13 additions & 7 deletions Code/Mantid/Framework/CurveFitting/src/FitMW.cpp
Expand Up @@ -280,18 +280,20 @@ namespace
* @param function :: A Pointer to the fitting function
* @param domain :: The domain containing x-values for the function
* @param ivalues :: A API::FunctionValues instance containing the fitting data
* @param outputWorkspacePropertyName :: The property name
*/
void FitMW::createOutputWorkspace(
boost::shared_ptr<API::Workspace> FitMW::createOutputWorkspace(
const std::string& baseName,
API::IFunction_sptr function,
boost::shared_ptr<API::FunctionDomain> domain,
boost::shared_ptr<API::IFunctionValues> ivalues
boost::shared_ptr<API::IFunctionValues> ivalues,
const std::string& outputWorkspacePropertyName
)
{
auto values = boost::dynamic_pointer_cast<API::FunctionValues>(ivalues);
if (!values)
{
return;
throw std::logic_error("FunctionValues expected");
}

// Compile list of functions to output. The top-level one is first
Expand Down Expand Up @@ -331,10 +333,14 @@ namespace
Diff[i] = values->getFitData(i) - Ycal[i];
}

declareProperty(new API::WorkspaceProperty<MatrixWorkspace>("OutputWorkspace","",Direction::Output),
"Name of the output Workspace holding resulting simulated spectrum");
m_manager->setPropertyValue("OutputWorkspace",baseName+"Workspace");
m_manager->setProperty("OutputWorkspace",ws);
if ( !outputWorkspacePropertyName.empty() )
{
declareProperty(new API::WorkspaceProperty<MatrixWorkspace>(outputWorkspacePropertyName,"",Direction::Output),
"Name of the output Workspace holding resulting simulated spectrum");
m_manager->setPropertyValue(outputWorkspacePropertyName,baseName+"Workspace");
m_manager->setProperty(outputWorkspacePropertyName,ws);
}
return ws;
}

/**
Expand Down
54 changes: 54 additions & 0 deletions Code/Mantid/Framework/CurveFitting/src/MultiDomainCreator.cpp
Expand Up @@ -4,6 +4,9 @@
#include "MantidCurveFitting/MultiDomainCreator.h"
#include "MantidAPI/JointDomain.h"
#include "MantidAPI/MultiDomainFunction.h"
#include "MantidAPI/WorkspaceGroup.h"
#include "MantidAPI/WorkspaceProperty.h"
#include "MantidAPI/MatrixWorkspace.h"
#include "MantidKernel/Logger.h"

#include <sstream>
Expand Down Expand Up @@ -104,6 +107,57 @@ namespace CurveFitting
}
}

/**
* Create the output workspace.
*/
boost::shared_ptr<API::Workspace> MultiDomainCreator::createOutputWorkspace(
const std::string& baseName,
API::IFunction_sptr function,
boost::shared_ptr<API::FunctionDomain> domain,
boost::shared_ptr<API::IFunctionValues> values,
const std::string& outputWorkspacePropertyName
)
{
auto mdFunction = boost::dynamic_pointer_cast<API::MultiDomainFunction>(function);
if ( !mdFunction )
{
throw std::runtime_error("A MultiDomainFunction is expected to be used with MultiDomainCreator.");
}

// split the function into independent parts
std::vector<API::IFunction_sptr> functions = mdFunction->createEquivalentFunctions();
// there must be as many parts as there are domains
if ( functions.size() != m_creators.size() )
{
throw std::runtime_error("Number of functions and domains don't match");
}

API::WorkspaceGroup_sptr outWS = API::WorkspaceGroup_sptr( new API::WorkspaceGroup() );

for(size_t i = 0; i < functions.size(); ++i)
{
std::string localName = baseName + "_" + boost::lexical_cast<std::string>(i);
auto fun = functions[i];
auto creator = m_creators[i];
boost::shared_ptr<API::FunctionDomain> localDomain;
boost::shared_ptr<API::IFunctionValues> localValues;
fun->setUpForFit();
creator->createDomain(localDomain,localValues);
creator->initFunction(fun);
auto ws = creator->createOutputWorkspace(localName,fun,localDomain,localValues,"");
outWS->addWorkspace( ws );
}

if ( !outputWorkspacePropertyName.empty() )
{
declareProperty(new API::WorkspaceProperty<API::WorkspaceGroup>(outputWorkspacePropertyName,"",Kernel::Direction::Output),
"Name of the output Workspace holding resulting simulated spectrum");
m_manager->setPropertyValue(outputWorkspacePropertyName,baseName+"Workspace");
m_manager->setProperty(outputWorkspacePropertyName,outWS);
}

return outWS;
}


} // namespace Algorithm
Expand Down

0 comments on commit 589e466

Please sign in to comment.