/** * Sum counts from the input workspace in lambda along lines of constant Q by * projecting to "virtual lambda" at a reference angle. * * @param detectorWS [in] :: the input workspace in wavelength * @param indices [in] :: an index set defining the foreground histograms * @return :: the single histogram output workspace in wavelength */ API::MatrixWorkspace_sptr ReflectometrySumInQ::sumInQ(const API::MatrixWorkspace &detectorWS, const Indexing::SpectrumIndexSet &indices) { const auto spectrumInfo = detectorWS.spectrumInfo(); const auto refAngles = referenceAngles(spectrumInfo); // Construct the output workspace in virtual lambda API::MatrixWorkspace_sptr IvsLam = constructIvsLamWS(detectorWS, indices, refAngles); auto &outputE = IvsLam->dataE(0); // Loop through each spectrum in the detector group for (auto spIdx : indices) { if (spectrumInfo.isMasked(spIdx) || spectrumInfo.isMonitor(spIdx)) { continue; } // Get the size of this detector in twoTheta const auto twoThetaRange = twoThetaWidth(spIdx, spectrumInfo); // Check X length is Y length + 1 const auto inputBinEdges = detectorWS.binEdges(spIdx); const auto inputCounts = detectorWS.counts(spIdx); const auto inputStdDevs = detectorWS.countStandardDeviations(spIdx); // Create a vector for the projected errors for this spectrum. // (Output Y values can simply be accumulated directly into the output // workspace, but for error values we need to create a separate error // vector for the projected errors from each input spectrum and then // do an overall sum in quadrature.) std::vector<double> projectedE(outputE.size(), 0.0); // Process each value in the spectrum const int ySize = static_cast<int>(inputCounts.size()); for (int inputIdx = 0; inputIdx < ySize; ++inputIdx) { // Do the summation in Q processValue(inputIdx, twoThetaRange, refAngles, inputBinEdges, inputCounts, inputStdDevs, *IvsLam, projectedE); } // Sum errors in quadrature const int eSize = static_cast<int>(outputE.size()); for (int outIdx = 0; outIdx < eSize; ++outIdx) { outputE[outIdx] += projectedE[outIdx] * projectedE[outIdx]; } } // Take the square root of all the accumulated squared errors for this // detector group. Assumes Gaussian errors double (*rs)(double) = std::sqrt; std::transform(outputE.begin(), outputE.end(), outputE.begin(), rs); return IvsLam; }