From 294f9fc9293f12ccb827a057f0d4b8f43bed673c Mon Sep 17 00:00:00 2001 From: Keith Brown <keith.brown@stfc.ac.uk> Date: Thu, 29 May 2014 17:12:51 +0100 Subject: [PATCH] Refs #9475 More tests working, intersect bugfix Fixed bug in x-intersect code Got two more tests working and passing Quashed a few warnings relating to double and unsigned int64 types --- .../inc/MantidAlgorithms/Stitch1D.h | 7 + .../Framework/Algorithms/src/Stitch1D.cpp | 120 +++++++++++++++++- .../Framework/Algorithms/test/Stitch1DTest.h | 81 +++++++++++- 3 files changed, 203 insertions(+), 5 deletions(-) diff --git a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/Stitch1D.h b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/Stitch1D.h index c33366a2b7a..1c5bf9878a4 100644 --- a/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/Stitch1D.h +++ b/Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/Stitch1D.h @@ -3,6 +3,7 @@ #include "MantidKernel/System.h" #include "MantidAPI/Algorithm.h" +#include <boost/tuple/tuple.hpp> namespace Mantid { @@ -47,9 +48,15 @@ namespace Algorithms void exec(); double getStartOverlap(const double& min, const double& max) const; double getEndOverlap(const double& min, const double& max) const; + bool hasNonzeroErrors(Mantid::API::MatrixWorkspace_sptr& ws) const; Mantid::MantidVec getRebinParams(Mantid::API::MatrixWorkspace_sptr& lhsWS, Mantid::API::MatrixWorkspace_sptr& rhsWS) const; Mantid::API::MatrixWorkspace_sptr rebin(Mantid::API::MatrixWorkspace_sptr& input, const Mantid::MantidVec& params); Mantid::API::MatrixWorkspace_sptr integration(Mantid::API::MatrixWorkspace_sptr& input, const double& start, const double& stop); + Mantid::API::MatrixWorkspace_sptr multiplyRange(Mantid::API::MatrixWorkspace_sptr& input, const int& startBin, const int& endBin, const double& factor); + Mantid::API::MatrixWorkspace_sptr multiplyRange(Mantid::API::MatrixWorkspace_sptr& input, const int& startBin, const double& factor); + Mantid::API::MatrixWorkspace_sptr singleValueWS(double val); + Mantid::API::MatrixWorkspace_sptr weightedMean(Mantid::API::MatrixWorkspace_sptr& inOne, Mantid::API::MatrixWorkspace_sptr& inTwo); + boost::tuple<int,int> findStartEndIndexes(double startOverlap, double endOverlap, Mantid::API::MatrixWorkspace_sptr& workspace); }; diff --git a/Code/Mantid/Framework/Algorithms/src/Stitch1D.cpp b/Code/Mantid/Framework/Algorithms/src/Stitch1D.cpp index 20f62fff20e..95b9bc6777e 100644 --- a/Code/Mantid/Framework/Algorithms/src/Stitch1D.cpp +++ b/Code/Mantid/Framework/Algorithms/src/Stitch1D.cpp @@ -31,6 +31,11 @@ namespace MantidVec rhs_x = rhsWS->readX(0); return MinMaxTuple(rhs_x.front(), lhs_x.back()); } + + bool isNonzero (double i) + { + return (0 != i); + } } namespace Mantid @@ -159,7 +164,7 @@ namespace Mantid } endOverlapVal = intesectionMax; std::stringstream buffer; - buffer << "StartOverlap calculated to be: " << endOverlapVal; + buffer << "EndOverlap calculated to be: " << endOverlapVal; g_log.information(buffer.str()); } return endOverlapVal; @@ -229,6 +234,75 @@ namespace Mantid return outWS; } + MatrixWorkspace_sptr Stitch1D::multiplyRange(MatrixWorkspace_sptr& input, const int& startBin, const int& endBin, const double& factor) + { + auto multiplyRange = this->createChildAlgorithm("MultiplyRange"); + multiplyRange->setProperty("InputWorkspace", input); + multiplyRange->setProperty("StartBin", startBin); + multiplyRange->setProperty("EndBin", endBin); + multiplyRange->setProperty("Factor", factor); + multiplyRange->execute(); + MatrixWorkspace_sptr outWS = multiplyRange->getProperty("OutputWorkspace"); + return outWS; + } + + MatrixWorkspace_sptr Stitch1D::multiplyRange(MatrixWorkspace_sptr& input, const int& startBin, const double& factor) + { + auto multiplyRange = this->createChildAlgorithm("MultiplyRange"); + multiplyRange->setProperty("InputWorkspace", input); + multiplyRange->setProperty("StartBin", startBin); + multiplyRange->setProperty("Factor", factor); + multiplyRange->execute(); + MatrixWorkspace_sptr outWS = multiplyRange->getProperty("OutputWorkspace"); + return outWS; + } + + MatrixWorkspace_sptr Stitch1D::weightedMean(MatrixWorkspace_sptr& inOne, MatrixWorkspace_sptr& inTwo) + { + auto weightedMean = this->createChildAlgorithm("WeightedMean"); + weightedMean->setProperty("InputWorkspace1", inOne); + weightedMean->setProperty("InputWorkspace2", inTwo); + weightedMean->execute(); + MatrixWorkspace_sptr outWS = weightedMean->getProperty("OutputWorkspace"); + return outWS; + } + + MatrixWorkspace_sptr Stitch1D::singleValueWS(double val) + { + auto singleValueWS = this->createChildAlgorithm("CreateSingleValuedWorkspace"); + singleValueWS->setProperty("DataValue", val); + singleValueWS->execute(); + MatrixWorkspace_sptr outWS = singleValueWS->getProperty("OutputWorkspace"); + return outWS; + } + + boost::tuple<int, int> Stitch1D::findStartEndIndexes(double startOverlap, double endOverlap, MatrixWorkspace_sptr& workspace) + { + int a1 = static_cast<int>(workspace->binIndexOf(startOverlap)); + int a2 = static_cast<int>(workspace->binIndexOf(endOverlap)); + if (a1 == a2) + { + throw std::runtime_error("The Params you have provided for binning yield a workspace in which start and end overlap appear in the same bin. Make binning finer via input Params."); + } + return boost::tuple<int,int>(a1,a2); + + } + + bool Stitch1D::hasNonzeroErrors(MatrixWorkspace_sptr& ws) const + { + size_t ws_size = ws->getNumberHistograms(); + for (size_t i = 0; i < ws_size; ++i) + { + auto e = ws->readE(i); + std::vector<double, std::allocator<double> >::iterator error = std::find_if(e.begin(), e.end(), isNonzero); + if (error != e.end()) + { + return true; + } + } + return false; + } + //---------------------------------------------------------------------------------------------- /** Execute the algorithm. */ @@ -236,7 +310,7 @@ namespace Mantid { MatrixWorkspace_sptr rhsWS = this->getProperty("RHSWorkspace"); MatrixWorkspace_sptr lhsWS = this->getProperty("LHSWorkspace"); - const MinMaxTuple intesectionXRegion = calculateXIntersection(rhsWS, lhsWS); + const MinMaxTuple intesectionXRegion = calculateXIntersection(lhsWS, rhsWS); const double intersectionMin = intesectionXRegion.get<0>(); const double intersectionMax = intesectionXRegion.get<1>(); @@ -283,6 +357,10 @@ namespace Mantid auto rebinnedLHS = rebin(lhsWS, params); auto rebinnedRHS = rebin(rhsWS, params); + boost::tuple<int,int> startEnd = findStartEndIndexes(startOverlap, endOverlap, rebinnedLHS); + + //manualscalefactor if + auto rhsOverlapIntegrated = integration(rebinnedRHS, startOverlap, endOverlap); auto lhsOverlapIntegrated = integration(rebinnedLHS, startOverlap, endOverlap); @@ -302,7 +380,43 @@ namespace Mantid scaleFactor = y2[0]/y1[0]; } - setProperty("OutputWorkspace", rhsWS); + //manualscalefactor end if + + int a1 = boost::tuples::get<0>(startEnd); + int a2 = boost::tuples::get<1>(startEnd); + + // Mask out everything BUT the overlap region as a new workspace. + MatrixWorkspace_sptr overlap1 = multiplyRange(rebinnedLHS,0,a1,0); + overlap1 = multiplyRange(overlap1,a2,0); + + // Mask out everything BUT the overlap region as a new workspace. + MatrixWorkspace_sptr overlap2 = multiplyRange(rebinnedRHS,0,a1,0); + overlap2 = multiplyRange(overlap2,a2,0); + + // Mask out everything AFTER the start of the overlap region + rebinnedLHS = multiplyRange(rebinnedLHS,a1 + 1,0); + + // Mask out everything BEFORE the end of the overlap region + rebinnedRHS = multiplyRange(rebinnedRHS,0,a2-1,0); + + // Calculate a weighted mean for the overlap region + + MatrixWorkspace_sptr overlapave; + if (hasNonzeroErrors(overlap1) && hasNonzeroErrors(overlap2)) + { + overlapave = weightedMean(overlap1, overlap2); + } + else + { + g_log.information("Using un-weighted mean for Stitch1D overlap mean"); + MatrixWorkspace_sptr sum = overlap1 + overlap2; + MatrixWorkspace_sptr denominator = singleValueWS(2.0); + overlapave = sum / denominator; + } + + MatrixWorkspace_sptr result = rebinnedLHS + overlapave + rebinnedRHS; + + setProperty("OutputWorkspace", result); setProperty("OutScaleFactor", scaleFactor); } diff --git a/Code/Mantid/Framework/Algorithms/test/Stitch1DTest.h b/Code/Mantid/Framework/Algorithms/test/Stitch1DTest.h index 418735d753b..1f8aba562cf 100644 --- a/Code/Mantid/Framework/Algorithms/test/Stitch1DTest.h +++ b/Code/Mantid/Framework/Algorithms/test/Stitch1DTest.h @@ -57,6 +57,21 @@ private: return outWS; } + MatrixWorkspace_sptr create1DWorkspace(MantidVec& xData, MantidVec& yData) + { + auto createWorkspace = AlgorithmManager::Instance().create("CreateWorkspace"); + createWorkspace->setChild(true); + createWorkspace->initialize(); + createWorkspace->setProperty("UnitX", "1/q"); + createWorkspace->setProperty("DataX", xData); + createWorkspace->setProperty("DataY", yData); + createWorkspace->setProperty("NSpec", 1); + createWorkspace->setPropertyValue("OutputWorkspace", "dummy"); + createWorkspace->execute(); + MatrixWorkspace_sptr outWS = createWorkspace->getProperty("OutputWorkspace"); + return outWS; + } + MatrixWorkspace_sptr a; MatrixWorkspace_sptr b; MantidVec x; @@ -154,6 +169,22 @@ public: return ResultType(stitched, scaleFactor); } + ResultType do_stitch1D(MatrixWorkspace_sptr& lhs, MatrixWorkspace_sptr& rhs, const MantidVec& params) + { + Stitch1D alg; + alg.setChild(true); + alg.setRethrows(true); + alg.initialize(); + alg.setProperty("LHSWorkspace", lhs); + alg.setProperty("RHSWorkspace", rhs); + alg.setProperty("Params", params); + alg.setPropertyValue("OutputWorkspace", "dummy_value"); + alg.execute(); + MatrixWorkspace_sptr stitched = alg.getProperty("OutputWorkspace"); + double scaleFactor = alg.getProperty("OutScaleFactor"); + return ResultType(stitched, scaleFactor); + } + void test_Init() { Stitch1D alg; @@ -172,7 +203,7 @@ public: { auto lhs_ws = make_arbitrary_point_ws(); auto rhs_ws = make_arbitrary_histogram_ws(); - TSM_ASSERT_THROWS("LHS WS must be histogram", do_stitch1D(lhs_ws, rhs_ws, -1, 1, MantidVec(0.2)), + TSM_ASSERT_THROWS("LHS WS must be histogram", do_stitch1D(lhs_ws, rhs_ws, -1, 1, MantidVec(1, 0.2)), std::invalid_argument&); } @@ -180,7 +211,7 @@ public: { auto lhs_ws = make_arbitrary_histogram_ws(); auto rhs_ws = make_arbitrary_point_ws(); - TSM_ASSERT_THROWS("RHS WS must be histogram", do_stitch1D(lhs_ws, rhs_ws, -1, 1, MantidVec(0.2)), + TSM_ASSERT_THROWS("RHS WS must be histogram", do_stitch1D(lhs_ws, rhs_ws, -1, 1, MantidVec(1, 0.2)), std::invalid_argument&); } @@ -198,6 +229,52 @@ public: TS_ASSERT_EQUALS(xMax, 1.0); } + void test_stitching_determines_params() + { + MantidVec x1 = boost::assign::list_of(-1.0)(-0.8)(-0.6)(-0.4)(-0.2)(0.0)(0.2)(0.4)(0.6)(0.8).convert_to_container<MantidVec>(); + MantidVec x2 = boost::assign::list_of(0.4)(0.6)(0.8)(1.0)(1.2)(1.4)(1.6).convert_to_container<MantidVec>(); + + MatrixWorkspace_sptr ws1 = create1DWorkspace(x1, boost::assign::list_of(1)(1)(1)(1)(1)(1)(1)(1)(1).convert_to_container<MantidVec>()); + MatrixWorkspace_sptr ws2 = create1DWorkspace(x2, boost::assign::list_of(1)(1)(1)(1)(1)(1).convert_to_container<MantidVec>()); + double demanded_step_size = 0.2; + auto ret = do_stitch1D(ws1,ws2,0.4,1.0,boost::assign::list_of(demanded_step_size).convert_to_container<MantidVec>()); + + //Check the ranges on the output workspace against the param inputs. + MantidVec out_x_values = ret.get<0>()->readX(0); + double x_min = *std::min_element(out_x_values.begin(), out_x_values.end()); + double x_max = *std::max_element(out_x_values.begin(), out_x_values.end()); + double step_size = out_x_values[1] - out_x_values[0]; + + TS_ASSERT_EQUALS(x_min, -1); + TS_ASSERT_DELTA(x_max - demanded_step_size, 1.4, 0.000001); + TS_ASSERT_DELTA(step_size, demanded_step_size, 0.000001); + } + + void test_stitching_determines_start_and_end_overlap() + { + MantidVec x1 = boost::assign::list_of(-1.0)(-0.8)(-0.6)(-0.4)(-0.2)(0.0)(0.2)(0.4).convert_to_container<MantidVec>(); + MantidVec x2 = boost::assign::list_of(-0.4)(-0.2)(0.0)(0.2)(0.4)(0.6)(0.8)(1.0).convert_to_container<MantidVec>(); + MatrixWorkspace_sptr ws1 = create1DWorkspace(x1, boost::assign::list_of(1)(1)(1)(3)(3)(3)(3).convert_to_container<MantidVec>()); + MatrixWorkspace_sptr ws2 = create1DWorkspace(x2, boost::assign::list_of(1)(1)(1)(1)(3)(3)(3).convert_to_container<MantidVec>()); + + auto ret = do_stitch1D(ws1,ws2,boost::assign::list_of(-1.0)(0.2)(1.0).convert_to_container<MantidVec>()); + + MantidVec stitched_y = ret.get<0>()->readY(0); + MantidVec stitched_x = ret.get<0>()->readX(0); + std::vector<size_t> overlap_indexes = std::vector<size_t>(); + for (size_t itr = 0; itr < stitched_y.size(); ++itr) + { + if (stitched_y[itr] >= 1.0009 && stitched_y[itr] <= 3.0001) + { + overlap_indexes.push_back(itr); + } + } + + double start_overlap_determined = stitched_x[overlap_indexes[0]]; + double end_overlap_determined = stitched_x[overlap_indexes[overlap_indexes.size()-1]]; + TS_ASSERT_DELTA(start_overlap_determined, -0.4, 0.000000001); + TS_ASSERT_DELTA(end_overlap_determined, 0.2, 0.000000001); + } }; #endif /* MANTID_ALGORITHMS_STITCH1DTEST_H_ */ -- GitLab