-
Campbell, Stuart authoredCampbell, Stuart authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
ConvertToDiffractionMDWorkspace2.cpp 10.22 KiB
#include "MantidMDAlgorithms/ConvertToDiffractionMDWorkspace2.h"
#include "MantidAPI/IMDEventWorkspace.h"
#include "MantidAPI/Progress.h"
#include "MantidAPI/WorkspaceValidators.h"
#include "MantidDataObjects/EventWorkspace.h"
#include "MantidDataObjects/MDEventWorkspace.h"
#include "MantidDataObjects/Workspace2D.h"
#include "MantidKernel/ArrayProperty.h"
#include "MantidKernel/EnabledWhenProperty.h"
#include "MantidKernel/ListValidator.h"
#include "MantidMDAlgorithms/MDTransfFactory.h"
#include "MantidMDAlgorithms/MDWSTransform.h"
using namespace Mantid::API;
using namespace Mantid::Kernel;
using namespace Mantid::DataObjects;
using namespace Mantid::Geometry;
namespace Mantid {
namespace MDAlgorithms {
// Register the algorithm into the AlgorithmFactory
DECLARE_ALGORITHM(ConvertToDiffractionMDWorkspace2)
/**Small class to diable propery on interface */
class DisabledProperty : public EnabledWhenProperty {
public:
DisabledProperty() : EnabledWhenProperty("NonExistingProperty", IS_DEFAULT) {}
virtual bool fulfillsCriterion(const IPropertyManager * /*algo*/) const {
return false;
}
};
//----------------------------------------------------------------------------------------------
/** Initialize the algorithm's properties.
*/
void ConvertToDiffractionMDWorkspace2::init() {
declareProperty(new WorkspaceProperty<MatrixWorkspace>("InputWorkspace", "",
Direction::Input),
"An input workspace.");
declareProperty(new WorkspaceProperty<IMDEventWorkspace>(
"OutputWorkspace", "", Direction::Output),
"Name of the output MDEventWorkspace. If the workspace "
"already exists, then the events will be added to it.");
declareProperty(
new PropertyWithValue<bool>("Append", false, Direction::Input),
"Append events to the output workspace. The workspace is replaced if "
"unchecked.");
// Disabled for this version
declareProperty(new PropertyWithValue<bool>("ClearInputWorkspace", false,
Direction::Input),
"Clearing the events from the input workspace during "
"conversion (to save memory) is not supported by algorithm "
"v2");
// disable property on interface
this->setPropertySettings("ClearInputWorkspace", new DisabledProperty());
declareProperty(
new PropertyWithValue<bool>("OneEventPerBin", true, Direction::Input),
"Use the histogram representation (event for event workspaces).\n"
"One MDEvent will be created for each histogram bin (even empty ones).\n"
"Warning! This can use signficantly more memory!");
frameOptions.push_back("Q (sample frame)");
frameOptions.push_back("Q (lab frame)");
frameOptions.push_back("HKL");
declareProperty(
"OutputDimensions", "Q (lab frame)",
boost::make_shared<StringListValidator>(frameOptions),
"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.");
declareProperty(
new PropertyWithValue<bool>("LorentzCorrection", false, Direction::Input),
"Correct the weights of events with by multiplying by the Lorentz "
"formula: sin(theta)^2 / lambda^4");
// Box controller properties. These are the defaults
this->initBoxControllerProps("2" /*SplitInto*/, 1500 /*SplitThreshold*/,
20 /*MaxRecursionDepth*/);
declareProperty(
new PropertyWithValue<int>("MinRecursionDepth", 1),
"Optional. If specified, then all the boxes will be split to this "
"minimum recursion depth. 1 = one level of splitting, etc.\n"
"Be careful using this since it can quickly create a huge number of "
"boxes = (SplitInto ^ (MinRercursionDepth * NumDimensions)).\n"
"But setting this property equal to MaxRecursionDepth property is "
"necessary if one wants to generate multiple file based workspaces in "
"order to merge them later\n");
setPropertyGroup("MinRecursionDepth", getBoxSettingsGroupName());
std::vector<double> extents(2, 0);
extents[0] = -50;
extents[1] = +50;
declareProperty(new ArrayProperty<double>("Extents", extents),
"A comma separated list of min, max for each dimension,\n"
"specifying the extents of each dimension. Optional, default "
"+-50 in each dimension.");
setPropertyGroup("Extents", getBoxSettingsGroupName());
}
/** method to convert the value of the target frame specified for the
*ConvertToDiffractionMDWorksapce into the properties names of the ConvertToMD
* @param TargFrame -- the string, describing target transformation frame in
*the form accepted by convertToDiffractionWorksapce
* @param TargFrameName -- the string describing target transformation frame
*in the form acepted by convertToMD
* @param ScalingName -- default coordinate scaling name accepted by
*convertToMD;
*
*@return TargFrameName and ScalingName
*/
void ConvertToDiffractionMDWorkspace2::convertFramePropertyNames(
const std::string &TargFrame, std::string &TargFrameName,
std::string &ScalingName) {
// ----------------- Handle the type of output
// -------------------------------------
MDAlgorithms::MDWSTransform QSclAndFrames;
if (TargFrame == frameOptions[0]) // "Q (sample frame)"
{
TargFrameName =
QSclAndFrames.getTargetFrame(MDAlgorithms::CnvrtToMD::SampleFrame);
ScalingName = QSclAndFrames.getQScaling(
MDAlgorithms::CnvrtToMD::NoScaling); //< momentums in A^-1
} else if (TargFrame == frameOptions[1]) // "Q (lab frame)"
{
TargFrameName =
QSclAndFrames.getTargetFrame(MDAlgorithms::CnvrtToMD::LabFrame);
ScalingName = QSclAndFrames.getQScaling(
MDAlgorithms::CnvrtToMD::NoScaling); //< momentums in A^-1
} else if (TargFrame == frameOptions[2]) // "HKL"
{
TargFrameName =
QSclAndFrames.getTargetFrame(MDAlgorithms::CnvrtToMD::HKLFrame);
ScalingName = QSclAndFrames.getQScaling(
MDAlgorithms::CnvrtToMD::HKLScale); //< momentums in A^-1
} else {
throw std::invalid_argument(
"ConvertToDiffractionMDWorkspace2::Unknown target frame: " + TargFrame);
}
}
/** Splits extents accepted by convertToDiffreactionMD workspace in the form
*min1,max1 or min1,max1,min2,max2,min3,max3
* into tso vectors min(3),max(3) accepted by convertToMD
* @param Extents -- the vector of extents consititing of 2 or 6 elements
* @param minVal -- 3-vector of minimal values for 3 processed dimensions
* @param maxVal -- 3-vector of maximal values for 3 processed dimensions
*
* @return minVal and maxVal -- two vectors with minimal and maximal values of
*the momentums in the target workspace.
*/
void ConvertToDiffractionMDWorkspace2::convertExtents(
const std::vector<double> &Extents, std::vector<double> &minVal,
std::vector<double> &maxVal) const {
minVal.resize(3);
maxVal.resize(3);
if (Extents.size() == 2) {
for (size_t d = 0; d < 3; d++) {
minVal[d] = Extents[0];
maxVal[d] = Extents[1];
}
} else if (Extents.size() == 6) {
for (size_t d = 0; d < 3; d++) {
minVal[d] = Extents[2 * d + 0];
maxVal[d] = Extents[2 * d + 1];
}
} else
throw std::invalid_argument(
"You must specify either 2 or 6 extents (min,max).");
}
//----------------------------------------------------------------------------------------------
/** Execute the algorithm. */
void ConvertToDiffractionMDWorkspace2::exec() {
Mantid::API::Algorithm_sptr Convert =
createChildAlgorithm("ConvertToMD", 0., 1.);
Convert->initialize();
Convert->setRethrows(true);
Convert->initialize();
Convert->setProperty<MatrixWorkspace_sptr>(
"InputWorkspace", this->getProperty("InputWorkspace"));
Convert->setProperty("OutputWorkspace",
this->getPropertyValue("OutputWorkspace"));
Convert->setProperty("OverwriteExisting", !this->getProperty("Append"));
if (!MDTransfFactory::Instance().exists("Q3D")) {
throw std::runtime_error(" ConvertToMD Q3D plugin used to transform into "
"DiffractionWorkspaced has not been registered "
"with the MDTransformation factory");
}
Convert->setPropertyValue("QDimensions", "Q3D");
std::vector<std::string> dE_modes = Kernel::DeltaEMode::availableTypes();
Convert->setPropertyValue("dEAnalysisMode",
dE_modes[Kernel::DeltaEMode::Elastic]);
std::string TargetFrame, Scaling;
this->convertFramePropertyNames(this->getPropertyValue("OutputDimensions"),
TargetFrame, Scaling);
Convert->setProperty("Q3DFrames", TargetFrame);
Convert->setProperty("QConversionScales", Scaling);
Convert->setProperty("OtherDimensions", "");
Convert->setProperty("PreprocDetectorsWS", "-");
bool lorCorr = this->getProperty("LorentzCorrection");
Convert->setProperty("LorentzCorrection", lorCorr);
bool ignoreZeros = !this->getProperty("OneEventPerBin");
Convert->setProperty("IgnoreZeroSignals", ignoreZeros);
// set extents
std::vector<double> extents = this->getProperty("Extents");
std::vector<double> minVal, maxVal;
convertExtents(extents, minVal, maxVal);
Convert->setProperty("MinValues", minVal);
Convert->setProperty("MaxValues", maxVal);
// Box controller properties. Has defaults
Convert->setProperty("SplitInto", this->getPropertyValue("SplitInto"));
Convert->setProperty("SplitThreshold",
this->getPropertyValue("SplitThreshold"));
Convert->setProperty("MaxRecursionDepth",
this->getPropertyValue("MaxRecursionDepth"));
std::string depth = this->getPropertyValue("MinRecursionDepth");
if (depth == "0")
depth = "1"; // ConvertToMD does not understand 0 depth
Convert->setProperty("MinRecursionDepth", depth);
Convert->executeAsChildAlg();
IMDEventWorkspace_sptr iOut = Convert->getProperty("OutputWorkspace");
this->setProperty("OutputWorkspace", iOut);
}
} // namespace Mantid
} // namespace DataObjects