Skip to content
Snippets Groups Projects
Commit 98d4b45b authored by Verena Reimund's avatar Verena Reimund
Browse files

Add input validation & clean doxygen commands

Refs #22197
parent 3015b137
No related merge requests found
...@@ -48,6 +48,8 @@ public: ...@@ -48,6 +48,8 @@ public:
} }
/// Does the x-axis have non-zero errors /// Does the x-axis have non-zero errors
bool hasNonzeroErrors(Mantid::API::MatrixWorkspace_sptr ws); bool hasNonzeroErrors(Mantid::API::MatrixWorkspace_sptr ws);
/// Cross-check properties with each other @see IAlgorithm::validateInputs
std::map<std::string, std::string> validateInputs() override;
private: private:
/// Helper typedef. For storing indexes of special values per spectra per /// Helper typedef. For storing indexes of special values per spectra per
......
...@@ -3,25 +3,24 @@ ...@@ -3,25 +3,24 @@
#include "MantidAPI/WorkspaceProperty.h" #include "MantidAPI/WorkspaceProperty.h"
#include "MantidAPI/MatrixWorkspace.h" #include "MantidAPI/MatrixWorkspace.h"
#include "MantidAPI/WorkspaceFactory.h" #include "MantidAPI/WorkspaceFactory.h"
#include "MantidHistogramData/HistogramE.h"
#include "MantidHistogramData/HistogramX.h" #include "MantidHistogramData/HistogramX.h"
#include "MantidHistogramData/HistogramY.h" #include "MantidHistogramData/HistogramY.h"
#include "MantidHistogramData/HistogramE.h"
#include "MantidKernel/ArrayProperty.h" #include "MantidKernel/ArrayProperty.h"
#include "MantidKernel/BoundedValidator.h" #include "MantidKernel/BoundedValidator.h"
#include "MantidKernel/MultiThreaded.h" #include "MantidKernel/MultiThreaded.h"
#include "MantidKernel/PropertyWithValue.h" #include "MantidKernel/PropertyWithValue.h"
#include "MantidKernel/RebinParamsValidator.h" #include "MantidKernel/RebinParamsValidator.h"
#include <algorithm>
#include <boost/tuple/tuple.hpp> #include <boost/tuple/tuple.hpp>
#include <boost/format.hpp> #include <boost/format.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/math/special_functions.hpp> #include <boost/math/special_functions.hpp>
#include <algorithm>
using namespace Mantid::Kernel;
using namespace Mantid::API; using namespace Mantid::API;
using Mantid::HistogramData::HistogramY; using namespace Mantid::Kernel;
using Mantid::HistogramData::HistogramE; using Mantid::HistogramData::HistogramE;
using Mantid::HistogramData::HistogramY;
namespace { namespace {
...@@ -37,9 +36,7 @@ bool isNonzero(double i) { return (0 != i); } ...@@ -37,9 +36,7 @@ bool isNonzero(double i) { return (0 != i); }
namespace Mantid { namespace Mantid {
namespace Algorithms { namespace Algorithms {
/** /** Range tolerance
* Range tolerance
*
* This is required for machine precision reasons. Used to adjust StartOverlap * This is required for machine precision reasons. Used to adjust StartOverlap
*and EndOverlap so that they are *and EndOverlap so that they are
* inclusive of bin boundaries if they are sitting ontop of the bin boundaries. * inclusive of bin boundaries if they are sitting ontop of the bin boundaries.
...@@ -48,8 +45,7 @@ const double Stitch1D::range_tolerance = 1e-9; ...@@ -48,8 +45,7 @@ const double Stitch1D::range_tolerance = 1e-9;
// Register the algorithm into the AlgorithmFactory // Register the algorithm into the AlgorithmFactory
DECLARE_ALGORITHM(Stitch1D) DECLARE_ALGORITHM(Stitch1D)
/** /** Zero out all y and e data that is not in the region a1 to a2.
* Zero out all y and e data that is not in the region a1 to a2.
* @param a1 : Zero based bin index (first one) * @param a1 : Zero based bin index (first one)
* @param a2 : Zero based bin index (last one inclusive) * @param a2 : Zero based bin index (last one inclusive)
* @param source : Workspace providing the source data. * @param source : Workspace providing the source data.
...@@ -87,8 +83,8 @@ MatrixWorkspace_sptr Stitch1D::maskAllBut(int a1, int a2, ...@@ -87,8 +83,8 @@ MatrixWorkspace_sptr Stitch1D::maskAllBut(int a1, int a2,
return product; return product;
} }
/** /** Mask out data in the region between a1 and a2 with zeros. Operation
* Mask out data in the region between a1 and a2 with zeros. Operation performed * performed
* on the original workspace * on the original workspace
* @param a1 : start position in X * @param a1 : start position in X
* @param a2 : end position in X * @param a2 : end position in X
...@@ -123,7 +119,8 @@ void Stitch1D::init() { ...@@ -123,7 +119,8 @@ void Stitch1D::init() {
"LHS input workspace."); "LHS input workspace.");
declareProperty(make_unique<WorkspaceProperty<MatrixWorkspace>>( declareProperty(make_unique<WorkspaceProperty<MatrixWorkspace>>(
"RHSWorkspace", "", Direction::Input), "RHSWorkspace", "", Direction::Input),
"RHS input workspace."); "RHS input workspace, must be same type as LHSWorkspace "
"(histogram or point data).");
declareProperty(make_unique<WorkspaceProperty<MatrixWorkspace>>( declareProperty(make_unique<WorkspaceProperty<MatrixWorkspace>>(
"OutputWorkspace", "", Direction::Output), "OutputWorkspace", "", Direction::Output),
"Output stitched workspace."); "Output stitched workspace.");
...@@ -158,7 +155,21 @@ void Stitch1D::init() { ...@@ -158,7 +155,21 @@ void Stitch1D::init() {
"The actual used value for the scaling factor."); "The actual used value for the scaling factor.");
} }
/**Gets the start of the overlapping region /** Validate the algorithm's properties.
* @return A map of porperty names and their issues.
*/
std::map<std::string, std::string> Stitch1D::validateInputs(void) {
std::map<std::string, std::string> issues;
MatrixWorkspace_sptr lhs = getProperty("LHSWorkspace");
MatrixWorkspace_sptr rhs = getProperty("RHSWorkspace");
if (lhs->isHistogramData() && !rhs->isHistogramData())
issues["RHSWorkspace"] = "Must be a histogram like LHSWorkspace.";
if (!lhs->isHistogramData() && rhs->isHistogramData())
issues["RHSWorkspace"] = "Must be point data like LHSWorkspace.";
return issues;
}
/** Gets the start of the overlapping region
@param intesectionMin :: The minimum possible value for the overlapping region @param intesectionMin :: The minimum possible value for the overlapping region
to inhabit to inhabit
@param intesectionMax :: The maximum possible value for the overlapping region @param intesectionMax :: The maximum possible value for the overlapping region
...@@ -189,7 +200,7 @@ double Stitch1D::getStartOverlap(const double &intesectionMin, ...@@ -189,7 +200,7 @@ double Stitch1D::getStartOverlap(const double &intesectionMin,
return startOverlapVal; return startOverlapVal;
} }
/**Gets the end of the overlapping region /** Gets the end of the overlapping region
@param intesectionMin :: The minimum possible value for the overlapping region @param intesectionMin :: The minimum possible value for the overlapping region
to inhabit to inhabit
@param intesectionMax :: The maximum possible value for the overlapping region @param intesectionMax :: The maximum possible value for the overlapping region
...@@ -220,7 +231,7 @@ double Stitch1D::getEndOverlap(const double &intesectionMin, ...@@ -220,7 +231,7 @@ double Stitch1D::getEndOverlap(const double &intesectionMin,
return endOverlapVal; return endOverlapVal;
} }
/**Gets the rebinning parameters and calculates any missing values /** Gets the rebinning parameters and calculates any missing values
@param lhsWS :: The left hand side input workspace @param lhsWS :: The left hand side input workspace
@param rhsWS :: The right hand side input workspace @param rhsWS :: The right hand side input workspace
@param scaleRHS :: Scale the right hand side workspace @param scaleRHS :: Scale the right hand side workspace
...@@ -276,7 +287,7 @@ std::vector<double> Stitch1D::getRebinParams(MatrixWorkspace_sptr &lhsWS, ...@@ -276,7 +287,7 @@ std::vector<double> Stitch1D::getRebinParams(MatrixWorkspace_sptr &lhsWS,
return result; return result;
} }
/**Runs the Rebin Algorithm as a child and replaces special values /** Runs the Rebin Algorithm as a child and replaces special values
@param input :: The input workspace @param input :: The input workspace
@param params :: a vector<double> containing rebinning parameters @param params :: a vector<double> containing rebinning parameters
@return A shared pointer to the resulting MatrixWorkspace @return A shared pointer to the resulting MatrixWorkspace
...@@ -334,7 +345,7 @@ MatrixWorkspace_sptr Stitch1D::rebin(MatrixWorkspace_sptr &input, ...@@ -334,7 +345,7 @@ MatrixWorkspace_sptr Stitch1D::rebin(MatrixWorkspace_sptr &input,
return outWS; return outWS;
} }
/**Runs the Integration Algorithm as a child. /** Runs the Integration Algorithm as a child.
@param input :: The input workspace @param input :: The input workspace
@param start :: a double defining the start of the region to integrate @param start :: a double defining the start of the region to integrate
@param stop :: a double defining the end of the region to integrate @param stop :: a double defining the end of the region to integrate
...@@ -356,7 +367,7 @@ MatrixWorkspace_sptr Stitch1D::integration(MatrixWorkspace_sptr &input, ...@@ -356,7 +367,7 @@ MatrixWorkspace_sptr Stitch1D::integration(MatrixWorkspace_sptr &input,
return outWS; return outWS;
} }
/**Runs the WeightedMean Algorithm as a child /** Runs the WeightedMean Algorithm as a child
@param inOne :: The first input workspace @param inOne :: The first input workspace
@param inTwo :: The second input workspace @param inTwo :: The second input workspace
@return A shared pointer to the resulting MatrixWorkspace @return A shared pointer to the resulting MatrixWorkspace
...@@ -371,7 +382,7 @@ MatrixWorkspace_sptr Stitch1D::weightedMean(MatrixWorkspace_sptr &inOne, ...@@ -371,7 +382,7 @@ MatrixWorkspace_sptr Stitch1D::weightedMean(MatrixWorkspace_sptr &inOne,
return outWS; return outWS;
} }
/**Runs the ConjoinXRuns Algorithm as a child /** Runs the ConjoinXRuns Algorithm as a child
@param inWS :: Input workspace @param inWS :: Input workspace
@return A shared pointer to the resulting MatrixWorkspace @return A shared pointer to the resulting MatrixWorkspace
*/ */
...@@ -390,7 +401,7 @@ MatrixWorkspace_sptr Stitch1D::conjoinXAxis(MatrixWorkspace_sptr &inOne, ...@@ -390,7 +401,7 @@ MatrixWorkspace_sptr Stitch1D::conjoinXAxis(MatrixWorkspace_sptr &inOne,
return outWS; return outWS;
} }
/**Runs the SortXAxis Algorithm as a child /** Runs the SortXAxis Algorithm as a child
@param inWS :: Input workspace @param inWS :: Input workspace
@return A shared pointer to the resulting MatrixWorkspace @return A shared pointer to the resulting MatrixWorkspace
*/ */
...@@ -402,7 +413,7 @@ MatrixWorkspace_sptr Stitch1D::sortXAxis(MatrixWorkspace_sptr &inWS) { ...@@ -402,7 +413,7 @@ MatrixWorkspace_sptr Stitch1D::sortXAxis(MatrixWorkspace_sptr &inWS) {
return outWS; return outWS;
} }
/**Runs the CreateSingleValuedWorkspace Algorithm as a child /** Runs the CreateSingleValuedWorkspace Algorithm as a child
@param val :: The double to convert to a single value workspace @param val :: The double to convert to a single value workspace
@return A shared pointer to the resulting MatrixWorkspace @return A shared pointer to the resulting MatrixWorkspace
*/ */
...@@ -415,7 +426,7 @@ MatrixWorkspace_sptr Stitch1D::singleValueWS(double val) { ...@@ -415,7 +426,7 @@ MatrixWorkspace_sptr Stitch1D::singleValueWS(double val) {
return outWS; return outWS;
} }
/**finds the bins containing the ends of the overlapping region /** Finds the bins containing the ends of the overlapping region
@param startOverlap :: The start of the overlapping region @param startOverlap :: The start of the overlapping region
@param endOverlap :: The end of the overlapping region @param endOverlap :: The end of the overlapping region
@param workspace :: The workspace to determine the overlaps inside @param workspace :: The workspace to determine the overlaps inside
...@@ -435,7 +446,7 @@ Stitch1D::findStartEndIndexes(double startOverlap, double endOverlap, ...@@ -435,7 +446,7 @@ Stitch1D::findStartEndIndexes(double startOverlap, double endOverlap,
return boost::tuple<int, int>(a1, a2); return boost::tuple<int, int>(a1, a2);
} }
/**Determines if a workspace has non zero errors /** Determines if a workspace has non zero errors
@param ws :: The input workspace @param ws :: The input workspace
@return True if there are any non-zero errors in the workspace @return True if there are any non-zero errors in the workspace
*/ */
...@@ -499,7 +510,7 @@ void Stitch1D::exec() { ...@@ -499,7 +510,7 @@ void Stitch1D::exec() {
if (startOverlap < xMin) { if (startOverlap < xMin) {
std::string message = boost::str( std::string message = boost::str(
boost::format("Stitch1D StartOverlap is outside the available X range " boost::format("Stitch1D StartOverlap is outside the available X range. "
"after rebinning. StartOverlap: %10.9f, X min: %10.9f") % "after rebinning. StartOverlap: %10.9f, X min: %10.9f") %
startOverlap % xMin); startOverlap % xMin);
throw std::runtime_error(message); throw std::runtime_error(message);
...@@ -509,7 +520,6 @@ void Stitch1D::exec() { ...@@ -509,7 +520,6 @@ void Stitch1D::exec() {
boost::format("Stitch1D EndOverlap is outside the available X range " boost::format("Stitch1D EndOverlap is outside the available X range "
"after rebinning. EndOverlap: %10.9f, X max: %10.9f") % "after rebinning. EndOverlap: %10.9f, X max: %10.9f") %
endOverlap % xMax); endOverlap % xMax);
throw std::runtime_error(message); throw std::runtime_error(message);
} }
...@@ -526,7 +536,7 @@ void Stitch1D::exec() { ...@@ -526,7 +536,7 @@ void Stitch1D::exec() {
MatrixWorkspace_sptr lhs, rhs; MatrixWorkspace_sptr lhs, rhs;
// If the input workspaces are histograms ... // If the input workspaces are histograms ...
if (rhsWS->isHistogramData() && lhsWS->isHistogramData()) { if (lhsWS->isHistogramData()) {
lhs = rebin(lhsWS, params); lhs = rebin(lhsWS, params);
rhs = rebin(rhsWS, params); rhs = rebin(rhsWS, params);
} }
...@@ -580,7 +590,7 @@ void Stitch1D::exec() { ...@@ -580,7 +590,7 @@ void Stitch1D::exec() {
MatrixWorkspace_sptr overlapave; MatrixWorkspace_sptr overlapave;
// If the input workspaces are histograms ... // If the input workspaces are histograms ...
if (rhsWS->isHistogramData() && lhsWS->isHistogramData()) { if (lhsWS->isHistogramData()) {
if (hasNonzeroErrors(overlap1) && hasNonzeroErrors(overlap2)) { if (hasNonzeroErrors(overlap1) && hasNonzeroErrors(overlap2)) {
overlapave = weightedMean(overlap1, overlap2); overlapave = weightedMean(overlap1, overlap2);
} else { } else {
...@@ -589,17 +599,9 @@ void Stitch1D::exec() { ...@@ -589,17 +599,9 @@ void Stitch1D::exec() {
MatrixWorkspace_sptr denominator = singleValueWS(2.0); MatrixWorkspace_sptr denominator = singleValueWS(2.0);
overlapave = sum / denominator; overlapave = sum / denominator;
} }
} else { } else { // The input workspaces are point data ... join & sort
// If the input workspaces are point data ... auto ws = conjoinXAxis(overlap1, overlap2);
if (!rhsWS->isHistogramData() && !lhsWS->isHistogramData()) { overlapave = sortXAxis(ws);
// Sort according to x values
auto ws = conjoinXAxis(overlap1, overlap2);
overlapave = sortXAxis(ws);
} else {
g_log.error("Input workspaces must be both histograms or point data");
throw std::invalid_argument(
"Input workspaces must be both histograms or point data");
}
} }
MatrixWorkspace_sptr result = lhs + overlapave + rhs; MatrixWorkspace_sptr result = lhs + overlapave + rhs;
...@@ -615,8 +617,7 @@ void Stitch1D::exec() { ...@@ -615,8 +617,7 @@ void Stitch1D::exec() {
setProperty("OutScaleFactor", scaleFactor); setProperty("OutScaleFactor", scaleFactor);
} }
/** /** Put special values back.
* Put special values back.
* @param ws : MatrixWorkspace to resinsert special values into. * @param ws : MatrixWorkspace to resinsert special values into.
*/ */
void Stitch1D::reinsertSpecialValues(MatrixWorkspace_sptr ws) { void Stitch1D::reinsertSpecialValues(MatrixWorkspace_sptr ws) {
......
...@@ -20,13 +20,13 @@ ...@@ -20,13 +20,13 @@
#include <boost/make_shared.hpp> #include <boost/make_shared.hpp>
using namespace Mantid::API; using namespace Mantid::API;
using namespace Mantid::DataObjects;
using namespace Mantid::Kernel; using namespace Mantid::Kernel;
using Mantid::Algorithms::Stitch1D; using Mantid::Algorithms::Stitch1D;
using namespace Mantid::DataObjects;
using Mantid::HistogramData::HistogramX;
using Mantid::HistogramData::HistogramY;
using Mantid::HistogramData::HistogramDx; using Mantid::HistogramData::HistogramDx;
using Mantid::HistogramData::HistogramE; using Mantid::HistogramData::HistogramE;
using Mantid::HistogramData::HistogramX;
using Mantid::HistogramData::HistogramY;
using Mantid::HistogramData::LinearGenerator; using Mantid::HistogramData::LinearGenerator;
double roundSix(double i) { return floor(i * 1000000. + 0.5) / 1000000.; } double roundSix(double i) { return floor(i * 1000000. + 0.5) / 1000000.; }
...@@ -44,8 +44,7 @@ MatrixWorkspace_sptr createWorkspace(const HistogramX &xData, ...@@ -44,8 +44,7 @@ MatrixWorkspace_sptr createWorkspace(const HistogramX &xData,
outWS->mutableY(i) = yData; outWS->mutableY(i) = yData;
outWS->mutableE(i) = eData; outWS->mutableE(i) = eData;
outWS->mutableX(i) = xData; outWS->mutableX(i) = xData;
outWS->setPointStandardDeviations(i, yData.size()); outWS->setPointStandardDeviations(i, Dx);
outWS->mutableDx(i) = Dx;
} }
outWS->getAxis(0)->unit() = UnitFactory::Instance().create("Wavelength"); outWS->getAxis(0)->unit() = UnitFactory::Instance().create("Wavelength");
...@@ -240,22 +239,49 @@ public: ...@@ -240,22 +239,49 @@ public:
std::runtime_error &); std::runtime_error &);
} }
void test_lhsworkspace_must_be_histogram() { void test_point_workspaces_pass() {
auto lhs_ws = make_arbitrary_point_ws(); auto point_ws = make_arbitrary_point_ws();
auto rhs_ws = make_arbitrary_histogram_ws(); const auto &x = HistogramX(3, LinearGenerator(-.5, 0.2));
TSM_ASSERT_THROWS( const auto &y = HistogramY(3, LinearGenerator(1., 1.0));
"Both ws must be either histogram or point data", const auto &e = HistogramE(3, 1.);
do_stitch1D(lhs_ws, rhs_ws, -1., 1., std::vector<double>(1., 0.2)), const auto &dx = HistogramDx(3, LinearGenerator(-3., 0.1));
std::invalid_argument &); auto point_ws_2 = createWorkspace(x, y, e, dx);
TSM_ASSERT_THROWS_NOTHING("Point workspaces should pass",
do_stitch1D(point_ws, point_ws_2));
} }
void test_rhsworkspace_must_be_histogram() { void test_histogram_workspaces_pass() {
auto lhs_ws = make_arbitrary_histogram_ws(); auto histo_ws = make_arbitrary_histogram_ws();
auto rhs_ws = make_arbitrary_point_ws(); const auto &x = HistogramX(3, LinearGenerator(-1.2, 0.2));
TSM_ASSERT_THROWS( const auto &y = HistogramY(2, LinearGenerator(1., 1.0));
"Both ws must be either histogram or point data", const auto &e = HistogramE(2, 1.);
do_stitch1D(lhs_ws, rhs_ws, -1., 1., std::vector<double>(1., 0.2)), const auto &dx = HistogramDx(2, LinearGenerator(-3., 0.1));
std::invalid_argument &); auto histo_ws_2 = createWorkspace(x, y, e, dx);
TSM_ASSERT_THROWS_NOTHING("Histogram workspaces should pass",
do_stitch1D(histo_ws_2, histo_ws));
}
void test_input_validation() {
Stitch1D alg;
alg.setChild(true);
alg.setRethrows(true);
alg.initialize();
alg.setProperty("LHSWorkspace", make_arbitrary_point_ws());
alg.setProperty("RHSWorkspace", make_arbitrary_histogram_ws());
alg.setProperty("StartOverlap", -1);
alg.setProperty("EndOverlap", 1);
alg.setProperty("Params", std::vector<double>(1., 0.2));
alg.setProperty("ScaleRHSWorkspace", true);
alg.setPropertyValue("OutputWorkspace", "dummy_value");
alg.execute();
TSM_ASSERT("RHSWorkspace must be point data.",
!alg.isExecuted());
alg.setProperty("LHSWorkspace", make_arbitrary_histogram_ws());
alg.setProperty("RHSWorkspace", make_arbitrary_point_ws());
alg.execute();
TSM_ASSERT("RHSWorkspace must be a histogram.",
!alg.isExecuted());
} }
void test_stitching_uses_supplied_params() { void test_stitching_uses_supplied_params() {
...@@ -549,7 +575,6 @@ public: ...@@ -549,7 +575,6 @@ public:
TSM_ASSERT("All error values are non-zero", alg.hasNonzeroErrors(ws)); TSM_ASSERT("All error values are non-zero", alg.hasNonzeroErrors(ws));
// Run it again with all zeros // Run it again with all zeros
e = HistogramE(9, 0.); e = HistogramE(9, 0.);
ws = createWorkspace(x, y, e, dx, nspectrum); ws = createWorkspace(x, y, e, dx, nspectrum);
TSM_ASSERT("All error values are non-zero", !alg.hasNonzeroErrors(ws)); TSM_ASSERT("All error values are non-zero", !alg.hasNonzeroErrors(ws));
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment