-
Gigg, Martyn Anthony authored
It removes MDAlgorithms as a dependency from Algorithms. Refs #11209
Gigg, Martyn Anthony authoredIt removes MDAlgorithms as a dependency from Algorithms. Refs #11209
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
ConvertMDHistoToMatrixWorkspaceTest.h 16.40 KiB
/*
* ConvertMDHistoToMatrixWorkspaceTest.h
*
* Created on: Feb 13, 2014
* Author: spu92482
*/
#ifndef CONVERTMDHISTOTOMATRIXWORKSPACETEST_H_
#define CONVERTMDHISTOTOMATRIXWORKSPACETEST_H_
#include <cxxtest/TestSuite.h>
#include "MantidAPI/AlgorithmManager.h"
#include "MantidAPI/FrameworkManager.h"
#include "MantidMDAlgorithms/ConvertMDHistoToMatrixWorkspace.h"
#include "MantidDataObjects/MDHistoWorkspace.h"
#include "MantidTestHelpers/MDEventsTestHelper.h"
#include "MantidTestHelpers/WorkspaceCreationHelper.h"
#include <boost/lexical_cast.hpp>
using namespace Mantid;
using namespace Mantid::API;
using namespace Mantid::DataObjects;
using namespace Mantid::Kernel;
using namespace Mantid::MDAlgorithms;
class ConvertMDHistoToMatrixWorkspaceTest : public CxxTest::TestSuite
{
public:
// This pair of boilerplate methods prevent the suite being created statically
// This means the constructor isn't called when running other tests
static ConvertMDHistoToMatrixWorkspaceTest *createSuite() { return new ConvertMDHistoToMatrixWorkspaceTest(); }
static void destroySuite( ConvertMDHistoToMatrixWorkspaceTest *suite ) { delete suite; }
MatrixWorkspace_sptr do_execute_on_1D_directly(const size_t n_dims, const double signal, const double error_sq, size_t* nbins, coord_t* min, coord_t* max)
{
IMDHistoWorkspace_sptr inWS = MDEventsTestHelper::makeFakeMDHistoWorkspaceGeneral(n_dims, signal,
error_sq, nbins, min, max);
ConvertMDHistoToMatrixWorkspace alg;
alg.setChild(true);
alg.setRethrows(true);
alg.initialize();
alg.setProperty("InputWorkspace", inWS);
alg.setPropertyValue("OutputWorkspace", "_");
alg.execute();
MatrixWorkspace_sptr outWS = alg.getProperty("OutputWorkspace");
return outWS;
}
/**
* Test convesion of a MD workspace to a 2D MatrixWorkspace.
*
* @param ndims :: Number of dimensions in the input MDHistoWorkspace. ndims >= 2.
* @param nonIntegr :: Indices of the non-integrated dimensions. There must be 2 of them to pass the test.
*/
void do_test_2D_slice(size_t ndims, std::vector<size_t> nonIntegr)
{
// create an MD histo workspace
size_t size = 1;
// property values for CreateMDHistoWorkspace
std::vector<size_t> numberOfBins(ndims);
std::vector<std::string> names(ndims);
// property values for SliceMDHisto
std::vector<coord_t> start(ndims);
std::vector<coord_t> end(ndims);
for(size_t i = 0; i < ndims; ++i)
{
names[i] = "x_" + boost::lexical_cast<std::string>(i);
if ( nonIntegr.end() != std::find( nonIntegr.begin(), nonIntegr.end(), i) )
{
size_t nbins = 3 + i;
size *= nbins;
numberOfBins[i] = nbins;
// if it's a non-integrated dimension - don't slice
end[i] = static_cast<coord_t>(nbins);
}
else
{
numberOfBins[i] = 1;
}
}
signal_t signal(0.f), error(0.f);
IMDHistoWorkspace_sptr slice = MDEventsTestHelper::makeFakeMDHistoWorkspaceGeneral(ndims, signal,
error, &numberOfBins.front(), &start.front(), &end.front(), names);
// test ConvertMDHistoToMatrixWorkspace
auto alg = AlgorithmManager::Instance().create("ConvertMDHistoToMatrixWorkspace");
alg->initialize();
alg->setRethrows(true);
alg->setChild(true);
alg->setProperty("InputWorkspace", slice);
alg->setPropertyValue("OutputWorkspace", "_2"); // Not really required for child algorithm
if ( nonIntegr.size() > 2 || nonIntegr.empty() )
{
TS_ASSERT_THROWS( alg->execute(), std::invalid_argument );
}
else
{
try
{
alg->execute();
}
catch(std::exception& e)
{
TS_FAIL(e.what());
}
MatrixWorkspace_sptr matrix = alg->getProperty("OutputWorkspace");
TS_ASSERT( matrix );
if ( nonIntegr.size() == 1 )
{
TS_ASSERT_EQUALS( matrix->getNumberHistograms(), 1 );
}
if ( nonIntegr.size() >= 1 )
{
auto xDim = slice->getDimension(nonIntegr[0]);
TS_ASSERT_EQUALS( xDim->getNBins(), matrix->blocksize() );
for(size_t i = 0; i < matrix->getNumberHistograms(); ++i)
{
TS_ASSERT_EQUALS( matrix->readX(i).front(), xDim->getMinimum() );
TS_ASSERT_EQUALS( matrix->readX(i).back(), xDim->getMaximum() );
}
}
else if ( nonIntegr.size() == 2 )
{
auto yDim = slice->getDimension(nonIntegr[1]);
TS_ASSERT_EQUALS( yDim->getNBins(), matrix->getNumberHistograms() );
auto axis = matrix->getAxis(1);
TS_ASSERT_EQUALS( axis->getMin(), yDim->getMinimum() );
TS_ASSERT_EQUALS( axis->getMax(), yDim->getMaximum() );
}
}
}
public:
void test_input_workspace_must_be_imdhisto()
{
MatrixWorkspace_sptr ws = WorkspaceCreationHelper::Create1DWorkspaceConstant(1,1,0);
ConvertMDHistoToMatrixWorkspace alg;
alg.setRethrows(true);
alg.initialize();
TS_ASSERT_THROWS(alg.setProperty("InputWorkspace", ws), std::invalid_argument&) ;
}
/*
* Test the conversion where there is no coordinate transformation to apply (no original workspace). So the coordinates are directly
* translated from the MDHistoWorkspace to the output MDWorkspace.
*/
void test_direct_conversion()
{
const size_t n_dims = 1;
const double signal = 1;
const double error_sq = 0;
size_t nbins[1] = {2};
coord_t min[1] = {-1};
coord_t max[1] = {1};
MatrixWorkspace_sptr out_ws = do_execute_on_1D_directly(n_dims, signal, error_sq, nbins, min, max);
TS_ASSERT_EQUALS(out_ws->getNumberHistograms(), 1);
auto first_x_spectra = out_ws->readX(0);
TS_ASSERT_EQUALS(first_x_spectra.front(), -1);
TS_ASSERT_EQUALS(first_x_spectra.back(), 1);
}
/*
* Test the conversion where there IS a coordinate transformation to apply. The original coordinates are transformed via the coordinate
* transformation on the original workspace.
*/
void test_indirect_conversion()
{
auto in_ws = MDEventsTestHelper::makeMDEW<2>(2, -10.0, 10, 3);
// Create a line slice at 45 degrees to the original workspace.
IAlgorithm_sptr binMDAlg = AlgorithmManager::Instance().create("BinMD");
binMDAlg->setRethrows(true);
binMDAlg->initialize();
binMDAlg->setChild(true);
binMDAlg->setProperty("InputWorkspace", in_ws);
binMDAlg->setProperty("AxisAligned", false);
binMDAlg->setPropertyValue("BasisVector0", "X,units,0.7071,0.7071"); // cos 45 to in_ws x-axis (consistent with a 45 degree anti-clockwise rotation)
binMDAlg->setPropertyValue("BasisVector1", "Y,units,-0.7071,0.7071"); // cos 45 to in_ws y-axis (consistent with a 45 degree anti-clockwise rotation)
binMDAlg->setPropertyValue("Translation", "-10,-10");
binMDAlg->setPropertyValue("OutputExtents", "0,28.284,-1,1"); // x goes from 0 to sqrt((-10-10)^2 + (-10-10)^2) and -1 to 1 in new system, but -10 to 10 in old coordinate axes for both x and y.
binMDAlg->setPropertyValue("OutputBins", "10,1");
binMDAlg->setPropertyValue("OutputWorkspace", "_"); // Not really required for child algorithm
binMDAlg->execute();
Workspace_sptr temp = binMDAlg->getProperty("OutputWorkspace");
auto slice = boost::dynamic_pointer_cast<IMDWorkspace>(temp);
ConvertMDHistoToMatrixWorkspace convert_alg;
convert_alg.setRethrows(true);
convert_alg.setChild(true);
convert_alg.initialize();
convert_alg.setProperty("InputWorkspace", slice);
convert_alg.setPropertyValue("OutputWorkspace", "_"); // Not really required for child algorithm
convert_alg.execute();
MatrixWorkspace_sptr out_ws = convert_alg.getProperty("OutputWorkspace");
TS_ASSERT_EQUALS(out_ws->getNumberHistograms(), 1);
auto first_x_spectra = out_ws->readX(0);
TSM_ASSERT_DELTA("First coordinate in the incorrect position. Incorrect transformation.", first_x_spectra.front(), -10, 1e-3);
TSM_ASSERT_DELTA( "Last coordinate in the incorrect position. Incorrect transformation.", first_x_spectra.back(), 10, 1e-3);
}
/*
What we are attempting to show here is that the dimension that gets selected as the x-axis for the
output matrix workspace, should be the one that has the greatest delta (start - end point) in the original coordinates.
In this case, that corresponds the the X-axis of the input workspace, so we should see the extents of the output matrix workspace
corresponding to -10 to 10, because that is how the cut was made.
Here's a schematic of the input MD workspace
y
| x (10,5)
| .
| .
(0,0) | .
----------------------------- x
. |
. |
. |
(-10,-5)x |
*/
void test_indirect_conversion_axis_selection_where_zeroth_dim_of_original_is_used()
{
auto in_ws = MDEventsTestHelper::makeMDEW<2>(2, -10.0, 10, 3);
// Create a line slice at degrees to the original workspace.
IAlgorithm_sptr binMDAlg = AlgorithmManager::Instance().create("BinMD");
binMDAlg->setRethrows(true);
binMDAlg->initialize();
binMDAlg->setChild(true);
binMDAlg->setProperty("InputWorkspace", in_ws);
binMDAlg->setProperty("AxisAligned", false);
binMDAlg->setPropertyValue("BasisVector0", "X,units,0.6666, 0.3333"); // Line set up to intersects 0,0 and 10,5 in original coords. Basis0 vector is therefore 10/(10+5) and 5/(10+5)
binMDAlg->setPropertyValue("BasisVector1", "Y,units,-0.3333, 0.6666"); // Line set up to intersects 0,0 and -10,5 in original coords. Basis1 vector is therefore 5/(10+5) and 10/(10+5)
binMDAlg->setPropertyValue("Translation", "-10,-5");
binMDAlg->setPropertyValue("OutputExtents", "0,22.36,-1,1"); // x goes from 0 to sqrt((-10-10)^2 + (-5-5)^2) and -1 to 1 in original coords
binMDAlg->setPropertyValue("OutputBins", "10,1");
binMDAlg->setPropertyValue("OutputWorkspace", "_"); // Not really required for child algorithm
binMDAlg->execute();
Workspace_sptr temp = binMDAlg->getProperty("OutputWorkspace");
auto slice = boost::dynamic_pointer_cast<IMDWorkspace>(temp);
ConvertMDHistoToMatrixWorkspace convert_alg;
convert_alg.setRethrows(true);
convert_alg.setChild(true);
convert_alg.initialize();
convert_alg.setProperty("InputWorkspace", slice);
convert_alg.setPropertyValue("OutputWorkspace", "_"); // Not really required for child algorithm
convert_alg.execute();
MatrixWorkspace_sptr out_ws = convert_alg.getProperty("OutputWorkspace");
// Should select the first dimension in this case.
TSM_ASSERT_EQUALS("Wrong dimension auto selected for output x-axis", in_ws->getDimension(0)->getName(), out_ws->getDimension(0)->getName());
TS_ASSERT_EQUALS(out_ws->getNumberHistograms(), 1);
auto first_x_spectra = out_ws->readX(0);
TSM_ASSERT_DELTA("First coordinate in the incorrect position. Incorrect transformation.", first_x_spectra.front(), -10, 1e-3);
TSM_ASSERT_DELTA( "Last coordinate in the incorrect position. Incorrect transformation.", first_x_spectra.back(), 10, 1e-3);
}
/*
What we are attempting to show here is that the dimension that gets selected as the x-axis for the
output matrix workspace, should be the one that has the greatest delta (start - end point) in the original coordinates.
In this case, that corresponds the the Y-axis of the input MD workspace, so we should see the extents of the output matrix workspace
corresponding to -10 to 10, because that is how the cut was made.
Here's a schematic of the input MD workspace
y
| x (5,8)
| .
| .
(0,0) | .
----------------------------- x
. |
. |
. |
(-5,-8)x |
*/
void test_indirect_conversion_axis_selection_where_y_dim_of_original_is_used()
{
auto in_ws = MDEventsTestHelper::makeMDEW<2>(2, -10.0, 10, 3);
// Create a line slice at degrees to the original workspace.
IAlgorithm_sptr binMDAlg = AlgorithmManager::Instance().create("BinMD");
binMDAlg->setRethrows(true);
binMDAlg->initialize();
binMDAlg->setChild(true);
binMDAlg->setProperty("InputWorkspace", in_ws);
binMDAlg->setProperty("AxisAligned", false);
binMDAlg->setPropertyValue("BasisVector0", "X,units,0.3846, 0.6154"); // Line set up to intersect 0,0 and 5,10 in original coords. Basis0 vector is therefore and 5/(5+8), 8/(5+8)
binMDAlg->setPropertyValue("BasisVector1", "Y,units,-0.6154, 0.3846"); // Line set up to intersect 0,0 and -5,10 in original coords. Basis1 vector is therefore -8/(5+8) and 5/(5+8)
binMDAlg->setPropertyValue("Translation", "-5,-8");
binMDAlg->setPropertyValue("OutputExtents", "0,18.867,-1,1"); // x goes from 0 to sqrt((-8-8)^2 + (-5-5)^2) and -1 to 1 in original coords
binMDAlg->setPropertyValue("OutputBins", "10,1");
binMDAlg->setPropertyValue("OutputWorkspace", "_"); // Not really required for child algorithm
binMDAlg->execute();
Workspace_sptr temp = binMDAlg->getProperty("OutputWorkspace");
auto slice = boost::dynamic_pointer_cast<IMDWorkspace>(temp);
ConvertMDHistoToMatrixWorkspace convert_alg;
convert_alg.setRethrows(true);
convert_alg.setChild(true);
convert_alg.initialize();
convert_alg.setProperty("InputWorkspace", slice);
convert_alg.setPropertyValue("OutputWorkspace", "_"); // Not really required for child algorithm
convert_alg.execute();
MatrixWorkspace_sptr out_ws = convert_alg.getProperty("OutputWorkspace");
// Should select the 2nd dimension for the x-axis in this case.
TSM_ASSERT_EQUALS("Wrong dimension auto selected for output x-axis", in_ws->getDimension(1)->getName(), out_ws->getDimension(0)->getName());
TS_ASSERT_EQUALS(out_ws->getNumberHistograms(), 1);
auto first_x_spectra = out_ws->readX(0);
TSM_ASSERT_DELTA("First coordinate in the incorrect position. Incorrect transformation.", first_x_spectra.front(), -8, 1e-3);
TSM_ASSERT_DELTA("Last coordinate in the incorrect position. Incorrect transformation.", first_x_spectra.back(), 8, 1e-3);
// Run it again, this time with FindXAxis set off.
convert_alg.setProperty("FindXAxis", false);
convert_alg.execute();
out_ws = convert_alg.getProperty("OutputWorkspace");
TSM_ASSERT_EQUALS("FindXAxis if off", "X", out_ws->getDimension(0)->getName());
TS_ASSERT_EQUALS(out_ws->getNumberHistograms(), 1);
first_x_spectra = out_ws->readX(0);
TSM_ASSERT_DELTA("First coordinate in the incorrect position. Incorrect transformation.", first_x_spectra.front(), -5, 1e-3);
TSM_ASSERT_DELTA("Last coordinate in the incorrect position. Incorrect transformation.", first_x_spectra.back(), 5, 1e-3);
}
void test_2D_slice_0()
{
// 4D sliced to 2D
std::vector<size_t> nonIntegr(2);
nonIntegr[0] = 0;
nonIntegr[1] = 1;
do_test_2D_slice(4,nonIntegr);
}
void test_2D_slice_1()
{
// 4D unsliced
do_test_2D_slice(4,std::vector<size_t>());
}
void test_2D_slice_2()
{
// 4D sliced to 3D
std::vector<size_t> nonIntegr(3);
nonIntegr[0] = 0;
nonIntegr[1] = 1;
nonIntegr[2] = 2;
do_test_2D_slice(4,nonIntegr);
}
void test_2D_slice_3()
{
// 4D sliced to 2D
std::vector<size_t> nonIntegr(2);
nonIntegr[0] = 0;
nonIntegr[1] = 2;
do_test_2D_slice(4,nonIntegr);
}
void test_2D_slice_4()
{
// 4D sliced to 2D
std::vector<size_t> nonIntegr(2);
nonIntegr[0] = 0;
nonIntegr[1] = 3;
do_test_2D_slice(4,nonIntegr);
}
void test_2D_slice_5()
{
// 4D sliced to 2D
std::vector<size_t> nonIntegr(2);
nonIntegr[0] = 1;
nonIntegr[1] = 3;
do_test_2D_slice(4,nonIntegr);
}
void test_2D_slice_6()
{
// 3D sliced to 2D
std::vector<size_t> nonIntegr(2);
nonIntegr[0] = 1;
nonIntegr[1] = 2;
do_test_2D_slice(3,nonIntegr);
}
void test_2D_slice_7()
{
// 4D sliced to 1D
std::vector<size_t> nonIntegr(1,0);
do_test_2D_slice(4,nonIntegr);
}
void test_2D_slice_8()
{
// 4D sliced to 1D
std::vector<size_t> nonIntegr(1,1);
do_test_2D_slice(4,nonIntegr);
}
void test_2D_slice_9()
{
// 4D sliced to 1D
std::vector<size_t> nonIntegr(1,2);
do_test_2D_slice(4,nonIntegr);
}
void test_2D_slice_10()
{
// 4D sliced to 1D
std::vector<size_t> nonIntegr(1,3);
do_test_2D_slice(4,nonIntegr);
}
void test_2D_slice_11()
{
// 2D unsliced
do_test_2D_slice(2,std::vector<size_t>());
}
void test_2D_slice_12()
{
// 1D unsliced
do_test_2D_slice(1,std::vector<size_t>());
}
};
#endif /* CONVERTMDHISTOTOMATRIXWORKSPACETEST_H_ */