From 7f5d87212f8baaedf134c648f50fff8434fd9702 Mon Sep 17 00:00:00 2001 From: Owen Arnold <owen.arnold@stfc.ac.uk> Date: Wed, 6 Aug 2014 08:54:51 +0100 Subject: [PATCH] refs #9955. Document and format. --- .../Framework/Algorithms/src/Stitch1D.cpp | 1017 +++++++++-------- .../docs/source/algorithms/Stitch1D-v3.rst | 10 + 2 files changed, 521 insertions(+), 506 deletions(-) diff --git a/Code/Mantid/Framework/Algorithms/src/Stitch1D.cpp b/Code/Mantid/Framework/Algorithms/src/Stitch1D.cpp index 98d5c433d2d..ba4f981b367 100644 --- a/Code/Mantid/Framework/Algorithms/src/Stitch1D.cpp +++ b/Code/Mantid/Framework/Algorithms/src/Stitch1D.cpp @@ -95,577 +95,582 @@ namespace Mantid std::copy(sourceY.begin() + a1 + 1, sourceY.begin() + a2, newY.begin() + a1 + 1); std::copy(sourceE.begin() + a1 + 1, sourceE.begin() + a2, newE.begin() + a1 + 1); - PARALLEL_END_INTERUPT_REGION + PARALLEL_END_INTERUPT_REGION + } + PARALLEL_CHECK_INTERUPT_REGION + return product; } - PARALLEL_CHECK_INTERUPT_REGION - return product; - } - /** - * Mask out data in the region between a1 and a2 with zeros. Operation performed on the original workspace - * @param a1 : start position in X - * @param a2 : end position in X - * @param source : Workspace to mask. - */ - void Stitch1D::maskInPlace(int a1, int a2, MatrixWorkspace_sptr source) - { - MatrixWorkspace_sptr product = WorkspaceFactory::Instance().create(source); - const int histogramCount = static_cast<int>(source->getNumberHistograms()); - PARALLEL_FOR2(source,product) - for (int i = 0; i < histogramCount; ++i) + /** + * Mask out data in the region between a1 and a2 with zeros. Operation performed on the original workspace + * @param a1 : start position in X + * @param a2 : end position in X + * @param source : Workspace to mask. + */ + void Stitch1D::maskInPlace(int a1, int a2, MatrixWorkspace_sptr source) { - PARALLEL_START_INTERUPT_REGION - // Copy over the data - MantidVec& sourceY = source->dataY(i); - MantidVec& sourceE = source->dataE(i); - - for (int i = a1; i < a2; ++i) + MatrixWorkspace_sptr product = WorkspaceFactory::Instance().create(source); + const int histogramCount = static_cast<int>(source->getNumberHistograms()); + PARALLEL_FOR2(source,product) + for (int i = 0; i < histogramCount; ++i) { - sourceY[i] = 0; - sourceE[i] = 0; - } + PARALLEL_START_INTERUPT_REGION + // Copy over the data + MantidVec& sourceY = source->dataY(i); + MantidVec& sourceE = source->dataE(i); - PARALLEL_END_INTERUPT_REGION - } -PARALLEL_CHECK_INTERUPT_REGION -} + for (int i = a1; i < a2; ++i) + { + sourceY[i] = 0; + sourceE[i] = 0; + } + + PARALLEL_END_INTERUPT_REGION + } + PARALLEL_CHECK_INTERUPT_REGION + } //---------------------------------------------------------------------------------------------- -/** Initialize the algorithm's properties. - */ -void Stitch1D::init() -{ -Kernel::IValidator_sptr histogramValidator = boost::make_shared<HistogramValidator>(); - -declareProperty( - new WorkspaceProperty<MatrixWorkspace>("LHSWorkspace", "", Direction::Input, - histogramValidator->clone()), "LHS input workspace."); -declareProperty( - new WorkspaceProperty<MatrixWorkspace>("RHSWorkspace", "", Direction::Input, - histogramValidator->clone()), "RHS input workspace."); -declareProperty(new WorkspaceProperty<MatrixWorkspace>("OutputWorkspace", "", Direction::Output), - "Output stitched workspace."); -declareProperty(new PropertyWithValue<double>("StartOverlap", Mantid::EMPTY_DBL(), Direction::Input), - "Start overlap x-value in units of x-axis. Optional."); -declareProperty(new PropertyWithValue<double>("EndOverlap", Mantid::EMPTY_DBL(), Direction::Input), - "End overlap x-value in units of x-axis. Optional."); -declareProperty(new ArrayProperty<double>("Params", boost::make_shared<RebinParamsValidator>(true)), - "Rebinning Parameters. See Rebin for format. If only a single value is provided, start and end are taken from input workspaces."); -declareProperty(new PropertyWithValue<bool>("ScaleRHSWorkspace", true, Direction::Input), - "Scaling either with respect to workspace 1 or workspace 2"); -declareProperty(new PropertyWithValue<bool>("UseManualScaleFactor", false, Direction::Input), - "True to use a provided value for the scale factor."); -auto manualScaleFactorValidator = boost::make_shared<BoundedValidator<double> >(); -manualScaleFactorValidator->setLower(0); -manualScaleFactorValidator->setExclusive(true); -declareProperty( - new PropertyWithValue<double>("ManualScaleFactor", 1.0, manualScaleFactorValidator, - Direction::Input), "Provided value for the scale factor. Optional."); -declareProperty(new PropertyWithValue<double>("OutScaleFactor", Mantid::EMPTY_DBL(), Direction::Output), - "The actual used value for the scaling factor."); -} + /** Initialize the algorithm's properties. + */ + void Stitch1D::init() + { + Kernel::IValidator_sptr histogramValidator = boost::make_shared<HistogramValidator>(); + + declareProperty( + new WorkspaceProperty<MatrixWorkspace>("LHSWorkspace", "", Direction::Input, + histogramValidator->clone()), "LHS input workspace."); + declareProperty( + new WorkspaceProperty<MatrixWorkspace>("RHSWorkspace", "", Direction::Input, + histogramValidator->clone()), "RHS input workspace."); + declareProperty(new WorkspaceProperty<MatrixWorkspace>("OutputWorkspace", "", Direction::Output), + "Output stitched workspace."); + declareProperty( + new PropertyWithValue<double>("StartOverlap", Mantid::EMPTY_DBL(), Direction::Input), + "Start overlap x-value in units of x-axis. Optional."); + declareProperty(new PropertyWithValue<double>("EndOverlap", Mantid::EMPTY_DBL(), Direction::Input), + "End overlap x-value in units of x-axis. Optional."); + declareProperty( + new ArrayProperty<double>("Params", boost::make_shared<RebinParamsValidator>(true)), + "Rebinning Parameters. See Rebin for format. If only a single value is provided, start and end are taken from input workspaces."); + declareProperty(new PropertyWithValue<bool>("ScaleRHSWorkspace", true, Direction::Input), + "Scaling either with respect to workspace 1 or workspace 2"); + declareProperty(new PropertyWithValue<bool>("UseManualScaleFactor", false, Direction::Input), + "True to use a provided value for the scale factor."); + auto manualScaleFactorValidator = boost::make_shared<BoundedValidator<double> >(); + manualScaleFactorValidator->setLower(0); + manualScaleFactorValidator->setExclusive(true); + declareProperty( + new PropertyWithValue<double>("ManualScaleFactor", 1.0, manualScaleFactorValidator, + Direction::Input), "Provided value for the scale factor. Optional."); + declareProperty( + new PropertyWithValue<double>("OutScaleFactor", Mantid::EMPTY_DBL(), Direction::Output), + "The actual used value for the scaling factor."); + } -/**Gets the start of the overlapping region - @param intesectionMin :: The minimum possible value for the overlapping region to inhabit - @param intesectionMax :: The maximum possible value for the overlapping region to inhabit - @return a double contianing the start of the overlapping region - */ -double Stitch1D::getStartOverlap(const double& intesectionMin, const double& intesectionMax) const -{ -Property* startOverlapProp = this->getProperty("StartOverlap"); -double startOverlapVal = this->getProperty("StartOverlap"); -startOverlapVal -= this->range_tolerance; -const bool startOverlapBeyondRange = (startOverlapVal < intesectionMin) - || (startOverlapVal > intesectionMax); -if (startOverlapProp->isDefault() || startOverlapBeyondRange) -{ - if (!startOverlapProp->isDefault() && startOverlapBeyondRange) - { - char message[200]; - std::sprintf(message, - "StartOverlap is outside range at %0.4f, Min is %0.4f, Max is %0.4f . Forced to be: %0.4f", - startOverlapVal, intesectionMin, intesectionMax, intesectionMin); - g_log.warning(std::string(message)); - } - startOverlapVal = intesectionMin; - std::stringstream buffer; - buffer << "StartOverlap calculated to be: " << startOverlapVal; - g_log.information(buffer.str()); -} -return startOverlapVal; -} + /**Gets the start of the overlapping region + @param intesectionMin :: The minimum possible value for the overlapping region to inhabit + @param intesectionMax :: The maximum possible value for the overlapping region to inhabit + @return a double contianing the start of the overlapping region + */ + double Stitch1D::getStartOverlap(const double& intesectionMin, const double& intesectionMax) const + { + Property* startOverlapProp = this->getProperty("StartOverlap"); + double startOverlapVal = this->getProperty("StartOverlap"); + startOverlapVal -= this->range_tolerance; + const bool startOverlapBeyondRange = (startOverlapVal < intesectionMin) + || (startOverlapVal > intesectionMax); + if (startOverlapProp->isDefault() || startOverlapBeyondRange) + { + if (!startOverlapProp->isDefault() && startOverlapBeyondRange) + { + char message[200]; + std::sprintf(message, + "StartOverlap is outside range at %0.4f, Min is %0.4f, Max is %0.4f . Forced to be: %0.4f", + startOverlapVal, intesectionMin, intesectionMax, intesectionMin); + g_log.warning(std::string(message)); + } + startOverlapVal = intesectionMin; + std::stringstream buffer; + buffer << "StartOverlap calculated to be: " << startOverlapVal; + g_log.information(buffer.str()); + } + return startOverlapVal; + } -/**Gets the end of the overlapping region - @param intesectionMin :: The minimum possible value for the overlapping region to inhabit - @param intesectionMax :: The maximum possible value for the overlapping region to inhabit - @return a double contianing the end of the overlapping region - */ -double Stitch1D::getEndOverlap(const double& intesectionMin, const double& intesectionMax) const -{ -Property* endOverlapProp = this->getProperty("EndOverlap"); -double endOverlapVal = this->getProperty("EndOverlap"); -endOverlapVal += this->range_tolerance; -const bool endOverlapBeyondRange = (endOverlapVal < intesectionMin) || (endOverlapVal > intesectionMax); -if (endOverlapProp->isDefault() || endOverlapBeyondRange) -{ - if (!endOverlapProp->isDefault() && endOverlapBeyondRange) - { - char message[200]; - std::sprintf(message, - "EndOverlap is outside range at %0.4f, Min is %0.4f, Max is %0.4f . Forced to be: %0.4f", - endOverlapVal, intesectionMin, intesectionMax, intesectionMax); - g_log.warning(std::string(message)); - } - endOverlapVal = intesectionMax; - std::stringstream buffer; - buffer << "EndOverlap calculated to be: " << endOverlapVal; - g_log.information(buffer.str()); -} -return endOverlapVal; -} + /**Gets the end of the overlapping region + @param intesectionMin :: The minimum possible value for the overlapping region to inhabit + @param intesectionMax :: The maximum possible value for the overlapping region to inhabit + @return a double contianing the end of the overlapping region + */ + double Stitch1D::getEndOverlap(const double& intesectionMin, const double& intesectionMax) const + { + Property* endOverlapProp = this->getProperty("EndOverlap"); + double endOverlapVal = this->getProperty("EndOverlap"); + endOverlapVal += this->range_tolerance; + const bool endOverlapBeyondRange = (endOverlapVal < intesectionMin) + || (endOverlapVal > intesectionMax); + if (endOverlapProp->isDefault() || endOverlapBeyondRange) + { + if (!endOverlapProp->isDefault() && endOverlapBeyondRange) + { + char message[200]; + std::sprintf(message, + "EndOverlap is outside range at %0.4f, Min is %0.4f, Max is %0.4f . Forced to be: %0.4f", + endOverlapVal, intesectionMin, intesectionMax, intesectionMax); + g_log.warning(std::string(message)); + } + endOverlapVal = intesectionMax; + std::stringstream buffer; + buffer << "EndOverlap calculated to be: " << endOverlapVal; + g_log.information(buffer.str()); + } + return endOverlapVal; + } -/**Gets the rebinning parameters and calculates any missing values - @param lhsWS :: The left hand side input workspace - @param rhsWS :: The right hand side input workspace - @param scaleRHS :: Scale the right hand side workspace - @return a vector<double> contianing the rebinning parameters - */ -MantidVec Stitch1D::getRebinParams(MatrixWorkspace_sptr& lhsWS, MatrixWorkspace_sptr& rhsWS, - const bool scaleRHS) const -{ -MantidVec inputParams = this->getProperty("Params"); -Property* prop = this->getProperty("Params"); -const bool areParamsDefault = prop->isDefault(); + /**Gets the rebinning parameters and calculates any missing values + @param lhsWS :: The left hand side input workspace + @param rhsWS :: The right hand side input workspace + @param scaleRHS :: Scale the right hand side workspace + @return a vector<double> contianing the rebinning parameters + */ + MantidVec Stitch1D::getRebinParams(MatrixWorkspace_sptr& lhsWS, MatrixWorkspace_sptr& rhsWS, + const bool scaleRHS) const + { + MantidVec inputParams = this->getProperty("Params"); + Property* prop = this->getProperty("Params"); + const bool areParamsDefault = prop->isDefault(); -const MantidVec& lhsX = lhsWS->readX(0); -auto it = std::min_element(lhsX.begin(), lhsX.end()); -const double minLHSX = *it; + const MantidVec& lhsX = lhsWS->readX(0); + auto it = std::min_element(lhsX.begin(), lhsX.end()); + const double minLHSX = *it; -const MantidVec& rhsX = rhsWS->readX(0); -it = std::max_element(rhsX.begin(), rhsX.end()); -const double maxRHSX = *it; + const MantidVec& rhsX = rhsWS->readX(0); + it = std::max_element(rhsX.begin(), rhsX.end()); + const double maxRHSX = *it; -MantidVec result; -if (areParamsDefault) -{ - MantidVec calculatedParams; + MantidVec result; + if (areParamsDefault) + { + MantidVec calculatedParams; + + // Calculate the step size based on the existing step size of the LHS workspace. That way scale factors should be reasonably maintained. + double calculatedStep = 0; + if (scaleRHS) + { + // Calculate the step from the workspace that will not be scaled. The LHS workspace. + calculatedStep = lhsX[1] - lhsX[0]; + } + else + { + // Calculate the step from the workspace that will not be scaled. The RHS workspace. + calculatedStep = rhsX[1] - rhsX[0]; + } + + calculatedParams.push_back(minLHSX); + calculatedParams.push_back(calculatedStep); + calculatedParams.push_back(maxRHSX); + result = calculatedParams; + } + else + { + if (inputParams.size() == 1) + { + MantidVec calculatedParams; + calculatedParams.push_back(minLHSX); + calculatedParams.push_back(inputParams.front()); // Use the step supplied. + calculatedParams.push_back(maxRHSX); + result = calculatedParams; + } + else + { + result = inputParams; // user has provided params. Use those. + } + } + return result; + } - // Calculate the step size based on the existing step size of the LHS workspace. That way scale factors should be reasonably maintained. - double calculatedStep = 0; - if (scaleRHS) - { - // Calculate the step from the workspace that will not be scaled. The LHS workspace. - calculatedStep = lhsX[1] - lhsX[0]; - } - else - { - // Calculate the step from the workspace that will not be scaled. The RHS workspace. - calculatedStep = rhsX[1] - rhsX[0]; - } + /**Runs the Rebin Algorithm as a child + @param input :: The input workspace + @param params :: a vector<double> containing rebinning parameters + @return A shared pointer to the resulting MatrixWorkspace + */ + MatrixWorkspace_sptr Stitch1D::rebin(MatrixWorkspace_sptr& input, const MantidVec& params) + { + auto rebin = this->createChildAlgorithm("Rebin"); + rebin->setProperty("InputWorkspace", input); + rebin->setProperty("Params", params); + rebin->execute(); + MatrixWorkspace_sptr outWS = rebin->getProperty("OutputWorkspace"); - calculatedParams.push_back(minLHSX); - calculatedParams.push_back(calculatedStep); - calculatedParams.push_back(maxRHSX); - result = calculatedParams; -} -else -{ - if (inputParams.size() == 1) - { - MantidVec calculatedParams; - calculatedParams.push_back(minLHSX); - calculatedParams.push_back(inputParams.front()); // Use the step supplied. - calculatedParams.push_back(maxRHSX); - result = calculatedParams; - } - else - { - result = inputParams; // user has provided params. Use those. - } -} -return result; -} + const int histogramCount = static_cast<int>(outWS->getNumberHistograms()); -/**Runs the Rebin Algorithm as a child - @param input :: The input workspace - @param params :: a vector<double> containing rebinning parameters - @return A shared pointer to the resulting MatrixWorkspace - */ -MatrixWorkspace_sptr Stitch1D::rebin(MatrixWorkspace_sptr& input, const MantidVec& params) -{ -auto rebin = this->createChildAlgorithm("Rebin"); -rebin->setProperty("InputWorkspace", input); -rebin->setProperty("Params", params); -rebin->execute(); -MatrixWorkspace_sptr outWS = rebin->getProperty("OutputWorkspace"); + // Record special values and then mask them out as zeros. Special values are remembered and then replaced post processing. + PARALLEL_FOR1(outWS) + for (int i = 0; i < histogramCount; ++i) + { + PARALLEL_START_INTERUPT_REGION + std::vector<size_t>& nanYIndexes = m_nanYIndexes[i]; + std::vector<size_t>& nanEIndexes = m_nanEIndexes[i]; + std::vector<size_t>& infYIndexes = m_infYIndexes[i]; + std::vector<size_t>& infEIndexes = m_infEIndexes[i]; + // Copy over the data + MantidVec& sourceY = outWS->dataY(i); + MantidVec& sourceE = outWS->dataE(i); + + for (size_t j = 0; j < sourceY.size(); ++j) + { + const double& value = sourceY[j]; + const double& eValue = sourceE[j]; + if (isNan(value)) + { + nanYIndexes.push_back(j); + sourceY[j] = 0; + } + else if (isInf(value)) + { + infYIndexes.push_back(j); + sourceY[j] = 0; + } + + if (isNan(eValue)) + { + nanEIndexes.push_back(j); + sourceE[j] = 0; + } + else if (isInf(eValue)) + { + infEIndexes.push_back(j); + sourceE[j] = 0; + } + + } + PARALLEL_END_INTERUPT_REGION + } + PARALLEL_CHECK_INTERUPT_REGION -const int histogramCount = static_cast<int>(outWS->getNumberHistograms()); + return outWS; + } -// Record special values and then mask them out as zeros. -PARALLEL_FOR1(outWS) -for (int i = 0; i < histogramCount; ++i) -{ - PARALLEL_START_INTERUPT_REGION - std::vector<size_t>& nanYIndexes = m_nanYIndexes[i]; - std::vector<size_t>& nanEIndexes = m_nanEIndexes[i]; - std::vector<size_t>& infYIndexes = m_infYIndexes[i]; - std::vector<size_t>& infEIndexes = m_infEIndexes[i]; - // Copy over the data - MantidVec& sourceY = outWS->dataY(i); - MantidVec& sourceE = outWS->dataE(i); - - for (size_t j = 0; j < sourceY.size(); ++j) - { - const double& value = sourceY[j]; - const double& eValue = sourceE[j]; - if (isNan(value)) + /**Runs the Integration Algorithm as a child. + @param input :: The input workspace + @param start :: a double defining the start of the region to integrate + @param stop :: a double defining the end of the region to integrate + @return A shared pointer to the resulting MatrixWorkspace + */ + MatrixWorkspace_sptr Stitch1D::integration(MatrixWorkspace_sptr& input, const double& start, + const double& stop) { - nanYIndexes.push_back(j); - sourceY[j] = 0; + auto integration = this->createChildAlgorithm("Integration"); + integration->setProperty("InputWorkspace", input); + integration->setProperty("RangeLower", start); + integration->setProperty("RangeUpper", stop); + integration->execute(); + MatrixWorkspace_sptr outWS = integration->getProperty("OutputWorkspace"); + return outWS; } - else if (isInf(value)) + + /**Runs the MultiplyRange Algorithm as a child defining an end bin + @param input :: The input workspace + @param startBin :: The first bin int eh range to multiply + @param endBin :: The last bin in the range to multiply + @param factor :: The multiplication factor + @return A shared pointer to the resulting MatrixWorkspace + */ + MatrixWorkspace_sptr Stitch1D::multiplyRange(MatrixWorkspace_sptr& input, const int& startBin, + const int& endBin, const double& factor) { - infYIndexes.push_back(j); - sourceY[j] = 0; + 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; } - if(isNan(eValue)) + /**Runs the MultiplyRange Algorithm as a child + @param input :: The input workspace + @param startBin :: The first bin int eh range to multiply + @param factor :: The multiplication factor + @return A shared pointer to the resulting MatrixWorkspace + */ + MatrixWorkspace_sptr Stitch1D::multiplyRange(MatrixWorkspace_sptr& input, const int& startBin, + const double& factor) { - nanEIndexes.push_back(j); - sourceE[j] = 0; + 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; } - else if(isInf(eValue)) + + /**Runs the WeightedMean Algorithm as a child + @param inOne :: The first input workspace + @param inTwo :: The second input workspace + @return A shared pointer to the resulting MatrixWorkspace + */ + MatrixWorkspace_sptr Stitch1D::weightedMean(MatrixWorkspace_sptr& inOne, MatrixWorkspace_sptr& inTwo) { - infEIndexes.push_back(j); - sourceE[j] = 0; + auto weightedMean = this->createChildAlgorithm("WeightedMean"); + weightedMean->setProperty("InputWorkspace1", inOne); + weightedMean->setProperty("InputWorkspace2", inTwo); + weightedMean->execute(); + MatrixWorkspace_sptr outWS = weightedMean->getProperty("OutputWorkspace"); + return outWS; } - } - -PARALLEL_END_INTERUPT_REGION -} -PARALLEL_CHECK_INTERUPT_REGION - - -return outWS; -} - -/**Runs the Integration Algorithm as a child. - @param input :: The input workspace - @param start :: a double defining the start of the region to integrate - @param stop :: a double defining the end of the region to integrate - @return A shared pointer to the resulting MatrixWorkspace - */ -MatrixWorkspace_sptr Stitch1D::integration(MatrixWorkspace_sptr& input, const double& start, -const double& stop) -{ -auto integration = this->createChildAlgorithm("Integration"); -integration->setProperty("InputWorkspace", input); -integration->setProperty("RangeLower", start); -integration->setProperty("RangeUpper", stop); -integration->execute(); -MatrixWorkspace_sptr outWS = integration->getProperty("OutputWorkspace"); -return outWS; -} - -/**Runs the MultiplyRange Algorithm as a child defining an end bin - @param input :: The input workspace - @param startBin :: The first bin int eh range to multiply - @param endBin :: The last bin in the range to multiply - @param factor :: The multiplication factor - @return A shared pointer to the resulting MatrixWorkspace - */ -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; -} - -/**Runs the MultiplyRange Algorithm as a child - @param input :: The input workspace - @param startBin :: The first bin int eh range to multiply - @param factor :: The multiplication factor - @return A shared pointer to the resulting MatrixWorkspace - */ -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; -} - -/**Runs the WeightedMean Algorithm as a child - @param inOne :: The first input workspace - @param inTwo :: The second input workspace - @return A shared pointer to the resulting MatrixWorkspace - */ -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; -} - -/**Runs the CreateSingleValuedWorkspace Algorithm as a child - @param val :: The double to convert to a single value workspace - @return A shared pointer to the resulting MatrixWorkspace - */ -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; -} + /**Runs the CreateSingleValuedWorkspace Algorithm as a child + @param val :: The double to convert to a single value workspace + @return A shared pointer to the resulting MatrixWorkspace + */ + 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; + } -/**finds the bins containing the ends of the overlappign region - @param startOverlap :: The start of the overlapping region - @param endOverlap :: The end of the overlapping region - @param workspace :: The workspace to determine the overlaps inside - @return a boost::tuple<int,int> containing the bin indexes of the overlaps - */ -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); + /**finds the bins containing the ends of the overlappign region + @param startOverlap :: The start of the overlapping region + @param endOverlap :: The end of the overlapping region + @param workspace :: The workspace to determine the overlaps inside + @return a boost::tuple<int,int> containing the bin indexes of the overlaps + */ + 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); -} + } -/**Determines if a workspace has non zero errors - @param ws :: The input workspace - @return True if there are any non-zero errors in the workspace - */ -bool Stitch1D::hasNonzeroErrors(MatrixWorkspace_sptr ws) -{ -int64_t ws_size = static_cast<int64_t>(ws->getNumberHistograms()); -bool hasNonZeroErrors = false; -PARALLEL_FOR1(ws) -for (int i = 0; i < ws_size; ++i) -{ -PARALLEL_START_INTERUPT_REGION -if (!hasNonZeroErrors) // Keep checking -{ - auto e = ws->readE(i); - auto it = std::find_if(e.begin(), e.end(), isNonzero); - if (it != e.end()) - { - PARALLEL_CRITICAL(has_non_zero) + /**Determines if a workspace has non zero errors + @param ws :: The input workspace + @return True if there are any non-zero errors in the workspace + */ + bool Stitch1D::hasNonzeroErrors(MatrixWorkspace_sptr ws) { - hasNonZeroErrors = true; // Set flag. Should not need to check any more spectra. + int64_t ws_size = static_cast<int64_t>(ws->getNumberHistograms()); + bool hasNonZeroErrors = false; + PARALLEL_FOR1(ws) + for (int i = 0; i < ws_size; ++i) + { + PARALLEL_START_INTERUPT_REGION + if (!hasNonZeroErrors) // Keep checking + { + auto e = ws->readE(i); + auto it = std::find_if(e.begin(), e.end(), isNonzero); + if (it != e.end()) + { + PARALLEL_CRITICAL(has_non_zero) + { + hasNonZeroErrors = true; // Set flag. Should not need to check any more spectra. + } + } + } + PARALLEL_END_INTERUPT_REGION } - } -} -PARALLEL_END_INTERUPT_REGION -} -PARALLEL_CHECK_INTERUPT_REGION + PARALLEL_CHECK_INTERUPT_REGION -return hasNonZeroErrors; -} + return hasNonZeroErrors; + } //---------------------------------------------------------------------------------------------- -/** Execute the algorithm. - */ -void Stitch1D::exec() -{ -MatrixWorkspace_sptr rhsWS = this->getProperty("RHSWorkspace"); -MatrixWorkspace_sptr lhsWS = this->getProperty("LHSWorkspace"); -const MinMaxTuple intesectionXRegion = calculateXIntersection(lhsWS, rhsWS); - -const double intersectionMin = intesectionXRegion.get<0>(); -const double intersectionMax = intesectionXRegion.get<1>(); + /** Execute the algorithm. + */ + void Stitch1D::exec() + { + MatrixWorkspace_sptr rhsWS = this->getProperty("RHSWorkspace"); + MatrixWorkspace_sptr lhsWS = this->getProperty("LHSWorkspace"); + const MinMaxTuple intesectionXRegion = calculateXIntersection(lhsWS, rhsWS); -const double startOverlap = getStartOverlap(intersectionMin, intersectionMax); -const double endOverlap = getEndOverlap(intersectionMin, intersectionMax); + const double intersectionMin = intesectionXRegion.get<0>(); + const double intersectionMax = intesectionXRegion.get<1>(); -if (startOverlap > endOverlap) -{ -std::string message = boost::str( - boost::format( - "Stitch1D cannot have a StartOverlap > EndOverlap. StartOverlap: %0.9f, EndOverlap: %0.9f") - % startOverlap % endOverlap); -throw std::runtime_error(message); -} + const double startOverlap = getStartOverlap(intersectionMin, intersectionMax); + const double endOverlap = getEndOverlap(intersectionMin, intersectionMax); -const bool scaleRHS = this->getProperty("ScaleRHSWorkspace"); -MantidVec params = getRebinParams(lhsWS, rhsWS, scaleRHS); + if (startOverlap > endOverlap) + { + std::string message = boost::str( + boost::format( + "Stitch1D cannot have a StartOverlap > EndOverlap. StartOverlap: %0.9f, EndOverlap: %0.9f") + % startOverlap % endOverlap); + throw std::runtime_error(message); + } -const double& xMin = params.front(); -const double& xMax = params.back(); + const bool scaleRHS = this->getProperty("ScaleRHSWorkspace"); + MantidVec params = getRebinParams(lhsWS, rhsWS, scaleRHS); -if (startOverlap < xMin) -{ -std::string message = - boost::str( - boost::format( - "Stitch1D StartOverlap is outside the available X range after rebinning. StartOverlap: %10.9f, X min: %10.9f") - % startOverlap % xMin); + const double& xMin = params.front(); + const double& xMax = params.back(); -throw std::runtime_error(message); -} -if (endOverlap > xMax) -{ -std::string message = - boost::str( - boost::format( - "Stitch1D EndOverlap is outside the available X range after rebinning. EndOverlap: %10.9f, X max: %10.9f") - % endOverlap % xMax); + if (startOverlap < xMin) + { + std::string message = + boost::str( + boost::format( + "Stitch1D StartOverlap is outside the available X range after rebinning. StartOverlap: %10.9f, X min: %10.9f") + % startOverlap % xMin); -throw std::runtime_error(message); -} + throw std::runtime_error(message); + } + if (endOverlap > xMax) + { + std::string message = + boost::str( + boost::format( + "Stitch1D EndOverlap is outside the available X range after rebinning. EndOverlap: %10.9f, X max: %10.9f") + % endOverlap % xMax); -const size_t histogramCount = rhsWS->getNumberHistograms(); -m_nanYIndexes.resize(histogramCount); -m_infYIndexes.resize(histogramCount); -m_nanEIndexes.resize(histogramCount); -m_infEIndexes.resize(histogramCount); -auto rebinnedLHS = rebin(lhsWS, params); -auto rebinnedRHS = rebin(rhsWS, params); + throw std::runtime_error(message); + } -boost::tuple<int, int> startEnd = findStartEndIndexes(startOverlap, endOverlap, rebinnedLHS); + const size_t histogramCount = rhsWS->getNumberHistograms(); + m_nanYIndexes.resize(histogramCount); + m_infYIndexes.resize(histogramCount); + m_nanEIndexes.resize(histogramCount); + m_infEIndexes.resize(histogramCount); + auto rebinnedLHS = rebin(lhsWS, params); + auto rebinnedRHS = rebin(rhsWS, params); -const bool useManualScaleFactor = this->getProperty("UseManualScaleFactor"); -double scaleFactor = 0; -double errorScaleFactor = 0; + boost::tuple<int, int> startEnd = findStartEndIndexes(startOverlap, endOverlap, rebinnedLHS); -if (useManualScaleFactor) -{ -double manualScaleFactor = this->getProperty("ManualScaleFactor"); -MatrixWorkspace_sptr manualScaleFactorWS = singleValueWS(manualScaleFactor); + const bool useManualScaleFactor = this->getProperty("UseManualScaleFactor"); + double scaleFactor = 0; + double errorScaleFactor = 0; -if (scaleRHS) -{ -rebinnedRHS = rebinnedRHS * manualScaleFactorWS; -} -else -{ -rebinnedLHS = rebinnedLHS * manualScaleFactorWS; -} -scaleFactor = manualScaleFactor; -errorScaleFactor = manualScaleFactor; -} -else -{ -auto rhsOverlapIntegrated = integration(rebinnedRHS, startOverlap, endOverlap); -auto lhsOverlapIntegrated = integration(rebinnedLHS, startOverlap, endOverlap); + if (useManualScaleFactor) + { + double manualScaleFactor = this->getProperty("ManualScaleFactor"); + MatrixWorkspace_sptr manualScaleFactorWS = singleValueWS(manualScaleFactor); -MatrixWorkspace_sptr ratio; -if (scaleRHS) -{ -ratio = lhsOverlapIntegrated / rhsOverlapIntegrated; -rebinnedRHS = rebinnedRHS * ratio; -} -else -{ -ratio = rhsOverlapIntegrated / lhsOverlapIntegrated; -rebinnedLHS = rebinnedLHS * ratio; -} -scaleFactor = ratio->readY(0).front(); -errorScaleFactor = ratio->readE(0).front(); -if (scaleFactor < 1e-2 || scaleFactor > 1e2 || boost::math::isnan(scaleFactor)) -{ -std::stringstream messageBuffer; -messageBuffer << "Stitch1D calculated scale factor is: " << scaleFactor - << ". Check that in both input workspaces the integrated overlap region is non-zero."; -g_log.warning(messageBuffer.str()); -} + if (scaleRHS) + { + rebinnedRHS = rebinnedRHS * manualScaleFactorWS; + } + else + { + rebinnedLHS = rebinnedLHS * manualScaleFactorWS; + } + scaleFactor = manualScaleFactor; + errorScaleFactor = manualScaleFactor; + } + else + { + auto rhsOverlapIntegrated = integration(rebinnedRHS, startOverlap, endOverlap); + auto lhsOverlapIntegrated = integration(rebinnedLHS, startOverlap, endOverlap); -} + MatrixWorkspace_sptr ratio; + if (scaleRHS) + { + ratio = lhsOverlapIntegrated / rhsOverlapIntegrated; + rebinnedRHS = rebinnedRHS * ratio; + } + else + { + ratio = rhsOverlapIntegrated / lhsOverlapIntegrated; + rebinnedLHS = rebinnedLHS * ratio; + } + scaleFactor = ratio->readY(0).front(); + errorScaleFactor = ratio->readE(0).front(); + if (scaleFactor < 1e-2 || scaleFactor > 1e2 || boost::math::isnan(scaleFactor)) + { + std::stringstream messageBuffer; + messageBuffer << "Stitch1D calculated scale factor is: " << scaleFactor + << ". Check that in both input workspaces the integrated overlap region is non-zero."; + g_log.warning(messageBuffer.str()); + } -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 = maskAllBut(a1, a2, rebinnedLHS); -// Mask out everything BUT the overlap region as a new workspace. -MatrixWorkspace_sptr overlap2 = maskAllBut(a1, a2, rebinnedRHS); -// Mask out everything AFTER the overlap region as a new workspace. -maskInPlace(a1 + 1, static_cast<int>(rebinnedLHS->blocksize()), rebinnedLHS); -// Mask out everything BEFORE the overlap region as a new workspace. -maskInPlace(0, a2, rebinnedRHS); + int a1 = boost::tuples::get<0>(startEnd); + int a2 = boost::tuples::get<1>(startEnd); -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; -} + // Mask out everything BUT the overlap region as a new workspace. + MatrixWorkspace_sptr overlap1 = maskAllBut(a1, a2, rebinnedLHS); + // Mask out everything BUT the overlap region as a new workspace. + MatrixWorkspace_sptr overlap2 = maskAllBut(a1, a2, rebinnedRHS); + // Mask out everything AFTER the overlap region as a new workspace. + maskInPlace(a1 + 1, static_cast<int>(rebinnedLHS->blocksize()), rebinnedLHS); + // Mask out everything BEFORE the overlap region as a new workspace. + maskInPlace(0, a2, rebinnedRHS); -MatrixWorkspace_sptr result = rebinnedLHS + overlapave + rebinnedRHS; -reinsertSpecialValues(result); + 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; + } -// Provide log information about the scale factors used in the calculations. -std::stringstream messageBuffer; -messageBuffer << "Scale Factor Y is: " << scaleFactor << " Scale Factor E is: " << errorScaleFactor; -g_log.notice(messageBuffer.str()); + MatrixWorkspace_sptr result = rebinnedLHS + overlapave + rebinnedRHS; + reinsertSpecialValues(result); -setProperty("OutputWorkspace", result); -setProperty("OutScaleFactor", scaleFactor); + // Provide log information about the scale factors used in the calculations. + std::stringstream messageBuffer; + messageBuffer << "Scale Factor Y is: " << scaleFactor << " Scale Factor E is: " << errorScaleFactor; + g_log.notice(messageBuffer.str()); -} + setProperty("OutputWorkspace", result); + setProperty("OutScaleFactor", scaleFactor); -void Stitch1D::reinsertSpecialValues(MatrixWorkspace_sptr ws) -{ -int histogramCount = static_cast<int>(ws->getNumberHistograms()); -PARALLEL_FOR1(ws) -for (int i = 0; i < histogramCount; ++i) -{ -PARALLEL_START_INTERUPT_REGION - // Copy over the data -MantidVec& sourceY = ws->dataY(i); + } -for (size_t j = 0; j < m_nanYIndexes[i].size(); ++j) -{ - sourceY[m_nanYIndexes[i][j]] = std::numeric_limits<double>::quiet_NaN(); -} + /** + * Put special values back. + * @param ws : MatrixWorkspace to resinsert special values into. + */ + void Stitch1D::reinsertSpecialValues(MatrixWorkspace_sptr ws) + { + int histogramCount = static_cast<int>(ws->getNumberHistograms()); + PARALLEL_FOR1(ws) + for (int i = 0; i < histogramCount; ++i) + { + PARALLEL_START_INTERUPT_REGION + // Copy over the data + MantidVec& sourceY = ws->dataY(i); -for (size_t j = 0; j < m_infYIndexes[i].size(); ++j) -{ - sourceY[m_infYIndexes[i][j]] = std::numeric_limits<double>::infinity(); -} + for (size_t j = 0; j < m_nanYIndexes[i].size(); ++j) + { + sourceY[m_nanYIndexes[i][j]] = std::numeric_limits<double>::quiet_NaN(); + } -for (size_t j = 0; j < m_nanEIndexes[i].size(); ++j) -{ - sourceY[m_nanEIndexes[i][j]] = std::numeric_limits<double>::quiet_NaN(); -} + for (size_t j = 0; j < m_infYIndexes[i].size(); ++j) + { + sourceY[m_infYIndexes[i][j]] = std::numeric_limits<double>::infinity(); + } -for (size_t j = 0; j < m_infEIndexes[i].size(); ++j) -{ - sourceY[m_infEIndexes[i][j]] = std::numeric_limits<double>::infinity(); -} + for (size_t j = 0; j < m_nanEIndexes[i].size(); ++j) + { + sourceY[m_nanEIndexes[i][j]] = std::numeric_limits<double>::quiet_NaN(); + } + for (size_t j = 0; j < m_infEIndexes[i].size(); ++j) + { + sourceY[m_infEIndexes[i][j]] = std::numeric_limits<double>::infinity(); + } -PARALLEL_END_INTERUPT_REGION -} + PARALLEL_END_INTERUPT_REGION + } PARALLEL_CHECK_INTERUPT_REGION } diff --git a/Code/Mantid/docs/source/algorithms/Stitch1D-v3.rst b/Code/Mantid/docs/source/algorithms/Stitch1D-v3.rst index c72bbb4ce75..4b38c4a60fa 100644 --- a/Code/Mantid/docs/source/algorithms/Stitch1D-v3.rst +++ b/Code/Mantid/docs/source/algorithms/Stitch1D-v3.rst @@ -22,6 +22,16 @@ The workspaces must be histogrammed. Use :ref:`algm-ConvertToHistogram` on workspaces prior to passing them to this algorithm. +**Special Value Processing** + +Special values, meaning infinite and NaN double precision values, are treated in a different way by the algorithm. The processing is as follows: + +#. The workspaces are initially rebinned, as prescribed by the rebin Params (determined automatically if not provided) +#. Each spectra is searched for signal values and error values that are special values. Positions and type of special value are recorded +#. Special values found in the previous step are set to zero +#. Stitching proceeds, integration will not be performed considering any special values +#. Post processing the indexes of the special values are used to put the special values back where they came from + Usage ----- **Example - a basic example using stitch1D to stitch two workspaces together.** -- GitLab