-
Campbell, Stuart authoredCampbell, Stuart authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
ConvertToMDMinMaxLocal.cpp 7.38 KiB
#include "MantidMDAlgorithms/ConvertToMDMinMaxLocal.h"
#include <cfloat>
#include "MantidKernel/ArrayProperty.h"
#include "MantidMDAlgorithms/ConvToMDSelector.h"
#include "MantidMDAlgorithms/MDWSTransform.h"
#include "MantidMDAlgorithms/UnitsConversionHelper.h"
using namespace Mantid::Kernel;
using namespace Mantid::API;
namespace Mantid {
namespace MDAlgorithms {
// Register the algorithm into the AlgorithmFactory
DECLARE_ALGORITHM(ConvertToMDMinMaxLocal)
//----------------------------------------------------------------------------------------------
/** Constructor
*/
ConvertToMDMinMaxLocal::ConvertToMDMinMaxLocal() {}
//----------------------------------------------------------------------------------------------
/** Destructor
*/
ConvertToMDMinMaxLocal::~ConvertToMDMinMaxLocal() {}
//----------------------------------------------------------------------------------------------
/// Algorithm's name for identification. @see Algorithm::name
const std::string ConvertToMDMinMaxLocal::name() const {
return "ConvertToMDMinMaxLocal";
}
//----------------------------------------------------------------------------------------------
void ConvertToMDMinMaxLocal::init() {
ConvertToMDParent::init();
declareProperty(
new Kernel::ArrayProperty<double>("MinValues", Direction::Output));
declareProperty(
new Kernel::ArrayProperty<double>("MaxValues", Direction::Output));
}
//----------------------------------------------------------------------------------------------
/** Execute the algorithm.
*/
void ConvertToMDMinMaxLocal::exec() {
// -------- get Input workspace
Mantid::API::MatrixWorkspace_sptr InWS2D = getProperty("InputWorkspace");
// Collect and Analyze the requests to the job, specified by the input
// parameters:
// a) Q selector:
std::string QModReq = getProperty("QDimensions");
// b) the energy exchange mode
std::string dEModReq = getProperty("dEAnalysisMode");
// c) other dim property;
std::vector<std::string> otherDimNames = getProperty("OtherDimensions");
// d) The output dimensions in the Q3D mode, processed together with
// QConversionScales
std::string QFrame = getProperty("Q3DFrames");
// e) part of the procedure, specifying the target dimensions units. Currently
// only Q3D target units can be converted to different flavors of hkl
std::string convertTo_ = getProperty("QConversionScales");
// Build the target ws description as function of the input & output ws and
// the parameters, supplied to the algorithm
MDWSDescription targWSDescr;
// get raw pointer to Q-transformation (do not delete this pointer, it's held
// by MDTransfFactory!)
MDTransfInterface *pQtransf =
MDTransfFactory::Instance().create(QModReq).get();
// get number of dimensions this Q transformation generates from the
// workspace.
auto iEmode = Kernel::DeltaEMode::fromString(dEModReq);
// get total number of dimensions the workspace would have.
unsigned int nMatrixDim = pQtransf->getNMatrixDimensions(iEmode, InWS2D);
// total number of dimensions
size_t nDim = nMatrixDim + otherDimNames.size();
std::vector<double> MinValues, MaxValues;
MinValues.resize(nDim, -FLT_MAX / 10);
MaxValues.resize(nDim, FLT_MAX / 10);
// verify that the number min/max values is equivalent to the number of
// dimensions defined by properties and min is less max
targWSDescr.setMinMax(MinValues, MaxValues);
targWSDescr.buildFromMatrixWS(InWS2D, QModReq, dEModReq, otherDimNames);
// add runindex to the target workspace description for further usage as the
// identifier for the events, which come from this run.
targWSDescr.addProperty("RUN_INDEX", uint16_t(0), true);
// instantiate class, responsible for defining Mslice-type projection
MDAlgorithms::MDWSTransform MsliceProj;
// identify if u,v are present among input parameters and use defaults if not
std::vector<double> ut = getProperty("UProj");
std::vector<double> vt = getProperty("VProj");
std::vector<double> wt = getProperty("WProj");
try {
// otherwise input uv are ignored -> later it can be modified to set ub
// matrix if no given, but this may over-complicate things.
MsliceProj.setUVvectors(ut, vt, wt);
} catch (std::invalid_argument &) {
g_log.error() << "The projections are coplanar. Will use defaults "
"[1,0,0],[0,1,0] and [0,0,1]" << std::endl;
}
// set up target coordinate system and identify/set the (multi) dimension's
// names to use
targWSDescr.m_RotMatrix =
MsliceProj.getTransfMatrix(targWSDescr, QFrame, convertTo_);
// preprocess detectors (or make fake detectors in CopyMD case)
targWSDescr.m_PreprDetTable = this->preprocessDetectorsPositions(
InWS2D, dEModReq, false, std::string(getProperty("PreprocDetectorsWS")));
// do the job
findMinMaxValues(targWSDescr, pQtransf, iEmode, MinValues, MaxValues);
setProperty("MinValues", MinValues);
setProperty("MaxValues", MaxValues);
}
void ConvertToMDMinMaxLocal::findMinMaxValues(MDWSDescription &WSDescription,
MDTransfInterface *const pQtransf,
Kernel::DeltaEMode::Type iEMode,
std::vector<double> &MinValues,
std::vector<double> &MaxValues) {
MDAlgorithms::UnitsConversionHelper unitsConverter;
double signal(1), errorSq(1);
//
size_t nDims = MinValues.size();
MinValues.assign(nDims, DBL_MAX);
MaxValues.assign(nDims, -DBL_MAX);
//
auto inWS = WSDescription.getInWS();
std::string convUnitsID = pQtransf->inputUnitID(iEMode, inWS);
// initialize units conversion
unitsConverter.initialize(WSDescription, convUnitsID);
// initialize MD transformation
pQtransf->initialize(WSDescription);
//
long nHist = static_cast<long>(inWS->getNumberHistograms());
auto detIDMap =
WSDescription.m_PreprDetTable->getColVector<size_t>("detIDMap");
// vector to place transformed coordinates;
std::vector<coord_t> locCoord(nDims);
pQtransf->calcGenericVariables(locCoord, nDims);
// PRAGMA_OMP(parallel for reduction(||:rangeChanged))
for (long i = 0; i < nHist; i++) {
// get valid spectrum number
size_t iSpctr = detIDMap[i];
// update unit conversion according to current spectra
unitsConverter.updateConversion(iSpctr);
// update coordinate transformation according to the spectra
pQtransf->calcYDepCoordinates(locCoord, iSpctr);
// get the range of the input data in the spectra
auto source_range = inWS->getSpectrum(iSpctr)->getXDataRange();
// extract part of this range which has well defined unit conversion
source_range = unitsConverter.getConversionRange(source_range.first,
source_range.second);
double x1 = unitsConverter.convertUnits(source_range.first);
double x2 = unitsConverter.convertUnits(source_range.second);
std::vector<double> range = pQtransf->getExtremumPoints(x1, x2, iSpctr);
// transform coordinates
for (size_t k = 0; k < range.size(); k++) {
pQtransf->calcMatrixCoord(range[k], locCoord, signal, errorSq);
// identify min-max ranges for current spectrum
for (size_t j = 0; j < nDims; j++) {
if (locCoord[j] < MinValues[j])
MinValues[j] = locCoord[j];
if (locCoord[j] > MaxValues[j])
MaxValues[j] = locCoord[j];
}
}
}
}
} // namespace MDAlgorithms
} // namespace Mantid