Skip to content

Commit

Permalink
Re #4158. MultiDomainFunction works with Fit algorithm.
Browse files Browse the repository at this point in the history
  • Loading branch information
mantid-roman committed Apr 2, 2012
1 parent c4d5887 commit 637f9eb
Show file tree
Hide file tree
Showing 10 changed files with 213 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
#include "MantidAPI/Workspace.h"
#include "MantidCurveFitting/IDomainCreator.h"

#include <boost/scoped_ptr.hpp>

namespace Mantid
{

Expand Down Expand Up @@ -53,7 +51,7 @@ namespace Mantid
{
public:
/// Default constructor
Fit() : API::Algorithm(),m_workspaceCount(0) {};
Fit() : API::Algorithm() {};
/// Algorithm's name for identification overriding a virtual method
virtual const std::string name() const { return "Fit";}
/// Algorithm's version for identification overriding a virtual method
Expand All @@ -72,15 +70,16 @@ namespace Mantid
virtual void afterPropertySet(const std::string& propName);
void setFunction();
void addWorkspace(const std::string& workspaceNameProperty, bool addProperties = true);
void addWorkspaces();

/// Pointer to the fitting function
API::IFunction_sptr m_function;
///// Pointer
//API::Workspace_const_sptr m_workspace;
/// Pointer to a domain creator
boost::scoped_ptr<IDomainCreator> m_domainCreator;
boost::shared_ptr<IDomainCreator> m_domainCreator;
friend class IDomainCreator;
size_t m_workspaceCount;
std::vector<std::string> m_workspacePropertyNames;

};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ namespace Mantid

/// Create a domain from the input workspace
virtual void createDomain(
const std::string& workspacePropetyName,
const std::vector<std::string>& workspacePropetyNames,
boost::shared_ptr<API::FunctionDomain>&,
boost::shared_ptr<API::IFunctionValues>&, size_t i0);
protected:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ namespace Mantid
virtual void declareDatasetProperties(const std::string& suffix = "",bool addProp = true);
/// Create a domain from the input workspace
virtual void createDomain(
const std::string& workspacePropetyName,
const std::vector<std::string>& workspacePropetyNames,
boost::shared_ptr<API::FunctionDomain>& domain,
boost::shared_ptr<API::IFunctionValues>& values, size_t i0 = 0);
void createOutputWorkspace(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ namespace Mantid
/// @param domain :: Shared pointer to hold the created domain
/// @param values :: Shared pointer to hold the created values with set fitting data and weights
virtual void createDomain(
const std::string& workspacePropetyName,
const std::vector<std::string>& workspacePropetyNames,
boost::shared_ptr<API::FunctionDomain>& domain,
boost::shared_ptr<API::IFunctionValues>& values,
size_t i0 = 0) = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ namespace Mantid
File change history is stored at: <https://svn.mantidproject.org/mantid/trunk/Code/Mantid>
Code Documentation is available at: <http://doxygen.mantidproject.org>
*/
class DLLExport MultiDomainCreator : IDomainCreator
class DLLExport MultiDomainCreator : public IDomainCreator
{
/// A friend that can create instances of this class
friend class Fit;
Expand All @@ -46,7 +46,7 @@ namespace Mantid

/// Create a domain from the input workspace
virtual void createDomain(
const std::string& workspacePropetyName,
const std::vector<std::string>& workspacePropetyNames,
boost::shared_ptr<API::FunctionDomain>& domain,
boost::shared_ptr<API::IFunctionValues>& values, size_t i0);

Expand Down
117 changes: 100 additions & 17 deletions Code/Mantid/Framework/CurveFitting/src/Fit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Setting the Output property defines the names of the output workspaces. One of t
#include "MantidCurveFitting/CostFuncFitting.h"
#include "MantidCurveFitting/FitMW.h"
#include "MantidCurveFitting/FitMD.h"
#include "MantidCurveFitting/MultiDomainCreator.h"

#include "MantidAPI/WorkspaceFactory.h"
#include "MantidAPI/MatrixWorkspace.h"
Expand Down Expand Up @@ -84,35 +85,117 @@ namespace CurveFitting
auto mdf = boost::dynamic_pointer_cast<API::MultiDomainFunction>(m_function);
if (mdf)
{
for(size_t i = 1; i < mdf->nFunctions(); ++i)
{
declareProperty(
new API::WorkspaceProperty<API::Workspace>("InputWorkspace_"+boost::lexical_cast<std::string>(i),"",Kernel::Direction::Input),
"Name of the input Workspace");
}
}
}

void Fit::addWorkspace(const std::string& workspaceNameProperty, bool addProperties)
void Fit::addWorkspace(const std::string& workspacePropertyName, bool addProperties)
{
// Create the creator
if (!m_domainCreator)
// get the workspace
API::Workspace_const_sptr ws = getProperty(workspacePropertyName);
//m_function->setWorkspace(ws);
const size_t n = std::string("InputWorkspace").size();
const std::string suffix = (workspacePropertyName.size() > n)? workspacePropertyName.substr(n) : "";

API::IFunction_sptr fun = getProperty("Function");
IDomainCreator* creator = nullptr;

if ( boost::dynamic_pointer_cast<const API::MatrixWorkspace>(ws) &&
!boost::dynamic_pointer_cast<API::IFunctionMD>(fun) )
{
// get the workspace
API::Workspace_const_sptr ws = getProperty("InputWorkspace");
//m_function->setWorkspace(ws);
creator = new FitMW(this);
}
else if (boost::dynamic_pointer_cast<const API::IMDWorkspace>(ws))
{
creator = new FitMD(this);
}
else
{// don't know what to do with this workspace
throw std::invalid_argument("Unsupported workspace type" + ws->id());
}
creator->declareDatasetProperties(suffix,addProperties);
m_workspacePropertyNames.push_back(workspacePropertyName);

if ( boost::dynamic_pointer_cast<const API::MatrixWorkspace>(ws) &&
!boost::dynamic_pointer_cast<API::IFunctionMD>(m_function) )
if (!m_domainCreator)
{
if (boost::dynamic_pointer_cast<API::MultiDomainFunction>(fun))
{
m_domainCreator.reset(new FitMW(this));
auto multiCreator = new MultiDomainCreator(this);
multiCreator->addCreator(workspacePropertyName,creator);
m_domainCreator.reset(multiCreator);
}
else if (boost::dynamic_pointer_cast<const API::IMDWorkspace>(ws))
else
{
m_domainCreator.reset(new FitMD(this));
m_domainCreator.reset(creator);
}
else
{// don't know what to do with this workspace
throw std::invalid_argument("Unsupported workspace type" + ws->id());
}
else
{
boost::shared_ptr<MultiDomainCreator> multiCreator = boost::dynamic_pointer_cast<MultiDomainCreator>(m_domainCreator);
//MultiDomainCreator* multiCreator = dynamic_cast<MultiDomainCreator*>(m_domainCreator.get());
if (!multiCreator)
{
throw std::runtime_error(std::string("MultiDomainCreator expected, found ") + typeid(*m_domainCreator.get()).name());
}
multiCreator->addCreator(workspacePropertyName,creator);
}

}

/**
* Collect all input workspace property names in the m_workspacePropertyNames vector
*/
void Fit::addWorkspaces()
{
auto multiFun = boost::dynamic_pointer_cast<API::MultiDomainFunction>(m_function);
if (multiFun)
{
m_domainCreator.reset(new MultiDomainCreator(this));
}
auto props = getProperties();
for(auto prop = props.begin(); prop != props.end(); ++prop)
{
if ((**prop).direction() == Kernel::Direction::Input && dynamic_cast<API::IWorkspaceProperty*>(*prop))
{
const std::string workspacePropertyName = (**prop).name();
API::Workspace_const_sptr ws = getProperty(workspacePropertyName);
IDomainCreator* creator = nullptr;
if ( boost::dynamic_pointer_cast<const API::MatrixWorkspace>(ws) &&
!boost::dynamic_pointer_cast<API::IFunctionMD>(m_function) )
{
creator = new FitMW(this);
}
else if (boost::dynamic_pointer_cast<const API::IMDWorkspace>(ws))
{
creator = new FitMD(this);
}
else
{// don't know what to do with this workspace
throw std::invalid_argument("Unsupported workspace type" + ws->id());
}
const size_t n = std::string("InputWorkspace").size();
const std::string suffix = (workspacePropertyName.size() > n)? workspacePropertyName.substr(n) : "";
creator->declareDatasetProperties(suffix,false);
m_workspacePropertyNames.push_back(workspacePropertyName);
if (!m_domainCreator)
{
m_domainCreator.reset(creator);
}
auto multiCreator = boost::dynamic_pointer_cast<MultiDomainCreator>(m_domainCreator);
if (multiCreator)
{
multiCreator->addCreator(workspacePropertyName,creator);
}
}
m_domainCreator->declareDatasetProperties("",addProperties);
}
}


/** Initialisation method
*/
void Fit::init()
Expand Down Expand Up @@ -168,15 +251,15 @@ namespace CurveFitting
if (!m_domainCreator)
{
setFunction();
addWorkspace("InputWorkspace",false);
addWorkspaces();
}

// do something with the function which may depend on workspace
m_domainCreator->initFunction();

API::FunctionDomain_sptr domain;
API::IFunctionValues_sptr values;
m_domainCreator->createDomain("InputWorkspace",domain,values);
m_domainCreator->createDomain(m_workspacePropertyNames,domain,values);

// get the minimizer
std::string minimizerName = getPropertyValue("Minimizer");
Expand Down
8 changes: 6 additions & 2 deletions Code/Mantid/Framework/CurveFitting/src/FitMD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,16 @@ namespace CurveFitting

/// Create a domain from the input workspace
void FitMD::createDomain(
const std::string& workspacePropetyName,
const std::vector<std::string>& workspacePropetyNames,
boost::shared_ptr<API::FunctionDomain>& domain,
boost::shared_ptr<API::IFunctionValues>& ivalues, size_t i0)
{
if (workspacePropetyNames.empty())
{
throw std::runtime_error("Cannot create FunctionDomainMD: no workspace given");
}
// get the workspace
API::Workspace_sptr ws = m_fit->getProperty(workspacePropetyName);
API::Workspace_sptr ws = m_fit->getProperty(workspacePropetyNames[0]);
m_IMDWorkspace = boost::dynamic_pointer_cast<API::IMDWorkspace>(ws);
if (!m_IMDWorkspace)
{
Expand Down
10 changes: 7 additions & 3 deletions Code/Mantid/Framework/CurveFitting/src/FitMW.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,15 @@ namespace

/// Create a domain from the input workspace
void FitMW::createDomain(
const std::string& workspacePropetyName,
const std::vector<std::string>& workspacePropetyNames,
boost::shared_ptr<API::FunctionDomain>& domain,
boost::shared_ptr<API::IFunctionValues>& ivalues, size_t i0)
{
m_workspacePropertyName = workspacePropetyName;
if (workspacePropetyNames.empty())
{
throw std::runtime_error("Cannot create FunctionDomain1D: no workspace given");
}
m_workspacePropertyName = workspacePropetyNames[0];
// get the function
m_function = m_fit->getProperty("Function");
// get the workspace
Expand Down Expand Up @@ -222,7 +226,7 @@ namespace

// set the data to fit to
m_startIndex = static_cast<size_t>( from - X.begin() );
size_t n = values->size();
size_t n = domain->size();
size_t ito = m_startIndex + n;
const Mantid::MantidVec& Y = m_matrixWorkspace->readY( m_workspaceIndex );
const Mantid::MantidVec& E = m_matrixWorkspace->readE( m_workspaceIndex );
Expand Down
21 changes: 16 additions & 5 deletions Code/Mantid/Framework/CurveFitting/src/MultiDomainCreator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,28 @@ namespace CurveFitting

/// Create a domain from the input workspace
void MultiDomainCreator::createDomain(
const std::string& workspacePropetyName,
const std::vector<std::string>& workspacePropetyNames,
boost::shared_ptr<API::FunctionDomain>& domain,
boost::shared_ptr<API::IFunctionValues>& values, size_t i0)
boost::shared_ptr<API::IFunctionValues>& ivalues, size_t i0)
{
(void)workspacePropetyName;
if (workspacePropetyNames.size() != m_creators.size())
{
throw std::runtime_error("Cannot create JointDomain: number of workspaces does not match "
"the number of creators");
}
auto jointDomain = new API::JointDomain;
API::IFunctionValues_sptr values;
i0 = 0;
for(auto c = m_creators.begin(); c != m_creators.end(); ++c)
{
//(**c).createDomain();
//jointDomain->addDomain();
auto i = static_cast<size_t>(c - m_creators.begin());
API::FunctionDomain_sptr domain;
(**c).createDomain(std::vector<std::string>(1,workspacePropetyNames[i]),domain,values,i0);
jointDomain->addDomain(domain);
i0 += domain->size();
}
domain.reset(jointDomain);
ivalues = values;
}


Expand Down

0 comments on commit 637f9eb

Please sign in to comment.