Skip to content

Commit

Permalink
Re #9891. Output a histo workspace from FitMD.
Browse files Browse the repository at this point in the history
  • Loading branch information
mantid-roman committed Sep 29, 2014
1 parent 70488cd commit c552656
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 10 deletions.
13 changes: 13 additions & 0 deletions Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/FitMD.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ namespace Mantid
class FunctionDomain;
class FunctionDomainMD;
class IMDWorkspace;
class IMDEventWorkspace;
class IMDHistoWorkspace;
}

namespace MDEvents
Expand Down Expand Up @@ -82,6 +84,17 @@ namespace Mantid
protected:
/// Set all parameters
void setParameters()const;
/// Create event output workspace
boost::shared_ptr<API::Workspace> createEventOutputWorkspace(const std::string& baseName,
const API::IMDEventWorkspace &inputWorkspace,
const API::FunctionValues &values,
const std::string& outputWorkspacePropertyName);
/// Create histo output workspace
boost::shared_ptr<API::Workspace> createHistoOutputWorkspace(const std::string& baseName,
API::IFunction_sptr function,
boost::shared_ptr<const API::IMDHistoWorkspace> inputWorkspace,
const std::string& outputWorkspacePropertyName);

/// Store workspace property name
std::string m_workspacePropertyName;
/// Store maxSize property name
Expand Down
82 changes: 73 additions & 9 deletions Code/Mantid/Framework/MDEvents/src/FitMD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#include "MantidAPI/IFunctionMD.h"
#include "MantidAPI/MemoryManager.h"
#include "MantidAPI/WorkspaceProperty.h"
#include "MantidAPI/AlgorithmFactory.h"

#include "MantidGeometry/MDGeometry/MDHistoDimensionBuilder.h"
#include "MantidMDEvents/MDEventFactory.h"

Expand Down Expand Up @@ -139,7 +141,7 @@ namespace Mantid
* @param outputWorkspacePropertyName :: The property name
*/
boost::shared_ptr<API::Workspace> FitMD::createOutputWorkspace(const std::string& baseName,
API::IFunction_sptr,
API::IFunction_sptr function,
boost::shared_ptr<API::FunctionDomain> domain,
boost::shared_ptr<API::FunctionValues> values,
const std::string& outputWorkspacePropertyName)
Expand All @@ -154,12 +156,35 @@ namespace Mantid
return boost::shared_ptr<API::Workspace>();
}
API::IMDWorkspace_const_sptr domainWS = functionMD->getWorkspace();
auto inputWS = boost::dynamic_pointer_cast<const API::IMDEventWorkspace>(domainWS);
if(!inputWS)

auto inputEventWS = boost::dynamic_pointer_cast<const API::IMDEventWorkspace>(domainWS);
if( inputEventWS )
{
return boost::shared_ptr<API::Workspace>();
return createEventOutputWorkspace( baseName, *inputEventWS, *values, outputWorkspacePropertyName );
}

auto inputHistoWS = boost::dynamic_pointer_cast<const API::IMDHistoWorkspace>(domainWS);
if( inputHistoWS )
{
return createHistoOutputWorkspace( baseName, function, inputHistoWS, outputWorkspacePropertyName );
}
auto outputWS = MDEventFactory::CreateMDWorkspace(inputWS->getNumDims(), "MDEvent");

return boost::shared_ptr<API::Workspace>();
}

