Commit 381ddfcd authored by Owen Arnold's avatar Owen Arnold
Browse files

refs #6393. Working algorithm.

parent 4484576f
......@@ -238,6 +238,7 @@ set ( INC_FILES
inc/MantidAPI/SampleEnvironment.h
inc/MantidAPI/SingleValueParameter.h
inc/MantidAPI/SingleValueParameterParser.h
inc/MantidAPI/SpecialCoordinateSystem.h
inc/MantidAPI/SpectraAxis.h
inc/MantidAPI/SpectraDetectorMap.h
inc/MantidAPI/TableRow.h
......
......@@ -76,6 +76,8 @@ namespace API
virtual size_t getLinearIndex(size_t index1, size_t index2, size_t index3, size_t index4) const = 0;
virtual double & operator [](const size_t & index) = 0;
virtual void setCoordinateSystem(const Mantid::API::SpecialCoordinateSystem coordinateSystem) = 0;
};
/// Shared pointer to the IMDWorkspace base class
......
......@@ -13,6 +13,7 @@
#include "MantidAPI/MDGeometry.h"
#include "MantidGeometry/MDGeometry/MDImplicitFunction.h"
#include "MantidAPI/IMDWorkspace.h"
#include "MantidAPI/SpecialCoordinateSystem.h"
namespace Mantid
{
......@@ -36,16 +37,6 @@ namespace Mantid
NumEventsNormalization = 2
};
/// Special coordinate systems
enum SpecialCoordinateSystem
{
None = 0,
QLab = 1,
QSample = 2,
HKL = 3
};
/** Basic MD Workspace Abstract Class.
*
......
......@@ -6,6 +6,7 @@
//----------------------------------------------------------------------
#include "MantidAPI/ITableWorkspace.h"
#include "MantidAPI/ExperimentInfo.h"
#include "MantidAPI/SpecialCoordinateSystem.h"
namespace Mantid
{
......@@ -121,7 +122,21 @@ namespace API
* @returns A shared pointer to a TableWorkspace containing the information
*/
virtual API::ITableWorkspace_sptr createDetectorTable() const = 0;
};
//---------------------------------------------------------------------------------------------
/**
* Set the special coordinate system.
* @param coordinateSystem : Special Q3D coordinate system to use.
*/
virtual void setCoordinateSystem(const Mantid::API::SpecialCoordinateSystem coordinateSystem) = 0;
//---------------------------------------------------------------------------------------------
/**
* Get the special coordinate system.
* @returns special Q3D coordinate system to use being used by this PeaksWorkspace object. Probably the one the workspace was generated with.
*/
virtual Mantid::API::SpecialCoordinateSystem getSpecialCoordinateSystem() const = 0;
};
/// Typedef for a shared pointer to a peaks workspace.
......
#ifndef MANTID_MDALGORITHMS_SpecialCoordinateSystem_H_
#define MANTID_MDALGORITHMS_SpecialCoordinateSystem_H_
namespace Mantid
{
namespace API
{
/**
* Special coordinate systems for Q3D.
*/
enum SpecialCoordinateSystem
{
None = 0, QLab = 1, QSample = 2, HKL = 3
};
}
}
#endif
......@@ -33,6 +33,7 @@ set ( SRC_FILES
src/SelectCellOfType.cpp
src/SelectCellWithForm.cpp
src/SetGoniometer.cpp
src/SetSpecialCoordinates.cpp
src/SetUB.cpp
src/ShowPossibleCells.cpp
src/SortHKL.cpp
......@@ -77,6 +78,7 @@ set ( INC_FILES
inc/MantidCrystal/SelectCellOfType.h
inc/MantidCrystal/SelectCellWithForm.h
inc/MantidCrystal/SetGoniometer.h
inc/MantidCrystal/SetSpecialCoordinates.h
inc/MantidCrystal/SetUB.h
inc/MantidCrystal/ShowPossibleCells.h
inc/MantidCrystal/SortHKL.h
......@@ -118,6 +120,7 @@ set ( TEST_FILES
SelectCellOfTypeTest.h
SelectCellWithFormTest.h
SetGoniometerTest.h
SetSpecialCoordinatesTest.h
SetUBTest.h
ShowPossibleCellsTest.h
SortHKLTest.h
......
#ifndef MANTID_CRYSTAL_SETSPECIALCOORDINATES_H_
#define MANTID_CRYSTAL_SETSPECIALCOORDINATES_H_
#include "MantidKernel/System.h"
#include "MantidAPI/Algorithm.h"
#include "MantidAPI/IMDWorkspace.h"
#include <vector>
#include <string>
namespace Mantid
{
namespace Crystal
{
/** SetSpecialCoordinates :
*
Set the special coordinates on an IMDWorspace or peaksworkspace. Also print out any existing special coordinates.
Copyright &copy; 2013 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory
This file is part of Mantid.
Mantid is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
Mantid is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
File change history is stored at: <https://github.com/mantidproject/mantid>
Code Documentation is available at: <http://doxygen.mantidproject.org>
*/
class DLLExport SetSpecialCoordinates : public API::Algorithm
{
public:
SetSpecialCoordinates();
virtual ~SetSpecialCoordinates();
virtual const std::string name() const;
virtual int version() const;
virtual const std::string category() const;
private:
virtual void initDocs();
void init();
void exec();
std::vector<std::string> m_specialCoordinatesNames;
typedef std::map<std::string, Mantid::API::SpecialCoordinateSystem> SpecialCoordinatesNameMap;
SpecialCoordinatesNameMap m_specialCoordinatesMap;
static const std::string QLabOption();
static const std::string QSampleOption();
static const std::string HKLOption();
bool writeCoordinatesToMDEventWorkspace(Mantid::API::Workspace_sptr inWS, Mantid::API::SpecialCoordinateSystem coordinateSystem);
bool writeCoordinatesToMDHistoWorkspace(Mantid::API::Workspace_sptr inWS, Mantid::API::SpecialCoordinateSystem coordinateSystem);
bool writeCoordinatesToPeaksWorkspace(Mantid::API::Workspace_sptr inWS, Mantid::API::SpecialCoordinateSystem coordinateSystem);
};
} // namespace Crystal
} // namespace Mantid
#endif /* MANTID_CRYSTAL_SETSPECIALCOORDINATES_H_ */
/*WIKI*
TODO: Enter a full wiki-markup description of your algorithm here. You can then use the Build/wiki_maker.py script to generate your full wiki page.
*WIKI*/
#include "MantidCrystal/SetSpecialCoordinates.h"
#include "MantidAPI/WorkspaceValidators.h"
#include "MantidAPI/IMDWorkspace.h"
#include "MantidAPI/IPeaksWorkspace.h"
#include "MantidAPI/IMDEventWorkspace.h"
#include "MantidAPI/IMDHistoWorkspace.h"
#include "MantidKernel/ListValidator.h"
#include <boost/make_shared.hpp>
using namespace Mantid::Kernel;
using namespace Mantid::API;
namespace Mantid
{
namespace Crystal
{
// Register the algorithm into the AlgorithmFactory
DECLARE_ALGORITHM(SetSpecialCoordinates)
const std::string SetSpecialCoordinates::QLabOption()
{
static const std::string ret("Q (lab frame)");
return ret;
}
const std::string SetSpecialCoordinates::QSampleOption()
{
static const std::string ret("Q (sample frame)");
return ret;
}
const std::string SetSpecialCoordinates::HKLOption()
{
static const std::string ret("HKL");
return ret;
}
//----------------------------------------------------------------------------------------------
/** Constructor
*/
SetSpecialCoordinates::SetSpecialCoordinates()
{
m_specialCoordinatesNames.push_back(SetSpecialCoordinates::QLabOption());
m_specialCoordinatesNames.push_back(SetSpecialCoordinates::QSampleOption());
m_specialCoordinatesNames.push_back(SetSpecialCoordinates::HKLOption());
m_specialCoordinatesMap.insert(
std::make_pair(SetSpecialCoordinates::QLabOption(), Mantid::API::QLab));
m_specialCoordinatesMap.insert(
std::make_pair(SetSpecialCoordinates::QSampleOption(), Mantid::API::QSample));
m_specialCoordinatesMap.insert(std::make_pair(SetSpecialCoordinates::HKLOption(), Mantid::API::HKL));
}
//----------------------------------------------------------------------------------------------
/** Destructor
*/
SetSpecialCoordinates::~SetSpecialCoordinates()
{
}
//----------------------------------------------------------------------------------------------
/// Algorithm's name for identification. @see Algorithm::name
const std::string SetSpecialCoordinates::name() const { return "SetSpecialCoordinates";};
/// Algorithm's version for identification. @see Algorithm::version
int SetSpecialCoordinates::version() const { return 1;};
/// Algorithm's category for identification. @see Algorithm::category
const std::string SetSpecialCoordinates::category() const { return "Crystal";}
//----------------------------------------------------------------------------------------------
/// Sets documentation strings for this algorithm
void SetSpecialCoordinates::initDocs()
{
this->setWikiSummary("Set or overwrite any Q3D special coordinates.");
this->setOptionalMessage("Set or overwrite any Q3D special coordinates.");
}
//----------------------------------------------------------------------------------------------
/** Initialize the algorithm's properties.
*/
void SetSpecialCoordinates::init()
{
declareProperty(new WorkspaceProperty<Workspace>("InputWorkspace", "", Direction::InOut),
"An input/output workspace. The new log will be added to it.");
declareProperty("SpecialCoordinates", "Q (lab frame)",
boost::make_shared<StringListValidator>(m_specialCoordinatesNames),
"What will be the dimensions of the output workspace?\n"
" Q (lab frame): Wave-vector change of the lattice in the lab frame.\n"
" Q (sample frame): Wave-vector change of the lattice in the frame of the sample (taking out goniometer rotation).\n"
" HKL: Use the sample's UB matrix to convert to crystal's HKL indices.");
}
bool SetSpecialCoordinates::writeCoordinatesToMDEventWorkspace(Workspace_sptr inWS, SpecialCoordinateSystem coordinateSystem)
{
bool written = false;
if (auto mdEventWS = boost::dynamic_pointer_cast<IMDEventWorkspace>(inWS))
{
mdEventWS->setCoordinateSystem(coordinateSystem);
written = true;
}
return written;
}
bool SetSpecialCoordinates::writeCoordinatesToMDHistoWorkspace(Workspace_sptr inWS,
SpecialCoordinateSystem coordinateSystem)
{
bool written = false;
if (auto mdHistoWS = boost::dynamic_pointer_cast<IMDHistoWorkspace>(inWS))
{
mdHistoWS->setCoordinateSystem(coordinateSystem);
written = true;
}
return written;
}
bool SetSpecialCoordinates::writeCoordinatesToPeaksWorkspace(Workspace_sptr inWS,
SpecialCoordinateSystem coordinateSystem)
{
bool written = false;
if (auto peaksWS = boost::dynamic_pointer_cast<IPeaksWorkspace>(inWS))
{
peaksWS->setCoordinateSystem(coordinateSystem);
written = true;
}
return written;
}
//----------------------------------------------------------------------------------------------
/** Execute the algorithm.
*/
void SetSpecialCoordinates::exec()
{
Workspace_sptr inputWS = getProperty("InputWorkspace");
std::string requestedCoordinateSystem = getProperty("SpecialCoordinates");
SpecialCoordinateSystem coordinatesToUse = this->m_specialCoordinatesMap.find(requestedCoordinateSystem)->second;
// Try to write the coordinates to the various allowed types of workspace.
if(!writeCoordinatesToMDEventWorkspace(inputWS, coordinatesToUse))
{
if(!writeCoordinatesToMDHistoWorkspace(inputWS, coordinatesToUse))
{
if(!writeCoordinatesToPeaksWorkspace(inputWS, coordinatesToUse))
{
throw std::invalid_argument("A workspace of this type cannot be processed/");
}
}
}
}
} // namespace Crystal
} // namespace Mantid
#ifndef MANTID_CRYSTAL_SETSPECIALCOORDINATESTEST_H_
#define MANTID_CRYSTAL_SETSPECIALCOORDINATESTEST_H_
#include <cxxtest/TestSuite.h>
#include "MantidCrystal/SetSpecialCoordinates.h"
#include "MantidTestHelpers/WorkspaceCreationHelper.h"
#include "MantidTestHelpers/MDEventsTestHelper.h"
#include "MantidAPI/IPeaksWorkspace.h"
#include "MantidDataObjects/TableWorkspace.h"
#include "MantidDataObjects/PeaksWorkspace.h"
#include "MantidAPI/Workspace.h"
using namespace Mantid::API;
using Mantid::Crystal::SetSpecialCoordinates;
class SetSpecialCoordinatesTest: 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 SetSpecialCoordinatesTest *createSuite()
{
return new SetSpecialCoordinatesTest();
}
static void destroySuite(SetSpecialCoordinatesTest *suite)
{
delete suite;
}
void test_Init()
{
SetSpecialCoordinates alg;
TS_ASSERT_THROWS_NOTHING( alg.initialize())
TS_ASSERT( alg.isInitialized())
}
void test_CannotUseAnyWorkspaceType()
{
Workspace_sptr tableWS = boost::make_shared<Mantid::DataObjects::TableWorkspace>(1);
SetSpecialCoordinates alg;
alg.setRethrows(true);
alg.initialize();
alg.setPropertyValue("SpecialCoordinates", "Q (lab frame)");
alg.setProperty("InputWorkspace", tableWS);
TSM_ASSERT_THROWS("Only IMDWorkspaces and IPeaksWorkspaces are acceptable inputs.", alg.execute(),
std::invalid_argument&);
}
void test_qLabAllowed()
{
SetSpecialCoordinates alg;
alg.setRethrows(true);
alg.initialize();
TS_ASSERT_THROWS_NOTHING(alg.setPropertyValue("SpecialCoordinates", "Q (lab frame)"));
}
void test_qSampleAllowed()
{
SetSpecialCoordinates alg;
alg.setRethrows(true);
alg.initialize();
TS_ASSERT_THROWS_NOTHING(alg.setPropertyValue("SpecialCoordinates", "Q (sample frame)"));
}
void test_HKLAllowed()
{
SetSpecialCoordinates alg;
alg.setRethrows(true);
alg.initialize();
TS_ASSERT_THROWS_NOTHING(alg.setPropertyValue("SpecialCoordinates", "HKL"));
}
void test_junkCoordinateSystemDisallowed()
{
SetSpecialCoordinates alg;
alg.setRethrows(true);
alg.initialize();
TS_ASSERT_THROWS(alg.setPropertyValue("SpecialCoordinates", "Junk"), std::invalid_argument&);
TS_ASSERT(alg.isInitialized());
}
void test_ModifyMDEventWorkspace()
{
IMDEventWorkspace_sptr inWS = Mantid::MDEvents::MDEventsTestHelper::makeMDEW<1>(1, 0, 1, 1);
AnalysisDataService::Instance().add("inWS", inWS);
SetSpecialCoordinates alg;
alg.setRethrows(true);
alg.initialize();
alg.setPropertyValue("SpecialCoordinates", "Q (sample frame)");
alg.setPropertyValue("InputWorkspace", "inWS");
alg.execute();
auto outWS = AnalysisDataService::Instance().retrieveWS<IMDWorkspace>("inWS");
TS_ASSERT_EQUALS(QSample, outWS->getSpecialCoordinateSystem());
AnalysisDataService::Instance().remove("inWS");
}
void test_ModifyMDHistoWorkspace()
{
IMDHistoWorkspace_sptr inWS = Mantid::MDEvents::MDEventsTestHelper::makeFakeMDHistoWorkspace(1, 1);
AnalysisDataService::Instance().add("inWS", inWS);
SetSpecialCoordinates alg;
alg.setRethrows(true);
alg.initialize();
alg.setPropertyValue("SpecialCoordinates", "Q (sample frame)");
alg.setPropertyValue("InputWorkspace", "inWS");
alg.execute();
auto outWS = AnalysisDataService::Instance().retrieveWS<IMDWorkspace>("inWS");
TS_ASSERT_EQUALS(QSample, outWS->getSpecialCoordinateSystem());
AnalysisDataService::Instance().remove("inWS");
}
void test_ModifyPeaksWorkspace()
{
IPeaksWorkspace_sptr inWS = WorkspaceCreationHelper::createPeaksWorkspace(1);
AnalysisDataService::Instance().add("inWS", inWS);
SetSpecialCoordinates alg;
alg.setRethrows(true);
alg.initialize();
alg.setPropertyValue("SpecialCoordinates", "Q (sample frame)");
alg.setPropertyValue("InputWorkspace", "inWS");
alg.execute();
auto outWS = AnalysisDataService::Instance().retrieveWS<IPeaksWorkspace>("inWS");
TS_ASSERT_EQUALS(QSample, outWS->getSpecialCoordinateSystem());
AnalysisDataService::Instance().remove("inWS");
}
};
#endif /* MANTID_CRYSTAL_SETSPECIALCOORDINATESTEST_H_ */
......@@ -114,6 +114,12 @@ namespace DataObjects
/// peaks within the workspace
API::ITableWorkspace_sptr createDetectorTable() const;
/// Set the special coordinate system.
virtual void setCoordinateSystem(const Mantid::API::SpecialCoordinateSystem coordinateSystem);
/// Get the special coordinate system.
virtual Mantid::API::SpecialCoordinateSystem getSpecialCoordinateSystem() const;
// ====================================== ITableWorkspace Methods ==================================
/// Number of columns in the workspace.
virtual size_t columnCount() const
......
......@@ -33,545 +33,579 @@ using namespace Mantid::Geometry;
namespace Mantid
{
namespace DataObjects
{
/// Register the workspace as a type
DECLARE_WORKSPACE(PeaksWorkspace );
// Kernel::Logger& PeaksWorkspace::g_log = Kernel::Logger::get("PeaksWorkspace");
//---------------------------------------------------------------------------------------------
/** Constructor. Create a table with all the required columns.
*
* @return PeaksWorkspace object
*/
PeaksWorkspace::PeaksWorkspace()
: IPeaksWorkspace()
namespace DataObjects
{
initColumns();
}
/// Register the workspace as a type
DECLARE_WORKSPACE(PeaksWorkspace);
//---------------------------------------------------------------------------------------------
/** Virtual constructor. Clone method to duplicate the peaks workspace.
*
* @return PeaksWorkspace object
*/
PeaksWorkspace* PeaksWorkspace::clone() const
{
//Deep copy via copy construtor.
return new PeaksWorkspace(*this);
}
// Kernel::Logger& PeaksWorkspace::g_log = Kernel::Logger::get("PeaksWorkspace");
//---------------------------------------------------------------------------------------------
/** Constructor. Create a table with all the required columns.
*
* @return PeaksWorkspace object
*/
PeaksWorkspace::PeaksWorkspace() :
IPeaksWorkspace()
{
initColumns();
}
//---------------------------------------------------------------------------------------------
/** Copy constructor
*
* @param other :: other PeaksWorkspace to copy from
* @return
*/
PeaksWorkspace::PeaksWorkspace(const PeaksWorkspace & other)
: IPeaksWorkspace(other), peaks(other.peaks)
{
initColumns();
}
//---------------------------------------------------------------------------------------------
/** Virtual constructor. Clone method to duplicate the peaks workspace.
*
* @return PeaksWorkspace object
*/
PeaksWorkspace* PeaksWorkspace::clone() const
{
//Deep copy via copy construtor.
return new PeaksWorkspace(*this);
}
//---------------------------------------------------------------------------------------------
/** Clone a shared pointer
*
* @return copy of the peaksworkspace
*/
boost::shared_ptr<PeaksWorkspace> PeaksWorkspace::clone()
{
// Copy construct and return
return boost::shared_ptr<PeaksWorkspace>(new PeaksWorkspace(*this));
}
//---------------------------------------------------------------------------------------------
/** Copy constructor
*
* @param other :: other PeaksWorkspace to copy from
* @return
*/
PeaksWorkspace::PeaksWorkspace(const PeaksWorkspace & other) :
IPeaksWorkspace(other), peaks(other.peaks)
{
initColumns();
}