diff --git a/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryReductionOne2.h b/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryReductionOne2.h index 4ac333833b4e591184f0fc62006b08802284fa2d..7c9aa809d1604520a24a14c59e89ae1c4966700e 100644 --- a/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryReductionOne2.h +++ b/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryReductionOne2.h @@ -88,6 +88,13 @@ private: // convert to momentum transfer Mantid::API::MatrixWorkspace_sptr convertToQ(Mantid::API::MatrixWorkspace_sptr inputWS); + // Utility function to create name for diagnostic workspaces + std::string createDebugWorkspaceName(const std::string &inputName); + // Utility function to output a diagnostic workspace to the ADS + void outputDebugWorkspace(API::MatrixWorkspace_sptr ws, + const std::string &wsName, + const std::string &wsSuffix, const bool debug, + int &step); // Create the output workspace in wavelength Mantid::API::MatrixWorkspace_sptr makeIvsLam(); // Do the reduction by summation in Q @@ -109,10 +116,12 @@ private: const double lambdaMax, const size_t outSpecIdx, API::MatrixWorkspace_sptr IvsLam, std::vector<double> &outputE); + void findWavelengthMinMax(API::MatrixWorkspace_sptr inputWS); // Construct the output workspace void findIvsLamRange(API::MatrixWorkspace_sptr detectorWS, - const std::vector<size_t> &detectors, double &xMin, - double &xMax); + const std::vector<size_t> &detectors, + const double lambdaMin, const double lambdaMax, + double &projectedMin, double &projectedMax); // Construct the output workspace Mantid::API::MatrixWorkspace_sptr constructIvsLamWS(API::MatrixWorkspace_sptr detectorWS); @@ -138,6 +147,8 @@ private: double theta0() { return m_theta0; } double twoThetaR(const std::vector<size_t> &detectors); size_t twoThetaRDetectorIdx(const std::vector<size_t> &detectors); + double wavelengthMin() { return m_wavelengthMin; }; + double wavelengthMax() { return m_wavelengthMax; }; API::MatrixWorkspace_sptr m_runWS; const API::SpectrumInfo *m_spectrumInfo; @@ -148,6 +159,11 @@ private: double m_theta0; // horizon angle // groups of spectrum indices of the detectors of interest std::vector<std::vector<size_t>> m_detectorGroups; + // Store the min/max wavelength we're interested in. These will be the + // input Wavelength min/max if summing in lambda, or the projected + // versions of these if summing in Q + double m_wavelengthMin; + double m_wavelengthMax; }; } // namespace Algorithms diff --git a/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase2.h b/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase2.h index a1823aa32a0fa0ee94f05dc38a1477a6fbe8a5e5..4f3f2c69598ba21526cc11e9d8ab4197338bdb6b 100644 --- a/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase2.h +++ b/Framework/Algorithms/inc/MantidAlgorithms/ReflectometryWorkflowBase2.h @@ -49,6 +49,8 @@ protected: void initAlgorithmicProperties(bool autodetect = false); /// Initialize momentum transfer properties void initMomentumTransferProperties(); + /// Initialize properties for diagnostics + void initDebugProperties(); /// Validate reduction-type properties std::map<std::string, std::string> validateReductionProperties() const; /// Validate direct beam properties @@ -62,7 +64,9 @@ protected: convertToWavelength(Mantid::API::MatrixWorkspace_sptr inputWS); /// Crop a workspace in wavelength Mantid::API::MatrixWorkspace_sptr - cropWavelength(Mantid::API::MatrixWorkspace_sptr inputWS); + cropWavelength(Mantid::API::MatrixWorkspace_sptr inputWS, + const bool useArgs = false, const double argMin = 0.0, + const double argMax = 0.0); // Create a detector workspace from input workspace in wavelength Mantid::API::MatrixWorkspace_sptr makeDetectorWS(Mantid::API::MatrixWorkspace_sptr inputWS, diff --git a/Framework/Algorithms/src/ReflectometryReductionOne2.cpp b/Framework/Algorithms/src/ReflectometryReductionOne2.cpp index 7725eb4f199facb8391ca72a885e95f64b0a92c2..181ab0a98afe857255351f6e327cb825fae53810 100644 --- a/Framework/Algorithms/src/ReflectometryReductionOne2.cpp +++ b/Framework/Algorithms/src/ReflectometryReductionOne2.cpp @@ -1,4 +1,5 @@ #include "MantidAlgorithms/ReflectometryReductionOne2.h" +#include "MantidAPI/AnalysisDataService.h" #include "MantidAPI/Axis.h" #include "MantidAPI/SpectrumInfo.h" #include "MantidAPI/MatrixWorkspace.h" @@ -386,6 +387,9 @@ void ReflectometryReductionOne2::init() { // Init properties for algorithmic corrections initAlgorithmicProperties(); + // Init properties for diagnostics + initDebugProperties(); + declareProperty(make_unique<WorkspaceProperty<>>("OutputWorkspace", "", Direction::Output), "Output Workspace IvsQ."); @@ -459,6 +463,55 @@ void ReflectometryReductionOne2::exec() { setProperty("OutputWorkspace", IvsQ); } +/** +* Utility function to create a unique workspace name for diagnostic outputs +* based on a given input workspace name +* +* @param inputName [in] : the input name +* @return : the output name +*/ +std::string ReflectometryReductionOne2::createDebugWorkspaceName( + const std::string &inputName) { + std::string result = inputName; + + if (summingInQ()) { + if (getPropertyValue("ReductionType") == "DivergentBeam") + result += "_QSD"; // Q-summed divergent beam + else + result += "_QSB"; // Q-summed bent (non-flat) sample + } else { + result += "_LS"; // lambda-summed + } + + return result; +} + +/** +* Utility function to add the given workspace to the ADS if debugging is +* enabled. +* +* @param ws [in] : the workspace to add to the ADS +* @param wsName [in] : the name to output the workspace as +* @param wsSuffix [in] : a suffix to apply to the wsName +* @param debug [in] : true if the workspace should be added to the ADS (the +* function does nothing if this is false) +* @param step [inout] : the current step number, which is added to the wsSuffix +* and is incremented after the workspace is output +*/ +void ReflectometryReductionOne2::outputDebugWorkspace( + MatrixWorkspace_sptr ws, const std::string &wsName, + const std::string &wsSuffix, const bool debug, int &step) { + // Nothing to do if debug is not enabled + if (debug) { + // Clone the workspace because otherwise we can end up outputting the same + // workspace twice with different names, which is confusing. + MatrixWorkspace_sptr cloneWS = ws->clone(); + AnalysisDataService::Instance().addOrReplace( + wsName + "_" + std::to_string(step) + wsSuffix, cloneWS); + ++step; + } +} + /** * Creates the output 1D array in wavelength from an input 2D workspace in * TOF. Summation is done over lambda or over lines of constant Q depending on @@ -470,43 +523,65 @@ void ReflectometryReductionOne2::exec() { MatrixWorkspace_sptr ReflectometryReductionOne2::makeIvsLam() { MatrixWorkspace_sptr result = m_runWS; + std::string wsName = + createDebugWorkspaceName(getPropertyValue("InputWorkspace")); + const bool debug = getProperty("Diagnostics"); + int step = 1; + if (summingInQ()) { if (m_convertUnits) { g_log.debug("Converting input workspace to wavelength\n"); result = convertToWavelength(result); + findWavelengthMinMax(result); + outputDebugWorkspace(result, wsName, "_lambda", debug, step); } + // Now the workspace is in wavelength, find the min/max wavelength + findWavelengthMinMax(result); if (m_normaliseMonitors) { g_log.debug("Normalising input workspace by monitors\n"); result = directBeamCorrection(result); + outputDebugWorkspace(result, wsName, "_norm_db", debug, step); result = monitorCorrection(result); + outputDebugWorkspace(result, wsName, "_norm_monitor", debug, step); } - // Crop to wavelength limits - g_log.debug("Cropping output workspace\n"); - result = cropWavelength(result); if (m_normaliseTransmission) { g_log.debug("Normalising input workspace by transmission run\n"); result = transOrAlgCorrection(result, false); + outputDebugWorkspace(result, wsName, "_norm_trans", debug, step); } if (m_sum) { g_log.debug("Summing in Q\n"); result = sumInQ(result); + outputDebugWorkspace(result, wsName, "_summed", debug, step); } + // Crop to wavelength limits + g_log.debug("Cropping output workspace\n"); + result = cropWavelength(result, true, wavelengthMin(), wavelengthMax()); + outputDebugWorkspace(result, wsName, "_cropped", debug, step); } else { if (m_sum) { g_log.debug("Summing in wavelength\n"); result = makeDetectorWS(result, m_convertUnits); + outputDebugWorkspace(result, wsName, "_summed", debug, step); } + // Now the workspace is in wavelength, find the min/max wavelength + findWavelengthMinMax(result); if (m_normaliseMonitors) { g_log.debug("Normalising output workspace by monitors\n"); result = directBeamCorrection(result); + outputDebugWorkspace(result, wsName, "_norm_db", debug, step); + result = monitorCorrection(result); + outputDebugWorkspace(result, wsName, "_norm_monitor", debug, step); } // Crop to wavelength limits g_log.debug("Cropping output workspace\n"); - result = cropWavelength(result); + result = cropWavelength(result, true, wavelengthMin(), wavelengthMax()); + outputDebugWorkspace(result, wsName, "_cropped", debug, step); if (m_normaliseTransmission) { g_log.debug("Normalising output workspace by transmission run\n"); result = transOrAlgCorrection(result, true); + outputDebugWorkspace(result, wsName, "_norm_trans", debug, step); } } @@ -834,7 +909,18 @@ void ReflectometryReductionOne2::findTheta0() { */ double ReflectometryReductionOne2::twoThetaR(const std::vector<size_t> &detectors) { - return getDetectorTwoTheta(m_spectrumInfo, twoThetaRDetectorIdx(detectors)); + // Get the twoTheta value for the destinaion pixel that we're projecting onto + double twoThetaR = + getDetectorTwoTheta(m_spectrumInfo, twoThetaRDetectorIdx(detectors)); + if (getPropertyValue("ReductionType") == "DivergentBeam") { + // The angle that should be used in the final conversion to Q is + // (twoThetaR-theta0). However, the angle actually used by ConvertUnits is + // twoThetaD/2 where twoThetaD is the detector's twoTheta angle. Since it + // is not easy to change what angle ConvertUnits uses, we can compensate by + // setting twoThetaR = twoThetaD/2+theta0 + twoThetaR = twoThetaR / 2.0 + theta0(); + } + return twoThetaR; } /** @@ -847,21 +933,60 @@ size_t ReflectometryReductionOne2::twoThetaRDetectorIdx( return detectors.front() + (detectors.back() - detectors.front()) / 2; } +void ReflectometryReductionOne2::findWavelengthMinMax( + MatrixWorkspace_sptr inputWS) { + + // Get the max/min wavelength of region of interest + const double lambdaMin = getProperty("WavelengthMin"); + const double lambdaMax = getProperty("WavelengthMax"); + + // If summing in lambda, the min/max wavelength is the same as the input + if (!summingInQ()) { + m_wavelengthMin = lambdaMin; + m_wavelengthMax = lambdaMax; + return; + } + + // If summing in Q, we need to do a projection the input min/max for each + // detector group and take the overall min/max of the projected range + const size_t numGroups = detectorGroups().size(); + + // Find the projected min/max wavelength for all detector groups + bool first = true; + for (size_t groupIdx = 0; groupIdx < numGroups; ++groupIdx) { + // Get the detectors in this group + auto &detectors = detectorGroups()[groupIdx]; + double projectedMin = 0; + double projectedMax = 0; + // Get the projected lambda for this detector group + findIvsLamRange(inputWS, detectors, lambdaMin, lambdaMax, projectedMin, + projectedMax); + // Set the overall min/max + if (first) { + m_wavelengthMin = projectedMin; + m_wavelengthMax = projectedMax; + first = false; + } else { + m_wavelengthMin = std::min(m_wavelengthMax, projectedMin); + m_wavelengthMax = std::max(m_wavelengthMax, projectedMax); + } + } +} + /** * Find the range of the projected lambda range when summing in Q * * @param detectorWS [in] : the workspace containing the values to project * @param detectors [in] : the workspace indices of the detectors of interest -* @param xMin [out] : the start of the projected lambda range -* @param xMax [out] : the end of the projected lambda range +* @param lambdaMin [in] : the start of the range to project +* @param lambdaMax [in] : the end of the range to project +* @param projectedMin [out] : the start of the resulting projected range +* @param projectedMax [out] : the end of the resulting projected range */ void ReflectometryReductionOne2::findIvsLamRange( MatrixWorkspace_sptr detectorWS, const std::vector<size_t> &detectors, - double &xMin, double &xMax) { - - // Get the max/min wavelength of region of interest - const double lambdaMin = getProperty("WavelengthMin"); - const double lambdaMax = getProperty("WavelengthMax"); + const double lambdaMin, const double lambdaMax, double &projectedMin, + double &projectedMax) { // Get the new max and min X values of the projected (virtual) lambda range double dummy = 0.0; @@ -875,7 +1000,7 @@ void ReflectometryReductionOne2::findIvsLamRange( double bLambda = (xValues[xValues.size() - 1] - xValues[0]) / static_cast<int>(xValues.size()); getProjectedLambdaRange(lambdaMax, twoThetaMin, bLambda, bTwoThetaMin, - detectors, dummy, xMax); + detectors, dummy, projectedMax); const size_t spIdxMax = detectors.back(); const double twoThetaMax = getDetectorTwoTheta(m_spectrumInfo, spIdxMax); @@ -885,13 +1010,14 @@ void ReflectometryReductionOne2::findIvsLamRange( bLambda = (xValues[xValues.size() - 1] - xValues[0]) / static_cast<int>(xValues.size()); getProjectedLambdaRange(lambdaMin, twoThetaMax, bLambda, bTwoThetaMax, - detectors, xMin, dummy); + detectors, projectedMin, dummy); - if (xMin > xMax) { + if (projectedMin > projectedMax) { throw std::runtime_error( "Error projecting lambda range to reference line at twoTheta=" + std::to_string(twoThetaR(detectors)) + "; projected range (" + - std::to_string(xMin) + "," + std::to_string(xMax) + ") is negative."); + std::to_string(projectedMin) + "," + std::to_string(projectedMax) + + ") is negative."); } } @@ -906,36 +1032,25 @@ MatrixWorkspace_sptr ReflectometryReductionOne2::constructIvsLamWS(MatrixWorkspace_sptr detectorWS) { // There is one output spectrum for each detector group - MatrixWorkspace_sptr outputWS = - WorkspaceFactory::Instance().create(detectorWS, detectorGroups().size()); - const size_t numGroups = detectorGroups().size(); - const size_t numHist = outputWS->getNumberHistograms(); - if (numHist != numGroups) { - throw std::runtime_error( - "Error constructing IvsLam: number of output histograms " + - std::to_string(numHist) + - " does not equal the number of input detector groups " + - std::to_string(numGroups)); - } + // Calculate the number of bins based on the min/max wavelength, using + // the same bin width as the input workspace + const double binWidth = (detectorWS->x(0).back() - detectorWS->x(0).front()) / + static_cast<double>(detectorWS->blocksize()); + const int numBins = static_cast<int>( + std::ceil((wavelengthMax() - wavelengthMin()) / binWidth)); + // Construct the histogram with these X values. Y and E values are zero. + const BinEdges xValues(numBins, LinearGenerator(wavelengthMin(), binWidth)); + // Create the output workspace + MatrixWorkspace_sptr outputWS = WorkspaceFactory::Instance().create( + detectorWS, numGroups, numBins, numBins - 1); // Loop through each detector group in the input for (size_t groupIdx = 0; groupIdx < numGroups; ++groupIdx) { // Get the detectors in this group auto &detectors = detectorGroups()[groupIdx]; - - // Find the X values. These are the projected lambda values for this - // detector group - double xMin = 0.0; - double xMax = 0.0; - findIvsLamRange(detectorWS, detectors, xMin, xMax); - // Use the same number of bins as the input - const int numBins = static_cast<int>(detectorWS->blocksize()); - const double binWidth = (xMax - xMin) / (numBins + 1); - // Construct the histogram with these X values. Y and E values are zero. - const BinEdges xValues(numBins + 1, LinearGenerator(xMin, binWidth)); + // Set the x values for this spectrum outputWS->setBinEdges(groupIdx, xValues); - // Set the detector ID from the twoThetaR detector. const size_t twoThetaRIdx = twoThetaRDetectorIdx(detectors); auto &outSpec = outputWS->getSpectrum(groupIdx); @@ -1006,7 +1121,7 @@ ReflectometryReductionOne2::sumInQ(MatrixWorkspace_sptr detectorWS) { } // Sum errors in quadrature - const int eSize = static_cast<int>(inputE.size()); + const int eSize = static_cast<int>(outputE.size()); for (int outIdx = 0; outIdx < eSize; ++outIdx) { outputE[outIdx] += projectedE[outIdx] * projectedE[outIdx]; } @@ -1145,6 +1260,13 @@ void ReflectometryReductionOne2::getProjectedLambdaRange( const double bTwoTheta, const std::vector<size_t> &detectors, double &lambdaVMin, double &lambdaVMax) { + // We cannot project pixels below the horizon angle + if (twoTheta <= theta0()) { + throw std::runtime_error( + "Cannot process twoTheta=" + std::to_string(twoTheta) + + " as it is below the horizon angle=" + std::to_string(theta0())); + } + // Get the angle from twoThetaR to this detector const double twoThetaRVal = twoThetaR(detectors); // Get the distance from the pixel to twoThetaR @@ -1154,12 +1276,14 @@ void ReflectometryReductionOne2::getProjectedLambdaRange( // Calculate the projected wavelength range try { - const double lambdaTop = std::sin(horizonThetaR) * - (lambda + bLambda / 2.0) / - std::sin(horizonThetaR + gamma - bTwoTheta / 2.0); - const double lambdaBot = std::sin(horizonThetaR) * - (lambda - bLambda / 2.0) / - std::sin(horizonThetaR + gamma + bTwoTheta / 2.0); + const double lambdaTop = + (lambda + bLambda / 2.0) * + (std::sin(horizonThetaR) / + std::sin(horizonThetaR + gamma - bTwoTheta / 2.0)); + const double lambdaBot = + (lambda - bLambda / 2.0) * + (std::sin(horizonThetaR) / + std::sin(horizonThetaR + gamma + bTwoTheta / 2.0)); lambdaVMin = std::min(lambdaTop, lambdaBot); lambdaVMax = std::max(lambdaTop, lambdaBot); } catch (std::exception &ex) { diff --git a/Framework/Algorithms/src/ReflectometryReductionOneAuto2.cpp b/Framework/Algorithms/src/ReflectometryReductionOneAuto2.cpp index ddc0e55ed42e8198efee8b3a3c0401ed893c1f03..0460b06d4e87171e61604774f61cd583a1271090 100644 --- a/Framework/Algorithms/src/ReflectometryReductionOneAuto2.cpp +++ b/Framework/Algorithms/src/ReflectometryReductionOneAuto2.cpp @@ -204,6 +204,9 @@ void ReflectometryReductionOneAuto2::init() { setPropertyGroup("CRho", "Polarization Corrections"); setPropertyGroup("CAlpha", "Polarization Corrections"); + // Init properties for diagnostics + initDebugProperties(); + // Output workspace in Q declareProperty(make_unique<WorkspaceProperty<MatrixWorkspace>>( "OutputWorkspaceBinned", "", Direction::Output), @@ -233,6 +236,7 @@ void ReflectometryReductionOneAuto2::exec() { // Mandatory properties alg->setProperty("SummationType", getPropertyValue("SummationType")); alg->setProperty("ReductionType", getPropertyValue("ReductionType")); + alg->setProperty("Diagnostics", getPropertyValue("Diagnostics")); double wavMin = checkForMandatoryInstrumentDefault<double>( this, "WavelengthMin", instrument, "LambdaMin"); alg->setProperty("WavelengthMin", wavMin); diff --git a/Framework/Algorithms/src/ReflectometryWorkflowBase2.cpp b/Framework/Algorithms/src/ReflectometryWorkflowBase2.cpp index 9be7cfe924e54088b4b4566b55e619b4b08094cd..b7d4bda73b7bef126fb575874336f20b5d90f328 100644 --- a/Framework/Algorithms/src/ReflectometryWorkflowBase2.cpp +++ b/Framework/Algorithms/src/ReflectometryWorkflowBase2.cpp @@ -197,6 +197,15 @@ void ReflectometryWorkflowBase2::initMomentumTransferProperties() { "Factor you wish to scale Q workspace by.", Direction::Input); } +/** Initialize properties for diagnostics +*/ +void ReflectometryWorkflowBase2::initDebugProperties() { + // Diagnostics + declareProperty("Diagnostics", false, "Whether to enable the output of " + "interim workspaces for debugging " + "purposes."); +} + /** Validate reduction properties, if given * * @return :: A map with results of validation @@ -342,14 +351,28 @@ ReflectometryWorkflowBase2::convertToWavelength(MatrixWorkspace_sptr inputWS) { /** Crops a workspace in wavelength to specified limits * @param inputWS :: the workspace to crop +* @param useArgs :: if true, use the given args as the min and max; +* otherwise, use the input properties to the algorithm +* @param argMin :: the minimum wavelength to crop to if useArgs is true +* @param argMax :: the maximum wavelength to crop to if useArgs is true * @return :: the cropped workspace */ -MatrixWorkspace_sptr -ReflectometryWorkflowBase2::cropWavelength(MatrixWorkspace_sptr inputWS) { +MatrixWorkspace_sptr ReflectometryWorkflowBase2::cropWavelength( + MatrixWorkspace_sptr inputWS, const bool useArgs, const double argMin, + const double argMax) { - // Crop out the lambda x-ranges now that the workspace is in wavelength. - double wavelengthMin = getProperty("WavelengthMin"); - double wavelengthMax = getProperty("WavelengthMax"); + double wavelengthMin = 0.0; + double wavelengthMax = 0.0; + + if (useArgs) { + // Use the given args + wavelengthMin = argMin; + wavelengthMax = argMax; + } else { + // Use the input properties to the algorithm + wavelengthMin = getProperty("WavelengthMin"); + wavelengthMax = getProperty("WavelengthMax"); + } auto cropWorkspaceAlg = createChildAlgorithm("CropWorkspace"); cropWorkspaceAlg->initialize(); diff --git a/Framework/Algorithms/test/ReflectometryReductionOne2Test.h b/Framework/Algorithms/test/ReflectometryReductionOne2Test.h index 5c6e780348b4c8d4b4422506aa5e82a3c8d9f4b6..a81db535a25473585f77dc4c8a3e26cb88f5bd66 100644 --- a/Framework/Algorithms/test/ReflectometryReductionOne2Test.h +++ b/Framework/Algorithms/test/ReflectometryReductionOne2Test.h @@ -445,14 +445,14 @@ public: alg.setProperty("SummationType", "SumInQ"); alg.setProperty("ReductionType", "DivergentBeam"); alg.setProperty("ThetaIn", 25.0); - MatrixWorkspace_sptr outLam = runAlgorithmLam(alg, 8); + MatrixWorkspace_sptr outLam = runAlgorithmLam(alg, 12); - TS_ASSERT_DELTA(outLam->x(0)[0], 0.8597, 0.0001); - TS_ASSERT_DELTA(outLam->x(0)[3], 5.8582, 0.0001); - TS_ASSERT_DELTA(outLam->x(0)[7], 12.5229, 0.0001); - TS_ASSERT_DELTA(outLam->y(0)[0], 0.0, 0.0001); - TS_ASSERT_DELTA(outLam->y(0)[3], 3.6539, 0.0001); - TS_ASSERT_DELTA(outLam->y(0)[7], 3.1458, 0.0001); + TS_ASSERT_DELTA(outLam->x(0)[0], 0.927132, 1e-6); + TS_ASSERT_DELTA(outLam->x(0)[3], 5.165740, 1e-6); + TS_ASSERT_DELTA(outLam->x(0)[7], 10.817217, 1e-6); + TS_ASSERT_DELTA(outLam->y(0)[0], 2.773699, 1e-6); + TS_ASSERT_DELTA(outLam->y(0)[3], 2.828460, 1e-6); + TS_ASSERT_DELTA(outLam->y(0)[7], 2.816935, 1e-6); } void test_sum_in_q_non_flat_sample() { @@ -467,14 +467,14 @@ public: setupAlgorithm(alg, 1.5, 15.0, "1"); alg.setProperty("SummationType", "SumInQ"); alg.setProperty("ReductionType", "NonFlatSample"); - MatrixWorkspace_sptr outLam = runAlgorithmLam(alg, 8); + MatrixWorkspace_sptr outLam = runAlgorithmLam(alg, 10); - TS_ASSERT_DELTA(outLam->x(0)[0], 0.8675, 0.0001); - TS_ASSERT_DELTA(outLam->x(0)[3], 5.8147, 0.0001); - TS_ASSERT_DELTA(outLam->x(0)[7], 12.4109, 0.0001); - TS_ASSERT_DELTA(outLam->y(0)[0], 0.0, 0.0001); - TS_ASSERT_DELTA(outLam->y(0)[3], 3.6513, 0.0001); - TS_ASSERT_DELTA(outLam->y(0)[7], 3.6137, 0.0001); + TS_ASSERT_DELTA(outLam->x(0)[0], 0.822974, 1e-6); + TS_ASSERT_DELTA(outLam->x(0)[3], 5.061582, 1e-6); + TS_ASSERT_DELTA(outLam->x(0)[7], 10.713059, 1e-6); + TS_ASSERT_DELTA(outLam->y(0)[0], 3.140302, 1e-6); + TS_ASSERT_DELTA(outLam->y(0)[3], 3.140457, 1e-6); + TS_ASSERT_DELTA(outLam->y(0)[7], 3.140644, 1e-6); } void test_sum_in_q_direct_beam() { @@ -490,14 +490,14 @@ public: alg.setProperty("SummationType", "SumInQ"); alg.setProperty("ReductionType", "DivergentBeam"); alg.setProperty("ThetaIn", 25.0); - MatrixWorkspace_sptr outLam = runAlgorithmLam(alg, 8); + MatrixWorkspace_sptr outLam = runAlgorithmLam(alg, 11); - TS_ASSERT_DELTA(outLam->x(0)[0], 0.8603, 0.0001); - TS_ASSERT_DELTA(outLam->x(0)[3], 5.8547, 0.0001); - TS_ASSERT_DELTA(outLam->x(0)[7], 12.5140, 0.0001); - TS_ASSERT_DELTA(outLam->y(0)[0], 0.0, 0.0001); - TS_ASSERT_DELTA(outLam->y(0)[3], 0.5803, 0.0001); - TS_ASSERT_DELTA(outLam->y(0)[7], 0.5048, 0.0001); + TS_ASSERT_DELTA(outLam->x(0)[0], 0.913144, 1e-6); + TS_ASSERT_DELTA(outLam->x(0)[3], 5.151752, 1e-6); + TS_ASSERT_DELTA(outLam->x(0)[7], 10.803229, 1e-6); + TS_ASSERT_DELTA(outLam->y(0)[0], 0.447237, 1e-6); + TS_ASSERT_DELTA(outLam->y(0)[3], 0.454605, 1e-6); + TS_ASSERT_DELTA(outLam->y(0)[7], 0.451946, 1e-6); } void test_sum_in_q_monitor_normalization() { @@ -525,14 +525,14 @@ public: alg.setProperty("SummationType", "SumInQ"); alg.setProperty("ReductionType", "DivergentBeam"); alg.setProperty("ThetaIn", 25.0); - MatrixWorkspace_sptr outLam = runAlgorithmLam(alg, 10); + MatrixWorkspace_sptr outLam = runAlgorithmLam(alg, 13); - TS_ASSERT_DELTA(outLam->x(0)[0], -0.6336, 0.0001); - TS_ASSERT_DELTA(outLam->x(0)[5], 6.8626, 0.0001); - TS_ASSERT_DELTA(outLam->x(0)[9], 12.8596, 0.0001); - TS_ASSERT_DELTA(outLam->y(0)[0], 7.2899, 0.0001); - TS_ASSERT_DELTA(outLam->y(0)[5], 2.6136, 0.0001); - TS_ASSERT_DELTA(outLam->y(0)[9], 2.0315, 0.0001); + TS_ASSERT_DELTA(outLam->x(0)[0], -0.742692, 1e-6); + TS_ASSERT_DELTA(outLam->x(0)[5], 6.321654, 1e-6); + TS_ASSERT_DELTA(outLam->x(0)[9], 11.973131, 1e-6); + TS_ASSERT_DELTA(outLam->y(0)[0], 5.044175, 1e-6); + TS_ASSERT_DELTA(outLam->y(0)[5], 2.118472, 1e-6); + TS_ASSERT_DELTA(outLam->y(0)[9], 2.280546, 1e-6); } void test_sum_in_q_transmission_correction_run() { @@ -544,14 +544,14 @@ public: alg.setProperty("SummationType", "SumInQ"); alg.setProperty("ReductionType", "DivergentBeam"); alg.setProperty("ThetaIn", 25.0); - MatrixWorkspace_sptr outLam = runAlgorithmLam(alg, 8); + MatrixWorkspace_sptr outLam = runAlgorithmLam(alg, 12); - TS_ASSERT_DELTA(outLam->x(0)[0], 0.8597, 0.0001); - TS_ASSERT_DELTA(outLam->x(0)[3], 5.8582, 0.0001); - TS_ASSERT_DELTA(outLam->x(0)[7], 12.5229, 0.0001); - TS_ASSERT_DELTA(outLam->y(0)[0], 0.0, 0.0001); - TS_ASSERT_DELTA(outLam->y(0)[3], 1.1625, 0.0001); - TS_ASSERT_DELTA(outLam->y(0)[7], 1.0009, 0.0001); + TS_ASSERT_DELTA(outLam->x(0)[0], 0.927132, 1e-6); + TS_ASSERT_DELTA(outLam->x(0)[3], 5.165740, 1e-6); + TS_ASSERT_DELTA(outLam->x(0)[7], 10.817217, 1e-6); + TS_ASSERT_DELTA(outLam->y(0)[0], 0.620714, 1e-6); + TS_ASSERT_DELTA(outLam->y(0)[3], 0.899935, 1e-6); + TS_ASSERT_DELTA(outLam->y(0)[7], 0.896268, 1e-6); } void test_sum_in_q_exponential_correction() { @@ -565,14 +565,14 @@ public: alg.setProperty("CorrectionAlgorithm", "ExponentialCorrection"); alg.setProperty("C0", 0.2); alg.setProperty("C1", 0.1); - MatrixWorkspace_sptr outLam = runAlgorithmLam(alg, 8); + MatrixWorkspace_sptr outLam = runAlgorithmLam(alg, 11); - TS_ASSERT_DELTA(outLam->x(0)[0], 0.8603, 0.0001); - TS_ASSERT_DELTA(outLam->x(0)[3], 5.8547, 0.0001); - TS_ASSERT_DELTA(outLam->x(0)[7], 12.5140, 0.0001); - TS_ASSERT_DELTA(outLam->y(0)[0], 0.0, 0.0001); - TS_ASSERT_DELTA(outLam->y(0)[3], 36.1423, 0.0001); - TS_ASSERT_DELTA(outLam->y(0)[7], 59.3020, 0.0001); + TS_ASSERT_DELTA(outLam->x(0)[0], 0.913144, 1e-6); + TS_ASSERT_DELTA(outLam->x(0)[3], 5.151752, 1e-6); + TS_ASSERT_DELTA(outLam->x(0)[7], 10.803229, 1e-6); + TS_ASSERT_DELTA(outLam->y(0)[0], 16.353662, 1e-6); + TS_ASSERT_DELTA(outLam->y(0)[3], 24.261270, 1e-6); + TS_ASSERT_DELTA(outLam->y(0)[7], 39.844321, 1e-6); } void test_sum_in_q_IvsQ() { @@ -587,16 +587,16 @@ public: alg.setProperty("SummationType", "SumInQ"); alg.setProperty("ReductionType", "DivergentBeam"); alg.setProperty("ThetaIn", 25.0); - MatrixWorkspace_sptr outQ = runAlgorithmQ(alg, 8); + MatrixWorkspace_sptr outQ = runAlgorithmQ(alg, 11); // X range in outQ - TS_ASSERT_DELTA(outQ->x(0)[0], 0.3391, 0.0001); - TS_ASSERT_DELTA(outQ->x(0)[3], 0.5235, 0.0001); - TS_ASSERT_DELTA(outQ->x(0)[7], 1.9044, 0.0001); + TS_ASSERT_DELTA(outQ->x(0)[0], 0.292253, 1e-6); + TS_ASSERT_DELTA(outQ->x(0)[3], 0.393656, 1e-6); + TS_ASSERT_DELTA(outQ->x(0)[7], 0.732554, 1e-6); // Y counts - TS_ASSERT_DELTA(outQ->y(0)[0], 3.1887, 0.0001); - TS_ASSERT_DELTA(outQ->y(0)[3], 3.6419, 0.0001); - TS_ASSERT_DELTA(outQ->y(0)[7], 0.0, 0.0001); + TS_ASSERT_DELTA(outQ->y(0)[0], 2.891639, 1e-6); + TS_ASSERT_DELTA(outQ->y(0)[3], 2.854571, 1e-6); + TS_ASSERT_DELTA(outQ->y(0)[7], 2.871364, 1e-6); } private: diff --git a/docs/source/algorithms/ReflectometryReductionOne-v2.rst b/docs/source/algorithms/ReflectometryReductionOne-v2.rst index 0ead45dccb4231e281dc9f903b3c2d2ea68168f1..6079a718311f5e69bb27e8816feaed526f51e69c 100644 --- a/docs/source/algorithms/ReflectometryReductionOne-v2.rst +++ b/docs/source/algorithms/ReflectometryReductionOne-v2.rst @@ -28,7 +28,8 @@ vector must be :math:`2\theta`. The figure below displays a high-level workflow diagram illustrating the main -steps taking place in the reduction. +steps taking place in the reduction. For the sake of clarity, all possible +steps are illustrated, even if some of them are optional. .. diagram:: ReflectometryReductionOne_HighLvl-v2_wkflw.dot @@ -45,7 +46,7 @@ cropped in wavelength according to :literal:`WavelengthMin` and :literal:`WavelengthMax`, which are both mandatory properties. If summation is to be done in Q, this is done after the normalisations and -cropping, but again, only if the original input was not already in wavelength. +cropping, but again, only if the reduction has not already been done. Finally, the output workspace in wavelength is converted to momentum transfer (Q). @@ -53,23 +54,43 @@ Finally, the output workspace in wavelength is converted to momentum transfer Conversion to Wavelength ######################## -If the input workspace is in TOF, monitors are extracted using -:ref:`algm-GroupDetectors` with ``RegionOfDirectBeam`` as input, and region of -direct beam using :ref:`algm-CropWorkspace` with ``I0MonitorIndex`` as -input. If summing in wavelength, detectors of interest are extracted and summed -in TOF using :ref:`algm-GroupDetectors` with ``ProcessingInstructions`` as -input. If summing in Q, summation is not done yet as it is done in a later step -after all normalisations have been done. - -Each of the resulting workspaces is converted to wavelength (note that -:literal:`AlignBins` is set to :literal:`True` in all the three cases). Note -that the normalization by a direct beam is optional, and only happens if -``RegionOfDirectBeam`` is provided. In the same way, monitor normalization is -also optional, and only takes place if ``I0MonitorIndex``, +If summing in wavelength, detectors of interest are extracted and summed in TOF +using :ref:`algm-GroupDetectors` with ``ProcessingInstructions`` as input. (If +summing in Q, summation is not done yet as it is done in a later step after all +normalisations have been done.) The workspace is then converted to wavelength +with :literal:`AlignBins` set to :literal:`True`. + +Next, normalization by direct beam and monitors is optionally done using +:ref:`algm-Divide`. A summary of the steps is shown in the workflow diagram +below. + +.. diagram:: ReflectometryReductionOne_ConvertToWavelength-v2_wkflw.dot + +Create Direct Beam Workspace +############################ + +Direct Beam and Monitor corrections can be applied to the workspace. These are +both optional steps and will only take place if the required inputs are +provided - otherwise, these steps will be skipped. + +The region of direct beam is extracted from the input workspace in TOF using +:ref:`algm-GroupDetectors` with ``RegionOfDirectBeam`` as input. This is only +done if ``RegionOfDirectBeam`` is specified. The resulting workspace is +converted to wavelength with :literal:`AlignBins` set to :literal:`True`. + +.. diagram:: ReflectometryReductionOne_DirectBeamCorrection-v2_wkflw.dot + +Create Monitor Workspace +######################## + +Monitors are extracted from the input workspace in TOF using +:ref:`algm-CropWorkspace` with ``I0MonitorIndex`` as input. The resulting +workspace is converted to wavelength with :literal:`AlignBins` set to +:literal:`True`. Monitor normalisation is only done if ``I0MonitorIndex``, ``MonitorBackgroundWavelengthMin`` and ``MonitorBackgroundWavelengthMax`` are all specified. -Detectors can be normalized by integrated monitors by setting +Normalisation can be done by integrated monitors by setting :literal:`NormalizeByIntegratedMonitors` to true, in which case :literal:`MonitorIntegrationWavelengthMin` and :literal:`MonitorIntegrationWavelengthMax` are used as the integration @@ -77,11 +98,7 @@ range. If monitors are not integrated, detectors are rebinned to monitors using :ref:`algm-RebinToWorkspace` so that the normalization by monitors can take place. -A summary of the steps is shown in the workflow diagram below. For the sake of -clarity, all possible steps are illustrated, even if some of them are optional. - -.. diagram:: ReflectometryReductionOne_ConvertToWavelength-v2_wkflw.dot - +.. diagram:: ReflectometryReductionOne_MonitorCorrection-v2_wkflw.dot Transmission Correction ####################### @@ -127,17 +144,20 @@ Sum in Q If summing in Q, the summation is done now, after all normalisations and cropping have been done. As with summation in :math:`\lambda`, the summation is -only done if the original workspace was not in :math:`\lambda` (otherwise we -assume the reduction has already been done). +only done if the reduction has not already been done. The summation is done using the algorithm proposed by Cubitt et al (J. Appl. Crystallogr., 48 (6) (2015)). This involves a projection to an arbitrary reference angle, :math:`2\theta_R`, with a "virtual" wavelength, :math:`\lambda_v`. This is the wavelength the neutron would have had if it had -arrived at :math:`2\theta_R` with the same momentum transfer -(:math:`Q`). Counts are shared out proportionally into the output array in -:math:`\lambda_v` and the projections from all pixels are summed in -:math:`\lambda_v`. +arrived at :math:`2\theta_R` with the same momentum transfer (:math:`Q`). + +Counts are considered to be spread evenly over the input pixel, and the +top-left and bottom-right corner of the pixel are projected onto +:math:`2\theta_R` giving a range in :math:`\lambda_v` to project onto. Counts +are shared out proportionally into the output bins that overlap this range, and +the projected counts from all pixels are summed into the appropriate output +bins. The resulting 1D workspace in :math:`\lambda_v` at :math:`2\theta_R` becomes the output workspace in wavelength. @@ -148,17 +168,21 @@ Conversion to Momentum Transfer (Q) ################################### Finally, the output workspace in wavelength is converted to momentum transfer -(:math:`Q`) using :ref:`algm-ConvertUnits`. Note that the output workspace in Q -is therefore a workspace with native binning, and no rebin step is applied to -it. +(:math:`Q`) using :ref:`algm-ConvertUnits`. The equation used is +:math:`Q=4\pi sin(\theta_R)/\lambda_v` in the non-flat sample case or +:math:`Q=4\pi sin(2\theta_R-\theta_0)/\lambda_v` in the divergent beam +case. This is because the latter needs to take into account the divergence of +the beam from the assumed direct beam direction. .. diagram:: ReflectometryReductionOne_ConvertToMomentum-v2_wkflw.dot -If you wish to obtain a rebinned workspace in Q you should consider using algorithm -:ref:`algm-ReflectometryReductionOneAuto` instead, which is a facade over this algorithm -and has two extra steps (:ref:`algm-Rebin` and :ref:`algm-Scale`) to produce an additional -workspace in Q with specified binning and scale factor. Please refer to :ref:`algm-ReflectometryReductionOneAuto` -for more information. +Note that the output workspace in Q is a workspace with native binning, and no +rebin step is applied to it. If you wish to obtain a rebinned workspace in Q +you should consider using algorithm :ref:`algm-ReflectometryReductionOneAuto` +instead, which is a facade over this algorithm and has two extra steps +(:ref:`algm-Rebin` and :ref:`algm-Scale`) to produce an additional workspace in +Q with specified binning and scale factor. Please refer to +:ref:`algm-ReflectometryReductionOneAuto` for more information. Previous Versions ----------------- diff --git a/docs/source/diagrams/ReflectometryReductionOne_ConvertToWavelength-v2_wkflw.dot b/docs/source/diagrams/ReflectometryReductionOne_ConvertToWavelength-v2_wkflw.dot index 9f3cee778b2d776e425f2aa93689c7547403dd9f..6f44c541eb4e07f96c11447b467cf3271615b3be 100644 --- a/docs/source/diagrams/ReflectometryReductionOne_ConvertToWavelength-v2_wkflw.dot +++ b/docs/source/diagrams/ReflectometryReductionOne_ConvertToWavelength-v2_wkflw.dot @@ -6,77 +6,58 @@ rankdir = TB; subgraph params { $param_style - inputWS [label="InputWorkspace"] - outputWS [label="OutputWorkspaceWavelength"] + inputWS [label="InputWorkspace", group=gmain] + outputWS [label="OutputWorkspaceWavelength", group=gmain] procCommands [label="ProcessingInstructions"] - monitorIndex [label="I0MonitorIndex"] - regionOfDirectBeam [label="RegionOf-\nDirectBeam"] - monIntWavMax [label="MonitorIntegration-\nWavelengthMax"] - monIntWavMin [label="MonitorIntegration-\nWavelengthMin"] - monBackWavMin [label="MonitorBackground-\nWavelengthMin"] - monBackWavMax [label="MonitorBackground-\nWavelengthMax"] + wavMin [label="WavelengthMin"] + wavMax [label="WavelengthMax"] } subgraph decisions { $decision_style checkSumInLam [label="Sum in λ?"] + checkSumInLam2 [label="Sum in λ?", group=gmain] } subgraph algorithms { $algorithm_style convertDet [label="ConvertUnits\n(AlignBins = True)"] - convertDB [label="ConvertUnits\n(AlignBins = True)"] - convertMon [label="ConvertUnits\n(AlignBins = True)", group=g11] groupDet [label="GroupDetectors"] - cropMonWS [label="CropWorkspace", group=g11] - calcFlatBg [label="CalculateFlatBackground", group=g11] - intMon [label="Integration", group=g11] - groupDetRDB [label="GroupDetectors"] - divideDetMon [label="Divide\n(Detectors / Monitors)", group=g1] - divideDetRDB [label="Divide\n(Detectors / DirectBeam)", group=g1] + cropWav [label="CropWorkspace"] + divideDetDB [label="Divide\n(Detectors / DirectBeam)"] + divideDetMon [label="Divide\n(Detectors / Monitors)"] } subgraph processes { $process_style + createDBWS [label="Create direct beam\nworkspace"] + createMonWS [label="Create monitor\nworkspace"] } subgraph values { $value_style } -inputWS -> checkSumInLam [label="Detectors"] -inputWS -> groupDetRDB [label="Direct Beam"] -inputWS -> cropMonWS [label="Monitors"] +inputWS -> checkSumInLam [label="Detectors"] +inputWS -> createDBWS [label="Direct Beam"] +inputWS -> createMonWS [label="Monitors"] -checkSumInLam -> convertDet [label="No"] -checkSumInLam -> groupDet [label="Yes"] -groupDet -> convertDet +checkSumInLam -> convertDet [label="No"] +checkSumInLam -> groupDet [label="Yes"] -procCommands -> groupDet +procCommands -> groupDet +groupDet -> convertDet +convertDet -> divideDetDB +createDBWS -> divideDetDB +divideDetDB -> divideDetMon +createMonWS -> divideDetMon +divideDetMon -> checkSumInLam2 -regionOfDirectBeam -> groupDetRDB -groupDetRDB -> convertDB +checkSumInLam2 -> outputWS [label="No"] +checkSumInLam2 -> cropWav [label="Yes"] +wavMin -> cropWav +wavMax -> cropWav +cropWav -> outputWS -monitorIndex -> cropMonWS -cropMonWS -> convertMon - -convertDet -> divideDetRDB -convertDB -> divideDetRDB - -convertMon -> calcFlatBg -monBackWavMin -> calcFlatBg -monBackWavMax -> calcFlatBg -calcFlatBg -> intMon -monIntWavMin -> intMon -monIntWavMax -> intMon - -divideDetRDB -> divideDetMon -intMon -> divideDetMon -divideDetMon -> outputWS - -{rank=same; groupDet; groupDetRDB; cropMonWS} -{rank=same; convertDet; convertDB; convertMon} -{rank=same; monIntWavMin; monIntWavMax} -{rank=same; divideDetRDB; intMon} -{rank=same; monBackWavMin; monBackWavMax} +{rank=same; wavMin; wavMax; checkSumInLam2} } diff --git a/docs/source/diagrams/ReflectometryReductionOne_DirectBeamCorrection-v2_wkflw.dot b/docs/source/diagrams/ReflectometryReductionOne_DirectBeamCorrection-v2_wkflw.dot new file mode 100644 index 0000000000000000000000000000000000000000..9a8df6882c49890465ca02c29222be660f4a31af --- /dev/null +++ b/docs/source/diagrams/ReflectometryReductionOne_DirectBeamCorrection-v2_wkflw.dot @@ -0,0 +1,39 @@ +digraph ReflectometryReductionOne { +splines=line +label = "\n" +rankdir = TB; + $global_style + +subgraph params { + $param_style + inputWS [label="InputWorkspace", group=gmain] + outputWS [label="DirectBeamWorkspace", group=gmain] + regionOfDirectBeam [label="RegionOf-\nDirectBeam"] +} + +subgraph decisions { + $decision_style +} + +subgraph algorithms { + $algorithm_style + convertDB [label="ConvertUnits\n(AlignBins = True)", group=gmain] + groupDetRDB [label="GroupDetectors", group=gmain] +} + +subgraph processes { + $process_style +} + +subgraph values { + $value_style +} + +inputWS -> groupDetRDB + +regionOfDirectBeam -> groupDetRDB +groupDetRDB -> convertDB + +convertDB -> outputWS + +} diff --git a/docs/source/diagrams/ReflectometryReductionOne_HighLvl-v2_wkflw.dot b/docs/source/diagrams/ReflectometryReductionOne_HighLvl-v2_wkflw.dot index 333f6bc94e490e57e8670e93660bce7da5e4fcef..6efddbcc1ca89271e507f8d2ee38f10db3ee3791 100644 --- a/docs/source/diagrams/ReflectometryReductionOne_HighLvl-v2_wkflw.dot +++ b/docs/source/diagrams/ReflectometryReductionOne_HighLvl-v2_wkflw.dot @@ -5,27 +5,24 @@ label = "\n" subgraph params { $param_style inputWS [label="InputWorkspace"] - wavMin [label="WavelengthMin", group=gwav] - wavMax [label="WavelengthMax", group=gwav] outputWSWL [label="OutputWorkspaceWavelength"] outputWSFinal [label="OutputWorkspace"] } subgraph decisions { $decision_style - checkXUnit [label="X axis in λ?"] + checkSumDone [label="Reduction required?"] } subgraph algorithms { $algorithm_style - cropWav [label="CropWorkspace", group=g1] } subgraph processes { $process_style - convertUnits [label="Convert to λ,\noptionally sum in λ, and\nnormalize by monitors"] + convertUnits [label="Convert to λ\nSum in λ\nNormalize by monitors"] applyCorrTrans [label="Apply transmission\n corrections"] - sumInQ [label="Optionally sum in Q"] + sumInQ [label="Sum in Q"] convertMom [label="Convert to momentum\ntransfer"] } @@ -33,14 +30,11 @@ subgraph values { $value_style } -inputWS -> checkXUnit -checkXUnit -> cropWav [label="Yes"] -checkXUnit -> convertUnits [label="No"] -convertUnits -> cropWav -wavMin -> cropWav -wavMax -> cropWav +inputWS -> checkSumDone +checkSumDone -> applyCorrTrans [label="No"] +checkSumDone -> convertUnits [label="Yes"] +convertUnits -> applyCorrTrans -cropWav -> applyCorrTrans applyCorrTrans -> sumInQ sumInQ -> outputWSWL diff --git a/docs/source/diagrams/ReflectometryReductionOne_MonitorCorrection-v2_wkflw.dot b/docs/source/diagrams/ReflectometryReductionOne_MonitorCorrection-v2_wkflw.dot new file mode 100644 index 0000000000000000000000000000000000000000..8e20ec4fcfd06c9c99fcb0c12fc6ed481f76a06a --- /dev/null +++ b/docs/source/diagrams/ReflectometryReductionOne_MonitorCorrection-v2_wkflw.dot @@ -0,0 +1,55 @@ +digraph ReflectometryReductionOne { +splines=line +label = "\n" +rankdir = TB; + $global_style + +subgraph params { + $param_style + inputWS [label="InputWorkspace", group=gmain] + outputWS [label="MonitorWorkspace", group=gmain] + monitorIndex [label="I0MonitorIndex"] + monIntWavMax [label="MonitorIntegration-\nWavelengthMax"] + monIntWavMin [label="MonitorIntegration-\nWavelengthMin"] + monBackWavMin [label="MonitorBackground-\nWavelengthMin"] + monBackWavMax [label="MonitorBackground-\nWavelengthMax"] +} + +subgraph decisions { + $decision_style +} + +subgraph algorithms { + $algorithm_style + convertMon [label="ConvertUnits\n(AlignBins = True)", group=gmon] + cropMonWS [label="CropWorkspace", group=gmon] + calcFlatBg [label="CalculateFlatBackground", group=gmon] + intMon [label="Integration", group=gmon] +} + +subgraph processes { + $process_style +} + +subgraph values { + $value_style +} + +inputWS -> cropMonWS + +monitorIndex -> cropMonWS +cropMonWS -> convertMon + +convertMon -> calcFlatBg + +monBackWavMin -> calcFlatBg +monBackWavMax -> calcFlatBg +calcFlatBg -> intMon + +monIntWavMin -> intMon +monIntWavMax -> intMon +intMon -> outputWS + +{rank=same; monIntWavMin; monIntWavMax} +{rank=same; monBackWavMin; monBackWavMax} +} diff --git a/docs/source/diagrams/ReflectometryReductionOne_SumInQ-v2_wkflw.dot b/docs/source/diagrams/ReflectometryReductionOne_SumInQ-v2_wkflw.dot index 9f02efbcbe6a78ae543009b4036eedb2112c9aed..654828d1bc7187471e32d912ac20591ada19018a 100644 --- a/docs/source/diagrams/ReflectometryReductionOne_SumInQ-v2_wkflw.dot +++ b/docs/source/diagrams/ReflectometryReductionOne_SumInQ-v2_wkflw.dot @@ -4,23 +4,29 @@ label = "\n" subgraph params { $param_style - inputWorkspace [label="OutputWorkspaceWavelength", group=g1] + inputWorkspace [label="OutputWorkspaceWavelength"] outputWorkspaceWav [label="OutputWorkspaceWavelength"] + procCommands [label="ProcessingInstructions"] + wavMin [label="WavelengthMin"] + wavMax [label="WavelengthMax"] } subgraph decisions { $decision_style - checkSumInQ [label="Sum in Q and input X axis was not in λ?"] + checkSumInQ [label="Sum in Q?"] + checkSumDone [label="Reduction required?"] } subgraph algorithms { $algorithm_style + cropWav [label="CropWorkspace"] } subgraph processes { $process_style - projectCounts [label=<Project input counts to λ<sub>v</sub> at 2θ<sub>R</sub>>] + projectCounts [label=<Project input counts to λ<sub>v</sub>>] sumInQ [label=<Sum in λ<sub>v</sub>>] + projectMinMax [label=<Convert crop range to λ<sub>v</sub>>] } subgraph values { @@ -28,10 +34,24 @@ subgraph values { } inputWorkspace -> checkSumInQ -checkSumInQ -> projectCounts [label="Yes"] + checkSumInQ -> outputWorkspaceWav [label="No"] +checkSumInQ -> checkSumDone [label="Yes"] + +checkSumDone -> projectCounts [label="Yes"] +checkSumDone -> projectMinMax [label="No"] + +procCommands -> projectCounts projectCounts -> sumInQ -sumInQ -> outputWorkspaceWav + +wavMin -> projectMinMax +wavMax -> projectMinMax +sumInQ -> projectMinMax + +projectMinMax -> cropWav +cropWav -> outputWorkspaceWav + +{rank=same; wavMin; wavMax} } diff --git a/docs/source/release/v3.11.0/reflectometry.rst b/docs/source/release/v3.11.0/reflectometry.rst index adaee54729b17dd94e807b39649b30f8223abc69..709724662d82a02a4c0ec5b541ecb9df2a852a49 100644 --- a/docs/source/release/v3.11.0/reflectometry.rst +++ b/docs/source/release/v3.11.0/reflectometry.rst @@ -5,9 +5,13 @@ Reflectometry Changes .. contents:: Table of Contents :local: -ConvertToReflectometryQ ------------------------ +Algorithms +---------- +- The following bugs have been fixed in the summation in Q functionality in :ref:`algm-ReflectometryReductionOne`: + - the incorrect angle was being used in the final conversion to Q in the divergent beam case + - the input was being cropped, causing loss of counts +- A new property, ``Diagnostics``, has been added to :ref:`algm-ReflectometryReductionOne` to allow the output of additional interim workspaces for debug purposes. Reflectometry Reduction Interface ---------------------------------