Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/feature/9199_multidomain_improve…
Browse files Browse the repository at this point in the history
…ments'
  • Loading branch information
Samuel Jackson committed Apr 3, 2014
2 parents 0b1be84 + 234ef73 commit bd71dbe
Show file tree
Hide file tree
Showing 11 changed files with 451 additions and 32 deletions.
15 changes: 12 additions & 3 deletions Code/Mantid/Framework/API/inc/MantidAPI/IDomainCreator.h
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ class MANTID_API_DLL MultiDomainFunction : public CompositeFunction
virtual void function(const FunctionDomain& domain, FunctionValues& values)const;
/// Derivatives of function with respect to active parameters
virtual void functionDeriv(const FunctionDomain& domain, Jacobian& jacobian);
/// Called at the start of each iteration
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 All @@ -63,6 +69,8 @@ class MANTID_API_DLL MultiDomainFunction : public CompositeFunction
void clearDomainIndices();
/// Get the largest domain index
size_t getMaxIndex() const {return m_maxIndex;}
/// Get domain indices for a member function
void getDomainIndices(size_t i, size_t nDomains, std::vector<size_t>& domains)const;

/// Returns the number of attributes associated with the function
virtual size_t nLocalAttributes()const {return 1;}
Expand All @@ -80,7 +88,6 @@ class MANTID_API_DLL MultiDomainFunction : public CompositeFunction
/// Counts number of the domains
void countNumberOfDomains();
void countValueOffsets(const CompositeDomain& domain)const;
void getFunctionDomains(size_t i, const CompositeDomain& cd, std::vector<size_t>& domains)const;

/// Domain index map: finction -> domain
std::map<size_t, std::vector<size_t> > m_domains;
Expand Down
85 changes: 81 additions & 4 deletions Code/Mantid/Framework/API/src/MultiDomainFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,16 @@ namespace API

/**
* Populates a vector with domain indices assigned to function i.
* @param i :: Index of a function to get the domain info about.
* @param nDomains :: Maximum number of domains.
* @param domains :: (Output) vector to collect domain indixes.
*/
void MultiDomainFunction::getFunctionDomains(size_t i, const CompositeDomain& cd, std::vector<size_t>& domains)const
void MultiDomainFunction::getDomainIndices(size_t i, size_t nDomains, std::vector<size_t>& domains)const
{
auto it = m_domains.find(i);
if (it == m_domains.end())
{// apply to all domains
domains.resize(cd.getNParts());
domains.resize(nDomains);
for(size_t i = 0; i < domains.size(); ++i)
{
domains[i] = i;
Expand Down Expand Up @@ -128,7 +131,7 @@ namespace API
{
// find the domains member function must be applied to
std::vector<size_t> domains;
getFunctionDomains(iFun, cd, domains);
getDomainIndices(iFun, cd.getNParts(), domains);

for(auto i = domains.begin(); i != domains.end(); ++i)
{
Expand Down Expand Up @@ -163,7 +166,7 @@ namespace API
{
// find the domains member function must be applied to
std::vector<size_t> domains;
getFunctionDomains(iFun, cd, domains);
getDomainIndices(iFun, cd.getNParts(), domains);

for(auto i = domains.begin(); i != domains.end(); ++i)
{
Expand All @@ -174,6 +177,28 @@ namespace API
}
}

/**
* Called at the start of each iteration. Call iterationStarting() of the members.
*/
void MultiDomainFunction::iterationStarting()
{
for(size_t iFun = 0; iFun < nFunctions(); ++iFun)
{
getFunction(iFun)->iterationStarting();
}
}

/**
* Called at the end of an iteration. Call iterationFinished() of the members.
*/
void MultiDomainFunction::iterationFinished()
{
for(size_t iFun = 0; iFun < nFunctions(); ++iFun)
{
getFunction(iFun)->iterationFinished();
}
}

/// Return a value of attribute attName
IFunction::Attribute MultiDomainFunction::getLocalAttribute(size_t i, const std::string& attName)const
{
Expand Down Expand Up @@ -251,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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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 All @@ -61,6 +69,8 @@ namespace Mantid
bool hasCreator(size_t i) const;
/// Get number of creators
size_t getNCreators() const {return m_creators.size();}
/// Initialize the function
void initFunction(API::IFunction_sptr function);

protected:
/// Vector of creators.
Expand Down
20 changes: 13 additions & 7 deletions Code/Mantid/Framework/CurveFitting/src/FitMW.cpp
Original file line number Diff line number Diff line change
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
Loading

0 comments on commit bd71dbe

Please sign in to comment.