diff --git a/Framework/Algorithms/inc/MantidAlgorithms/SumSpectra.h b/Framework/Algorithms/inc/MantidAlgorithms/SumSpectra.h index d7ba859a70662289c0438ffcadcdac411614630a..51185412ebbe7b9fe0a275a9d112799eb7a5d3bf 100644 --- a/Framework/Algorithms/inc/MantidAlgorithms/SumSpectra.h +++ b/Framework/Algorithms/inc/MantidAlgorithms/SumSpectra.h @@ -76,7 +76,7 @@ private: size_t &numZeros); specnum_t getOutputSpecNo(API::MatrixWorkspace_const_sptr localworkspace); - API::MatrixWorkspace_sptr replaceSpecialValues(bool forceCopy = false); + API::MatrixWorkspace_sptr replaceSpecialValues(); void determineIndices(const size_t numberOfSpectra); /// The output spectrum number diff --git a/Framework/Algorithms/src/Rebin2D.cpp b/Framework/Algorithms/src/Rebin2D.cpp index 238011d280c8eab533a21fbcec3b9afa62b1278e..8301c3292612451ade37a55d912988c65bc9c984 100644 --- a/Framework/Algorithms/src/Rebin2D.cpp +++ b/Framework/Algorithms/src/Rebin2D.cpp @@ -155,6 +155,7 @@ void Rebin2D::exec() { } PARALLEL_CHECK_INTERUPT_REGION if (useFractionalArea) { + FractionalRebinning::finalizeFractionalRebin(*outputRB); outputRB->finalize(true); } diff --git a/Framework/Algorithms/src/SofQWNormalisedPolygon.cpp b/Framework/Algorithms/src/SofQWNormalisedPolygon.cpp index b583f653dce63e0b78c8c48f3de8f712b54f2ba0..98157f314023c2171f9cbc9c5af79e6d62d5e2bd 100644 --- a/Framework/Algorithms/src/SofQWNormalisedPolygon.cpp +++ b/Framework/Algorithms/src/SofQWNormalisedPolygon.cpp @@ -474,6 +474,7 @@ void SofQWNormalisedPolygon::exec() { } PARALLEL_CHECK_INTERUPT_REGION + FractionalRebinning::finalizeFractionalRebin(*outputWS); outputWS->finalize(); FractionalRebinning::normaliseOutput(outputWS, inputWS, m_progress.get()); diff --git a/Framework/Algorithms/src/SumSpectra.cpp b/Framework/Algorithms/src/SumSpectra.cpp index c454fefc134e2544da47d6e1552faa583509f0a4..f34877d08084286efb4a73ec81865d960395cab6 100644 --- a/Framework/Algorithms/src/SumSpectra.cpp +++ b/Framework/Algorithms/src/SumSpectra.cpp @@ -159,16 +159,16 @@ void SumSpectra::init() { "If enabled floating point special values such as NaN or Inf" " are removed before the spectra are summed."); - declareProperty("UseFractionalArea", true, - "Normalize the output workspace to the fractional area for " - "RebinnedOutput workspaces."); - declareProperty("MultiplyBySpectra", true, "For unnormalized data one should multiply the weighted sum " "by the number of spectra contributing to the bin."); setPropertySettings( "MultiplyBySpectra", std::make_unique<EnabledWhenProperty>("WeightedSum", IS_EQUAL_TO, "1")); + + declareProperty("UseFractionalArea", true, + "Normalize the output workspace to the fractional area for " + "RebinnedOutput workspaces."); } /* @@ -349,13 +349,13 @@ SumSpectra::getOutputSpecNo(MatrixWorkspace_const_sptr localworkspace) { * such as NaN or Inf to 0. * @return The workspace with special floating point values set to 0 */ -API::MatrixWorkspace_sptr SumSpectra::replaceSpecialValues(bool forceCopy) { +API::MatrixWorkspace_sptr SumSpectra::replaceSpecialValues() { // Get a copy of the input workspace MatrixWorkspace_sptr wksp = getProperty("InputWorkspace"); if (!m_replaceSpecialValues) { - // Skip any additional processing but create copy if needed - return (forceCopy ? wksp->clone() : wksp); + // Skip any additional processing + return wksp; } IAlgorithm_sptr alg = createChildAlgorithm("ReplaceSpecialValues"); @@ -516,7 +516,7 @@ void SumSpectra::doFractionalSum(MatrixWorkspace_sptr outputWorkspace, // First, we need to clean the input workspace for nan's and inf's in order // to treat the data correctly later. This will create a new private // workspace that will be retrieved as mutable. - auto localworkspace = replaceSpecialValues(true); + auto localworkspace = replaceSpecialValues(); // Transform to real workspace types RebinnedOutput_sptr inWS = @@ -524,8 +524,9 @@ void SumSpectra::doFractionalSum(MatrixWorkspace_sptr outputWorkspace, RebinnedOutput_sptr outWS = boost::dynamic_pointer_cast<RebinnedOutput>(outputWorkspace); - // Unfinalize the workspace prior to the sum process - inWS->unfinalize(); + // Check finalize state prior to the sum process, at the completion + // the output is unfinalized + auto isFinalized = inWS->isFinalized(); // Get references to the output workspaces's data vectors auto &outSpec = outputWorkspace->getSpectrum(0); @@ -555,19 +556,22 @@ void SumSpectra::doFractionalSum(MatrixWorkspace_sptr outputWorkspace, if (m_calculateWeightedSum) { for (size_t yIndex = 0; yIndex < m_yLength; ++yIndex) { const double yErrorsVal = YErrors[yIndex]; + const double fracVal = (isFinalized ? FracArea[yIndex] : 1.0); if (std::isnormal(yErrorsVal)) { // is non-zero, nan, or infinity - const double errsq = yErrorsVal * yErrorsVal; + const double errsq = yErrorsVal * yErrorsVal * fracVal * fracVal; YErrorSum[yIndex] += errsq; Weight[yIndex] += 1. / errsq; - YSum[yIndex] += YValues[yIndex] / errsq; + YSum[yIndex] += YValues[yIndex] * fracVal / errsq; } else { nZeros[yIndex]++; } } } else { for (size_t yIndex = 0; yIndex < m_yLength; ++yIndex) { - YSum[yIndex] += YValues[yIndex]; - YErrorSum[yIndex] += YErrors[yIndex] * YErrors[yIndex]; + const double fracVal = (isFinalized ? FracArea[yIndex] : 1.0); + YSum[yIndex] += YValues[yIndex] * fracVal; + YErrorSum[yIndex] += + YErrors[yIndex] * YErrors[yIndex] * fracVal * fracVal; } } // accumulation of fractional weight is the same diff --git a/Framework/Algorithms/test/SumSpectraTest.h b/Framework/Algorithms/test/SumSpectraTest.h index 9b788614fb39d0b4a404da52ca29c360f67f5308..4f6b59606eb21cdea1cc6e2410d79552b32f68fa 100644 --- a/Framework/Algorithms/test/SumSpectraTest.h +++ b/Framework/Algorithms/test/SumSpectraTest.h @@ -342,28 +342,52 @@ public: RebinnedOutput_sptr output; output = AnalysisDataService::Instance().retrieveWS<RebinnedOutput>(outName); - TS_ASSERT(output); - TS_ASSERT_EQUALS(output->getNumberHistograms(), 1); - TS_ASSERT_EQUALS(output->blocksize(), 6); - // Row with full acceptance - TS_ASSERT_EQUALS(output->y(0)[1], 1.); - TS_ASSERT_DELTA(output->e(0)[1], 0.40824829046386296, 1.e-5); - TS_ASSERT_EQUALS(output->dataF(0)[1], 6.); - // Row with limited, but non-zero acceptance, shouldn't have nans! - TS_ASSERT_DELTA(output->y(0)[5], 0.66666, 1.e-5); - TS_ASSERT_DELTA(output->e(0)[5], 0.47140452079103173, 1.e-5); - TS_ASSERT_EQUALS(output->dataF(0)[5], 3.); - TS_ASSERT(output->run().hasProperty("NumAllSpectra")) - TS_ASSERT(output->run().hasProperty("NumMaskSpectra")) - TS_ASSERT(output->run().hasProperty("NumZeroSpectra")) - - TS_ASSERT_EQUALS(boost::lexical_cast<std::string>(nHist), - output->run().getLogData("NumAllSpectra")->value()) - TS_ASSERT_EQUALS(boost::lexical_cast<std::string>(0), - output->run().getLogData("NumMaskSpectra")->value()) - TS_ASSERT_EQUALS(boost::lexical_cast<std::string>(0), - output->run().getLogData("NumZeroSpectra")->value()) + auto evaluate = [&, nHist](RebinnedOutput_sptr &output) { + TS_ASSERT(output); + TS_ASSERT_EQUALS(output->getNumberHistograms(), 1); + TS_ASSERT_EQUALS(output->blocksize(), 6); + // Row with full acceptance + TS_ASSERT_EQUALS(output->y(0)[1], 1.); + TS_ASSERT_DELTA(output->e(0)[1], 0.40824829046386296, 1.e-5); + TS_ASSERT_EQUALS(output->dataF(0)[1], 6.); + // Row with limited, but non-zero acceptance, shouldn't have nans! + TS_ASSERT_DELTA(output->y(0)[5], 0.66666, 1.e-5); + TS_ASSERT_DELTA(output->e(0)[5], 0.47140452079103173, 1.e-5); + TS_ASSERT_EQUALS(output->dataF(0)[5], 3.); + + TS_ASSERT(output->run().hasProperty("NumAllSpectra")) + TS_ASSERT(output->run().hasProperty("NumMaskSpectra")) + TS_ASSERT(output->run().hasProperty("NumZeroSpectra")) + + TS_ASSERT_EQUALS(boost::lexical_cast<std::string>(nHist), + output->run().getLogData("NumAllSpectra")->value()) + TS_ASSERT_EQUALS(boost::lexical_cast<std::string>(0), + output->run().getLogData("NumMaskSpectra")->value()) + TS_ASSERT_EQUALS(boost::lexical_cast<std::string>(0), + output->run().getLogData("NumZeroSpectra")->value()) + }; + + evaluate(output); + + // unfinalize the workspace and confirm it gives the same results + // using a clean algorithm + ws->unfinalize(); + AnalysisDataService::Instance().addOrReplace(inName, ws); + Mantid::Algorithms::SumSpectra alg3a; + if (!alg3a.isInitialized()) { + alg3a.initialize(); + } + // Set the properties + alg3a.setPropertyValue("InputWorkspace", inName); + alg3a.setPropertyValue("OutputWorkspace", outName); + alg3a.setProperty("IncludeMonitors", false); + alg3a.setProperty("RemoveSpecialValues", true); + alg3a.execute(); + TS_ASSERT(alg3a.isExecuted()); + output = + AnalysisDataService::Instance().retrieveWS<RebinnedOutput>(outName); + evaluate(output); } void testExecNoLimitsWeighted() { Mantid::Algorithms::SumSpectra alg2; diff --git a/Framework/DataObjects/inc/MantidDataObjects/FractionalRebinning.h b/Framework/DataObjects/inc/MantidDataObjects/FractionalRebinning.h index eaa08f04d077365c80a85291dce65708ec6c755f..6bf685879efb01964daafd16d8628848d658894f 100644 --- a/Framework/DataObjects/inc/MantidDataObjects/FractionalRebinning.h +++ b/Framework/DataObjects/inc/MantidDataObjects/FractionalRebinning.h @@ -62,6 +62,10 @@ MANTID_DATAOBJECTS_DLL void rebinToFractionalOutput( const std::vector<double> &verticalAxis, const DataObjects::RebinnedOutput_const_sptr &inputRB = nullptr); +/// Set finalize flag after fractional rebinning loop +MANTID_DATAOBJECTS_DLL void +finalizeFractionalRebin(DataObjects::RebinnedOutput &outputWS); + } // namespace FractionalRebinning } // namespace DataObjects diff --git a/Framework/DataObjects/src/FractionalRebinning.cpp b/Framework/DataObjects/src/FractionalRebinning.cpp index d1157b045e56ea3655e77484de2ae08d3bcd716a..3064644bf89025447f3f597f81f79af207f2ed01 100644 --- a/Framework/DataObjects/src/FractionalRebinning.cpp +++ b/Framework/DataObjects/src/FractionalRebinning.cpp @@ -685,6 +685,16 @@ void rebinToFractionalOutput(const Quadrilateral &inputQ, } } +/** + * Called at the completion of the fractional rebinning loop + * to the set the finalize flag in the output workspace. + * @param outputWS Reference to the rebinned output workspace + */ +void finalizeFractionalRebin(RebinnedOutput &outputWS) { + // rebinToFractionalOutput() leaves the data in an unfinalized state + outputWS.setFinalized(false); +} + } // namespace FractionalRebinning } // namespace DataObjects diff --git a/Framework/DataObjects/src/ReflectometryTransform.cpp b/Framework/DataObjects/src/ReflectometryTransform.cpp index a3231deedb7a1e9f798e555afd6e4eed80886e51..b0a1dd48628308d68db34cff3a4baa6784e52825 100644 --- a/Framework/DataObjects/src/ReflectometryTransform.cpp +++ b/Framework/DataObjects/src/ReflectometryTransform.cpp @@ -513,6 +513,7 @@ MatrixWorkspace_sptr ReflectometryTransform::executeNormPoly( } } } + FractionalRebinning::finalizeFractionalRebin(*outWS); outWS->finalize(); FractionalRebinning::normaliseOutput(outWS, inputWS); // Set the output spectrum-detector mapping