/**
* Create an output event workspace filled with data simulated with the fitting function.
* @param baseName :: The base name for the workspace
* @param inputWorkspace :: The input workspace.
* @param values :: The calculated values
* @param outputWorkspacePropertyName :: The property name
*/
boost::shared_ptr<API::Workspace> FitMD::createEventOutputWorkspace(const std::string& baseName,
const API::IMDEventWorkspace &inputWorkspace,
const API::FunctionValues &values,
const std::string& outputWorkspacePropertyName)
{
auto outputWS = MDEventFactory::CreateMDWorkspace(inputWorkspace.getNumDims(), "MDEvent");
// Add events
// TODO: Generalize to ND (the current framework is a bit limiting)
auto mdWS = boost::dynamic_pointer_cast<MDEvents::MDEventWorkspace<MDEvents::MDEvent<4>,4> >(outputWS);
Expand All @@ -171,7 +196,7 @@ namespace Mantid
// Bins extents and meta data
for(size_t i = 0;i < 4; ++i)
{
boost::shared_ptr<const Geometry::IMDDimension> inputDim = inputWS->getDimension(i);
boost::shared_ptr<const Geometry::IMDDimension> inputDim = inputWorkspace.getDimension(i);
Geometry::MDHistoDimensionBuilder builder;
builder.setName(inputDim->getName());
builder.setId(inputDim->getDimensionId());
Expand All @@ -184,21 +209,21 @@ namespace Mantid
}

// Run information
outputWS->copyExperimentInfos(*inputWS);
outputWS->copyExperimentInfos(inputWorkspace);
// Set sensible defaults for splitting behaviour
BoxController_sptr bc = outputWS->getBoxController();
bc->setSplitInto(3);
bc->setSplitThreshold(3000);
outputWS->initialize();
outputWS->splitBox();

auto inputIter = inputWS->createIterator();
auto inputIter = inputWorkspace.createIterator();
size_t resultValueIndex(0);
const float errorSq = 0.0;
do
{
const size_t numEvents = inputIter->getNumEvents();
const float signal = static_cast<float>(values->getCalculated(resultValueIndex));
const float signal = static_cast<float>(values.getCalculated(resultValueIndex));
for(size_t i = 0; i < numEvents; ++i)
{
coord_t centers[4] = { inputIter->getInnerPosition(i,0), inputIter->getInnerPosition(i,1),
Expand Down Expand Up @@ -235,6 +260,45 @@ namespace Mantid
return outputWS;
}

/**
* Create an output histo workspace filled with data simulated with the fitting function.
* @param baseName :: The base name for the workspace
* @param function :: The function used for the calculation
* @param domain :: A pointer to the input domain
* @param values :: A pointer to the calculated values
* @param outputWorkspacePropertyName :: The property name
*/
boost::shared_ptr<API::Workspace> FitMD::createHistoOutputWorkspace(const std::string& baseName,
API::IFunction_sptr function,
API::IMDHistoWorkspace_const_sptr inputWorkspace,
const std::string& outputWorkspacePropertyName)
{
// have to cast const away to be able to pass the workspace to the algorithm
API::IMDHistoWorkspace_sptr nonConstInputWS = boost::const_pointer_cast<API::IMDHistoWorkspace,const API::IMDHistoWorkspace>( inputWorkspace );
// evaluate the function on the input workspace
auto alg = API::AlgorithmFactory::Instance().create("EvaluateMDFunction",-1);
alg->setChild( true );
alg->setRethrows( true );
alg->initialize();
alg->setProperty( "Function", function );
alg->setProperty( "InputWorkspace", nonConstInputWS );
alg->setProperty( "OutputWorkspace", "__FitMD_createHistoOutputWorkspace_outputWorkspace" );
alg->execute();

// get the result
API::IMDHistoWorkspace_sptr outputWorkspace = alg->getProperty( "OutputWorkspace" );
// Store it
if ( !outputWorkspacePropertyName.empty() )
{
declareProperty(new API::WorkspaceProperty<API::IMDHistoWorkspace>(outputWorkspacePropertyName,"",Direction::Output),
"Name of the output Workspace holding resulting simulated spectrum");
m_manager->setPropertyValue(outputWorkspacePropertyName,baseName+"Workspace");
m_manager->setProperty(outputWorkspacePropertyName,outputWorkspace);
}

return outputWorkspace;
}

/**
* Set all parameters
*/
Expand Down
67 changes: 66 additions & 1 deletion Code/Mantid/Framework/MDEvents/test/FitMDTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "MantidAPI/FrameworkManager.h"
#include "MantidAPI/IMDIterator.h"
#include "MantidAPI/ITableWorkspace.h"
#include "MantidAPI/IMDHistoWorkspace.h"
#include "MantidMDEvents/UserFunctionMD.h"

#include <sstream>
Expand Down Expand Up @@ -212,10 +213,74 @@ class FitMDTest : public CxxTest::TestSuite
TS_ASSERT_EQUALS(params->Double(2,2), 0.0);

API::AnalysisDataService::Instance().clear();
//--------------------------------------------------//

}

void test_output_histo_workspace()
{
auto inputWS = createHistoWorkspace(3,4, "name=UserFunctionMD,Formula=10 + y + (2 + 0.1*y) * x");

auto fit = API::AlgorithmManager::Instance().create("Fit");
fit->initialize();

fit->setProperty("Function","name=UserFunctionMD,Formula=h + y + (s + 0.1*y) * x, h = 0, s = 0");
fit->setProperty("InputWorkspace",inputWS);
fit->setPropertyValue("Output","out");
fit->execute();

IMDHistoWorkspace_sptr outputWS = AnalysisDataService::Instance().retrieveWS<IMDHistoWorkspace>( "out_Workspace" );
TS_ASSERT( outputWS );
if ( !outputWS ) return;

TS_ASSERT_EQUALS( inputWS->getNPoints(), outputWS->getNPoints() );

uint64_t n = outputWS->getNPoints();
coord_t invVolume = inputWS->getInverseVolume();
for( uint64_t i = 0; i < n; ++i )
{
TS_ASSERT_DELTA( outputWS->signalAt(i) / inputWS->signalAt(i) / invVolume, 1.0, 0.1 );
}

AnalysisDataService::Instance().clear();
}

// ---------------------------------------------------------- //
IMDHistoWorkspace_sptr createHistoWorkspace(size_t nx, size_t ny, const std::string& function)
{

std::vector<double> values( nx * ny, 1.0 );
std::vector<int> dims(2);
dims[0] = static_cast<int>(nx);
dims[1] = static_cast<int>(ny);

auto alg = AlgorithmManager::Instance().create("CreateMDHistoWorkspace");
alg->initialize();
alg->setProperty("SignalInput", values);
alg->setProperty("ErrorInput", values);
alg->setProperty("Dimensionality", 2);
alg->setProperty("NumberOfBins", dims);
alg->setPropertyValue("Extents", "-1,1,-1,1");
alg->setPropertyValue("Names", "A,B");
alg->setPropertyValue("Units", "U,U");
alg->setPropertyValue("OutputWorkspace", "out");
alg->execute();
TS_ASSERT( alg->isExecuted() );

IMDHistoWorkspace_sptr ws = AnalysisDataService::Instance().retrieveWS<IMDHistoWorkspace>("out");

alg = AlgorithmManager::Instance().create("EvaluateMDFunction");
alg->initialize();
alg->setProperty("InputWorkspace", ws);
alg->setPropertyValue("Function",function);
alg->setPropertyValue("OutputWorkspace", "out");
alg->execute();

ws = AnalysisDataService::Instance().retrieveWS<IMDHistoWorkspace>("out");

AnalysisDataService::Instance().remove("out");
return ws;
}


};

Expand Down

0 comments on commit c552656

Please sign in to comment.