22#include "MantidHistogramData/Interpolate.h"
30using namespace Geometry;
31using namespace Kernel;
34using HistogramData::interpolateLinearInplace;
40constexpr int64_t MAX_INTEGRATION_LENGTH{1000};
42static constexpr double RAD2DEG = 180.0 / M_PI;
44inline int64_t findMiddle(
const int64_t start,
const int64_t stop) {
45 auto half =
static_cast<int64_t
>(floor(.5 * (
static_cast<double>(stop - start))));
49inline size_t calcLinearIdxFromUpperTriangular(
const size_t N,
const size_t row_idx,
const size_t col_idx) {
52 assert(row_idx < col_idx);
53 return N * (N - 1) / 2 - (N - row_idx) * (N - row_idx - 1) / 2 + col_idx - row_idx - 1;
57inline const V3D getDirection(
const V3D &posInitial,
const V3D &posFinal) {
return normalize(posFinal - posInitial); }
60inline double getDistanceInsideObject(
const IObject &shape,
Track &track) {
68inline double checkzero(
const double x) {
return std::abs(
x) < std::numeric_limits<float>::min() ? 0.0 :
x; }
77 auto wsValidator = std::make_shared<CompositeValidator>();
84 "The X values for the input workspace must be in units of wavelength");
86 auto positiveInt = std::make_shared<BoundedValidator<int64_t>>();
87 positiveInt->setLower(1);
89 "The number of wavelength points for which the numerical integral is\n"
90 "calculated (default: all points)");
92 auto moreThanZero = std::make_shared<BoundedValidator<double>>();
93 moreThanZero->setLower(0.001);
94 declareProperty(
"ElementSize", 1.0, moreThanZero,
"The size of one side of an integration element cube in mm");
97 "The size of one side of an integration element cube in mm for container."
98 "Default to be the same as ElementSize.");
100 std::vector<std::string> methodOptions{
"SampleOnly",
"SampleAndContainer"};
101 declareProperty(
"Method",
"SampleOnly", std::make_shared<StringListValidator>(methodOptions),
102 "Correction method, use either SampleOnly or SampleAndContainer.");
105 "Output workspace name. "
106 "A Workspace2D containing the correction matrix that can be directly applied to the corresponding "
107 "Event workspace for multiple scattering correction.");
116 std::map<std::string, std::string> result;
122 const auto &sample =
m_inputWS->sample();
123 if (!sample.getShape().hasValidShape()) {
124 result[
"InputWorkspace"] =
"The input workspace must have a valid sample shape";
129 if (method ==
"SampleAndContainer") {
130 const auto &containerShape =
m_inputWS->sample().getEnvironment().getContainer();
131 if (!containerShape.hasValidShape()) {
132 result[
"Method"] =
"SampleAndContainer requires a valid container shape.";
149 if (method ==
"SampleOnly") {
154 ws_sampleOnly->setYUnit(
"");
155 ws_sampleOnly->setDistribution(
true);
156 ws_sampleOnly->setYUnitLabel(
"Multiple Scattering Correction factor");
158 const auto &sampleShape =
m_inputWS->sample().getShape();
161 const std::string outWSName =
getProperty(
"OutputWorkspace");
162 std::vector<std::string> names;
163 names.emplace_back(outWSName +
"_sampleOnly");
164 API::AnalysisDataService::Instance().addOrReplace(names.back(), ws_sampleOnly);
168 group->setProperty(
"InputWorkspaces", names);
169 group->setProperty(
"OutputWorkspace", outWSName);
177 }
else if (method ==
"SampleAndContainer") {
184 ws_containerOnly->setYUnit(
"");
185 ws_containerOnly->setDistribution(
true);
186 ws_containerOnly->setYUnitLabel(
"Multiple Scattering Correction factor");
187 const auto &containerShape =
m_inputWS->sample().getEnvironment().getContainer();
191 ws_sampleAndContainer->setYUnit(
"");
192 ws_sampleAndContainer->setDistribution(
true);
193 ws_sampleAndContainer->setYUnitLabel(
"Multiple Scattering Correction factor");
196 const std::string outWSName =
getProperty(
"OutputWorkspace");
197 std::vector<std::string> names;
198 names.emplace_back(outWSName +
"_containerOnly");
199 API::AnalysisDataService::Instance().addOrReplace(names.back(), ws_containerOnly);
200 names.emplace_back(outWSName +
"_sampleAndContainer");
201 API::AnalysisDataService::Instance().addOrReplace(names.back(), ws_sampleAndContainer);
205 group->setProperty(
"InputWorkspaces", names);
206 group->setProperty(
"OutputWorkspace", outWSName);
214 throw std::invalid_argument(
"Invalid method: " + method);
233 const auto specSize =
static_cast<int64_t
>(
m_inputWS->blocksize());
236 std::ostringstream msg;
237 msg <<
"Numerical integration performed every " <<
m_xStep <<
" wavelength points";
257 const auto material = shape.
material();
267 std::vector<double> LS1s(numVolumeElements, 0.0);
274 const int64_t len_l12 = numVolumeElements * (numVolumeElements - 1) / 2;
275 std::vector<double> L12s(len_l12, 0.0);
286 const double rho = material.numberDensityEffective();
287 const double sigma_s = material.totalScatterXSection();
288 const double unit_scaling = 1e2;
289 const double totScatterCoeff =
rho * sigma_s * unit_scaling;
292 const auto &spectrumInfo =
m_inputWS->spectrumInfo();
293 const auto numHists =
static_cast<int64_t
>(
m_inputWS->getNumberHistograms());
294 const auto specSize =
static_cast<int64_t
>(
m_inputWS->blocksize());
295 Progress prog(
this, 0.0, 1.0, numHists);
298 for (int64_t workspaceIndex = 0; workspaceIndex < numHists; ++workspaceIndex) {
301 if (!spectrumInfo.hasDetectors(workspaceIndex)) {
302 g_log.
information() <<
"Spectrum " << workspaceIndex <<
" does not have a detector defined for it\n";
305 if (spectrumInfo.isMasked(workspaceIndex)) {
310 std::vector<double> L2Ds(numVolumeElements, 0.0);
311 calculateL2Ds(distGraber, spectrumInfo, workspaceIndex, L2Ds, shape);
313 const auto wavelengths =
m_inputWS->points(workspaceIndex);
316 const auto LinearCoefAbs = material.linearAbsorpCoef(wavelengths.cbegin(), wavelengths.cend());
318 auto &output = outws->mutableY(workspaceIndex);
320 for (int64_t wvBinsIndex = 0; wvBinsIndex < specSize; wvBinsIndex +=
m_xStep) {
324 pairWiseSum(A1, A2, -LinearCoefAbs[wvBinsIndex], distGraber, LS1s, L12s, L2Ds, 0, numVolumeElements);
328 output[wvBinsIndex] = totScatterCoeff / (4 * M_PI) * (A2 / A1);
332 std::ostringstream msg_debug;
333 msg_debug <<
"Det_" << workspaceIndex <<
"@spectrum_" << wvBinsIndex <<
'\n'
334 <<
"\trho = " <<
rho <<
", sigma_s = " << sigma_s <<
'\n'
335 <<
"\tA1 = " << A1 <<
'\n'
336 <<
"\tA2 = " << A2 <<
'\n'
337 <<
"\tms_factor = " << output[wvBinsIndex] <<
'\n';
342 if (
m_xStep > 1 && wvBinsIndex +
m_xStep >= specSize && wvBinsIndex + 1 != specSize) {
343 wvBinsIndex = specSize -
m_xStep - 1;
350 auto histNew = outws->histogram(workspaceIndex);
351 interpolateLinearInplace(histNew,
m_xStep);
352 outws->setHistogram(workspaceIndex, histNew);
372 const auto &sample =
m_inputWS->sample();
373 const auto &sampleMaterial = sample.getShape().material();
374 const auto &containerMaterial = sample.getEnvironment().getContainer().material();
377 const auto &sampleShape = sample.getShape();
378 const auto &containerShape = sample.getEnvironment().getContainer();
388 const int64_t numVolumeElements = numVolumeElementsSample + numVolumeElementsContainer;
389 g_log.
information() <<
"numVolumeElementsSample=" << numVolumeElementsSample
390 <<
", numVolumeElementsContainer=" << numVolumeElementsContainer <<
"\n";
401 std::vector<double> LS1_container(numVolumeElements, 0.0);
402 std::vector<double> LS1_sample(numVolumeElements, 0.0);
403 calculateLS1s(distGraberContainer, distGraberSample, LS1_container, LS1_sample, containerShape, sampleShape);
419 const int64_t len_l12 = numVolumeElements * (numVolumeElements - 1) / 2;
420 std::vector<double> L12_container(len_l12, 0.0);
421 std::vector<double> L12_sample(len_l12, 0.0);
422 calculateL12s(distGraberContainer, distGraberSample, L12_container, L12_sample, containerShape, sampleShape);
424 for (
size_t i = 0; i < size_t(numVolumeElements); ++i) {
425 for (
size_t j = i + 1; j < size_t(numVolumeElements); ++j) {
426 const auto idx = calcLinearIdxFromUpperTriangular(numVolumeElements, i, j);
427 const auto l12 = L12_container[idx] + L12_sample[idx];
429 g_log.
notice() <<
"L12_container(" << i <<
"," << j <<
")=" << L12_container[idx] <<
'\n'
430 <<
"L12_sample(" << i <<
"," << j <<
")=" << L12_sample[idx] <<
'\n';
437 std::vector<double> elementVolumes(distGraberContainer.
m_elementVolumes.begin(),
439 elementVolumes.insert(elementVolumes.end(), distGraberSample.
m_elementVolumes.begin(),
442 for (
size_t i = 0; i < elementVolumes.size(); ++i) {
443 if (elementVolumes[i] < 1e-16) {
444 g_log.
notice() <<
"Element_" << i <<
" has near zero volume: " << elementVolumes[i] <<
'\n';
461 const double unit_scaling = 1e2;
462 const double rho_sample = sampleMaterial.numberDensityEffective();
463 const double sigma_s_sample = sampleMaterial.totalScatterXSection();
464 const double rho_container = containerMaterial.numberDensityEffective();
465 const double sigma_s_container = containerMaterial.totalScatterXSection();
466 const double totScatterCoef_container = rho_container * sigma_s_container * unit_scaling;
467 const double totScatterCoef_sample = rho_sample * sigma_s_sample * unit_scaling;
470 const auto &spectrumInfo =
m_inputWS->spectrumInfo();
471 const auto numHists =
static_cast<int64_t
>(
m_inputWS->getNumberHistograms());
472 const auto specSize =
static_cast<int64_t
>(
m_inputWS->blocksize());
473 Progress prog(
this, 0.0, 1.0, numHists);
476 for (int64_t workspaceIndex = 0; workspaceIndex < numHists; ++workspaceIndex) {
479 if (!spectrumInfo.hasDetectors(workspaceIndex)) {
480 g_log.
information() <<
"Spectrum " << workspaceIndex <<
" does not have a detector defined for it\n";
483 if (spectrumInfo.isMasked(workspaceIndex)) {
489 std::vector<double> L2D_container(numVolumeElements, 0.0);
490 std::vector<double> L2D_sample(numVolumeElements, 0.0);
491 calculateL2Ds(distGraberContainer, distGraberSample, spectrumInfo, workspaceIndex, L2D_container, L2D_sample,
492 containerShape, sampleShape);
495 const auto wavelengths =
m_inputWS->points(workspaceIndex);
496 const auto sampleLinearCoefAbs = sampleMaterial.linearAbsorpCoef(wavelengths.cbegin(), wavelengths.cend());
497 const auto containerLinearCoefAbs = containerMaterial.linearAbsorpCoef(wavelengths.cbegin(), wavelengths.cend());
499 auto &output = outws->mutableY(workspaceIndex);
500 for (int64_t wvBinsIndex = 0; wvBinsIndex < specSize; wvBinsIndex +=
m_xStep) {
506 -containerLinearCoefAbs[wvBinsIndex], -sampleLinearCoefAbs[wvBinsIndex],
507 numVolumeElementsContainer, numVolumeElements,
508 totScatterCoef_container, totScatterCoef_sample,
510 LS1_container, LS1_sample,
511 L12_container, L12_sample,
512 L2D_container, L2D_sample,
513 0, numVolumeElements);
515 output[wvBinsIndex] = (A2 / A1) / (4.0 * M_PI);
519 std::ostringstream msg_debug;
520 msg_debug <<
"Det_" << workspaceIndex <<
"@spectrum_" << wvBinsIndex <<
'\n'
521 <<
"-containerLinearCoefAbs[wvBinsIndex] = " << -containerLinearCoefAbs[wvBinsIndex] <<
'\n'
522 <<
"-sampleLinearCoefAbs[wvBinsIndex] = " << -sampleLinearCoefAbs[wvBinsIndex] <<
'\n'
523 <<
"numVolumeElementsContainer = " << numVolumeElementsContainer <<
'\n'
524 <<
"numVolumeElements = " << numVolumeElements <<
'\n'
525 <<
"totScatterCoef_container = " << totScatterCoef_container <<
'\n'
526 <<
"totScatterCoef_sample = " << totScatterCoef_sample <<
'\n'
527 <<
"\tA1 = " << A1 <<
'\n'
528 <<
"\tA2 = " << A2 <<
'\n'
529 <<
"\tms_factor = " << output[wvBinsIndex] <<
'\n';
534 if (
m_xStep > 1 && wvBinsIndex +
m_xStep >= specSize && wvBinsIndex + 1 != specSize) {
535 wvBinsIndex = specSize -
m_xStep - 1;
541 auto histNew = outws->histogram(workspaceIndex);
542 interpolateLinearInplace(histNew,
m_xStep);
543 outws->setHistogram(workspaceIndex, histNew);
560 std::vector<double> &LS1s,
562 const auto &sourcePos =
m_inputWS->getInstrument()->getSource()->getPos();
566 for (int64_t idx = 0; idx < numVolumeElements; ++idx) {
568 const auto vec = getDirection(pos, sourcePos);
570 trackerLS1.reset(pos,
vec);
571 trackerLS1.clearIntersectionResults();
572 LS1s[idx] = getDistanceInsideObject(shape, trackerLS1);
588 std::vector<double> &LS1sContainer,
589 std::vector<double> &LS1sSample,
601 const int64_t numVolumeElements = numVolumeElementsSample + numVolumeElementsContainer;
602 const auto sourcePos =
m_inputWS->getInstrument()->getSource()->getPos();
604 for (int64_t idx = 0; idx < numVolumeElements; ++idx) {
605 const auto pos = idx < numVolumeElementsContainer
608 const auto vec = getDirection(pos, sourcePos);
610 trackerLS1.reset(pos,
vec);
611 trackerLS1.clearIntersectionResults();
612 LS1sContainer[idx] = getDistanceInsideObject(shapeContainer, trackerLS1);
613 trackerLS1.reset(pos,
vec);
614 trackerLS1.clearIntersectionResults();
615 LS1sSample[idx] = getDistanceInsideObject(shapeSample, trackerLS1);
618 std::ostringstream msg_debug;
619 msg_debug <<
"idx=" << idx <<
", pos=" << pos <<
", vec=" <<
vec <<
'\n';
620 if (idx < numVolumeElementsContainer) {
621 msg_debug <<
"Container element " << idx <<
'\n';
623 msg_debug <<
"Sample element " << idx - numVolumeElementsContainer <<
'\n';
625 msg_debug <<
"LS1_container=" << LS1sContainer[idx] <<
", LS1_sample=" << LS1sSample[idx] <<
'\n';
639 std::vector<double> &L12s,
648 for (int64_t indexTo = 0; indexTo < numVolumeElements; ++indexTo) {
653 for (int64_t indexFrom = indexTo + 1; indexFrom < numVolumeElements; ++indexFrom) {
659 const int64_t idx = calcLinearIdxFromUpperTriangular(numVolumeElements, indexTo, indexFrom);
662 const V3D unitVector = getDirection(posFrom, posTo);
665 track.
reset(posFrom, unitVector);
667 const auto rayLengthOne1 = getDistanceInsideObject(shape, track);
669 track.
reset(posTo, unitVector);
671 const auto rayLengthOne2 = getDistanceInsideObject(shape, track);
675 L12s[idx] = checkzero(rayLengthOne1 - rayLengthOne2);
685 std::vector<double> &L12sContainer,
686 std::vector<double> &L12sSample,
691 const int64_t numVolumeElements = numVolumeElementsSample + numVolumeElementsContainer;
707 for (int64_t indexTo = 0; indexTo < numVolumeElements; ++indexTo) {
710 const auto posTo = indexTo < numVolumeElementsContainer
716 for (int64_t indexFrom = indexTo + 1; indexFrom < numVolumeElements; ++indexFrom) {
717 const int64_t idx = calcLinearIdxFromUpperTriangular(numVolumeElements, indexTo, indexFrom);
718 const auto posFrom = indexFrom < numVolumeElementsContainer
721 const V3D unitVector = getDirection(posFrom, posTo);
725 track.
reset(posFrom, unitVector);
726 const auto rayLen1_container = getDistanceInsideObject(shapeContainer, track);
728 track.
reset(posFrom, unitVector);
729 const auto rayLen1_sample = getDistanceInsideObject(shapeSample, track);
731 track.
reset(posTo, unitVector);
732 const auto rayLen2_container = getDistanceInsideObject(shapeContainer, track);
734 track.
reset(posTo, unitVector);
735 const auto rayLen2_sample = getDistanceInsideObject(shapeSample, track);
737 L12sContainer[idx] = checkzero(rayLen1_container - rayLen2_container);
738 L12sSample[idx] = checkzero(rayLen1_sample - rayLen2_sample);
769 TwoToDetector.
reset(elementPos, getDirection(elementPos, detectorPos));
772 L2Ds[i] = getDistanceInsideObject(shape, TwoToDetector);
779 std::vector<double> &container_L2Ds,
780 std::vector<double> &sample_L2Ds,
793 const int64_t numVolumeElements = numVolumeElementsSample + numVolumeElementsContainer;
803 for (int64_t idx = 0; idx < numVolumeElements; ++idx) {
804 const auto pos = idx < numVolumeElementsContainer
807 const auto vec = getDirection(pos, detectorPos);
809 trackerL2D.reset(pos,
vec);
810 trackerL2D.clearIntersectionResults();
811 container_L2Ds[idx] = getDistanceInsideObject(shapeContainer, trackerL2D);
812 trackerL2D.reset(pos,
vec);
813 trackerL2D.clearIntersectionResults();
814 sample_L2Ds[idx] = getDistanceInsideObject(shapeSample, trackerL2D);
819 const double linearCoefAbs,
821 const std::vector<double> &LS1s,
822 const std::vector<double> &L12s,
823 const std::vector<double> &L2Ds,
824 const int64_t startIndex,
const int64_t endIndex)
const {
825 if (endIndex - startIndex > MAX_INTEGRATION_LENGTH) {
826 int64_t middle = findMiddle(startIndex, endIndex);
829 pairWiseSum(A1, A2, linearCoefAbs, distGraber, LS1s, L12s, L2Ds, startIndex, middle);
830 pairWiseSum(A1, A2, linearCoefAbs, distGraber, LS1s, L12s, L2Ds, middle, endIndex);
835 for (int64_t i = startIndex; i < endIndex; ++i) {
837 double exponent = (LS1s[i] + L2Ds[i]) * linearCoefAbs;
838 A1 += exp(exponent) * elementVolumes[i];
841 for (int64_t j = 0; j < int64_t(nElements); ++j) {
847 size_t idx_l12 = i < j ? calcLinearIdxFromUpperTriangular(nElements, i, j)
848 : calcLinearIdxFromUpperTriangular(nElements, j, i);
850 const auto l12 = L12s[idx_l12];
852 exponent = (LS1s[i] + L12s[idx_l12] + L2Ds[j]) * linearCoefAbs;
853 a2 += exp(exponent) * elementVolumes[j] / (L12s[idx_l12] * L12s[idx_l12]);
856 A2 += a2 * elementVolumes[i];
862 double &A1,
double &A2,
863 const double linearCoefAbsContainer,
const double linearCoefAbsSample,
864 const int64_t numVolumeElementsContainer,
const int64_t numVolumeElementsTotal,
865 const double totScatterCoefContainer,
866 const double totScatterCoefSample,
867 const std::vector<double> &elementVolumes,
868 const std::vector<double> &LS1sContainer,
const std::vector<double> &LS1sSample,
869 const std::vector<double> &L12sContainer,
const std::vector<double> &L12sSample,
870 const std::vector<double> &L2DsContainer,
const std::vector<double> &L2DsSample,
871 const int64_t startIndex,
const int64_t endIndex)
const {
872 if (endIndex - startIndex > MAX_INTEGRATION_LENGTH) {
873 int64_t middle = findMiddle(startIndex, endIndex);
875 pairWiseSum(A1, A2, linearCoefAbsContainer, linearCoefAbsSample, numVolumeElementsContainer, numVolumeElementsTotal,
876 totScatterCoefContainer, totScatterCoefSample, elementVolumes, LS1sContainer, LS1sSample, L12sContainer,
877 L12sSample, L2DsContainer, L2DsSample, startIndex, middle);
878 pairWiseSum(A1, A2, linearCoefAbsContainer, linearCoefAbsSample, numVolumeElementsContainer, numVolumeElementsTotal,
879 totScatterCoefContainer, totScatterCoefSample, elementVolumes, LS1sContainer, LS1sSample, L12sContainer,
880 L12sSample, L2DsContainer, L2DsSample, middle, endIndex);
883 for (int64_t i = startIndex; i < endIndex; ++i) {
884 const double factor_i = i > numVolumeElementsContainer ? totScatterCoefSample : totScatterCoefContainer;
886 double exponent = (LS1sContainer[i] + L2DsContainer[i]) * linearCoefAbsContainer +
887 (LS1sSample[i] + L2DsSample[i]) * linearCoefAbsSample;
888 A1 += exp(exponent) * factor_i * elementVolumes[i];
891 for (int64_t j = 0; j < numVolumeElementsTotal; ++j) {
896 const double factor_j = j > numVolumeElementsContainer ? totScatterCoefSample : totScatterCoefContainer;
898 size_t idx_l12 = i < j ? calcLinearIdxFromUpperTriangular(numVolumeElementsTotal, i, j)
899 : calcLinearIdxFromUpperTriangular(numVolumeElementsTotal, j, i);
900 const double l12 = L12sContainer[idx_l12] + L12sSample[idx_l12];
902 exponent = (LS1sContainer[i] + L12sContainer[idx_l12] + L2DsContainer[j]) * linearCoefAbsContainer +
903 (LS1sSample[i] + L12sSample[idx_l12] + L2DsSample[j]) * linearCoefAbsSample;
904 a2 += exp(exponent) * factor_j * elementVolumes[j] / (l12 * l12);
907 A2 += a2 * factor_i * elementVolumes[i];
#define DECLARE_ALGORITHM(classname)
std::map< DeltaEMode::Type, std::string > index
#define PARALLEL_START_INTERRUPT_REGION
Begins a block to skip processing is the algorithm has been interupted Note the end of the block if n...
#define PARALLEL_END_INTERRUPT_REGION
Ends a block to skip processing is the algorithm has been interupted Note the start of the block if n...
#define PARALLEL_FOR_IF(condition)
Empty definitions - to enable set your complier to enable openMP.
#define PARALLEL_CHECK_INTERRUPT_REGION
Adds a check after a Parallel region to see if it was interupted.
std::vector< T > const * vec
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
virtual std::shared_ptr< Algorithm > createChildAlgorithm(const std::string &name, const double startProgress=-1., const double endProgress=-1., const bool enableLogging=true, const int &version=-1)
Create a Child Algorithm.
bool isDefault(const std::string &name) const
A validator which checks that a workspace has a valid instrument.
Helper class for reporting progress from algorithms.
A validator which checks that sample has the required properties.
API::SpectrumInfo is an intermediate step towards a SpectrumInfo that is part of Instrument-2....
double twoTheta(const size_t index) const
Returns the scattering angle 2 theta in radians (angle w.r.t.
Kernel::V3D position(const size_t index) const
Returns the position of the spectrum with given index.
const SpectrumDefinition & spectrumDefinition(const size_t index) const
Returns a const reference to the SpectrumDefinition of the spectrum.
double phi(const size_t index) const
Returns the angle of the spectrum position about the lab-frame z axis, atan2(y, x),...
A property class for workspaces.
A validator which checks that the unit of the workspace referred to by a WorkspaceProperty is the exp...
MultipleScatteringCorrectionDistGraber : This is a helper class to calculate the distance from source...
size_t m_numVolumeElements
The number of volume elements.
std::vector< double > m_elementVolumes
Cached element volumes.
std::vector< Kernel::V3D > m_elementPositions
Cached element positions.
void cacheLS1(const Mantid::Kernel::V3D &beamDirection)
pre-calculate the distance from source to L1 for all the voxels in the sample
void calculateLS1s(const MultipleScatteringCorrectionDistGraber &distGraber, std::vector< double > &LS1s, const Geometry::IObject &shape) const
compute LS1s within given shape for single component case
void exec() override
execute the algorithm
void calculateSingleComponent(const API::MatrixWorkspace_sptr &outws, const Geometry::IObject &shape, const double elementSize)
calculate the correction factor per detector for sample only case
void parseInputs()
parse and assign corresponding values from input properties
void pairWiseSum(double &A1, double &A2, const double linearCoefAbs, const MultipleScatteringCorrectionDistGraber &distGraber, const std::vector< double > &LS1s, const std::vector< double > &L12s, const std::vector< double > &L2Ds, const int64_t startIndex, const int64_t endIndex) const
double m_sampleElementSize
The size of the integration element for sample in meters.
void calculateSampleAndContainer(const API::MatrixWorkspace_sptr &outws)
calculate the multiple scattering factor (0, 1) for sample and container case
API::MatrixWorkspace_sptr m_inputWS
A pointer to the input workspace.
void calculateL2Ds(const MultipleScatteringCorrectionDistGraber &distGraber, const API::SpectrumInfo &spectrumInfo, const size_t index, std::vector< double > &L2Ds, const Geometry::IObject &shape) const
Calculate distance between exiting element to the detector for single component case.
Kernel::V3D m_beamDirection
The direction of the beam.
int64_t m_num_lambda
The number of points in wavelength, the rest is interpolated linearly.
int64_t m_xStep
The step in bin number between adjacent points for linear interpolation.
void init() override
interface initialisation method
std::map< std::string, std::string > validateInputs() override
validate the inputs
void calculateL12s(const MultipleScatteringCorrectionDistGraber &distGraber, std::vector< double > &L12s, const Geometry::IObject &shape)
calculate L12 for single component case
double m_containerElementSize
the size of the integration element for container in meters
IObject : Interface for geometry objects.
virtual int interceptSurface(Geometry::Track &) const =0
virtual const Kernel::Material & material() const =0
Defines a track as a start point and a direction.
void clearIntersectionResults()
Clear the current set of intersection results.
double totalDistInsideObject() const
Returns the sum of all the links distInsideObject in the track.
void reset(const Kernel::V3D &startPoint, const Kernel::V3D &direction)
Set a starting point and direction.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void notice(const std::string &msg)
Logs at notice level.
void information(const std::string &msg)
Logs at information level.
void report()
Increments the loop counter by 1, then sends the progress notification on behalf of its algorithm.
void spherical(const double R, const double theta, const double phi) noexcept
Sets the vector position based on spherical coordinates.
double norm() const noexcept
std::shared_ptr< WorkspaceGroup > WorkspaceGroup_sptr
shared pointer to Mantid::API::WorkspaceGroup
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::enable_if< std::is_pointer< Arg >::value, bool >::type threadSafe(Arg workspace)
Thread-safety check Checks the workspace to ensure it is suitable for multithreaded access.
MANTID_KERNEL_DLL V3D normalize(V3D v)
Normalizes a V3D.
constexpr int EMPTY_INT() noexcept
Returns what we consider an "empty" integer within a property.
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
@ Input
An input workspace.
@ Output
An output workspace.