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)) {
308 const auto &det = spectrumInfo.detector(workspaceIndex);
311 std::vector<double> L2Ds(numVolumeElements, 0.0);
314 const auto wavelengths =
m_inputWS->points(workspaceIndex);
317 const auto LinearCoefAbs = material.linearAbsorpCoef(wavelengths.cbegin(), wavelengths.cend());
319 auto &output = outws->mutableY(workspaceIndex);
321 for (int64_t wvBinsIndex = 0; wvBinsIndex < specSize; wvBinsIndex +=
m_xStep) {
325 pairWiseSum(A1, A2, -LinearCoefAbs[wvBinsIndex], distGraber, LS1s, L12s, L2Ds, 0, numVolumeElements);
329 output[wvBinsIndex] = totScatterCoeff / (4 * M_PI) * (A2 / A1);
333 std::ostringstream msg_debug;
334 msg_debug <<
"Det_" << workspaceIndex <<
"@spectrum_" << wvBinsIndex <<
'\n'
335 <<
"\trho = " <<
rho <<
", sigma_s = " << sigma_s <<
'\n'
336 <<
"\tA1 = " << A1 <<
'\n'
337 <<
"\tA2 = " << A2 <<
'\n'
338 <<
"\tms_factor = " << output[wvBinsIndex] <<
'\n';
343 if (
m_xStep > 1 && wvBinsIndex +
m_xStep >= specSize && wvBinsIndex + 1 != specSize) {
344 wvBinsIndex = specSize -
m_xStep - 1;
351 auto histNew = outws->histogram(workspaceIndex);
352 interpolateLinearInplace(histNew,
m_xStep);
353 outws->setHistogram(workspaceIndex, histNew);
373 const auto &sample =
m_inputWS->sample();
374 const auto &sampleMaterial = sample.getShape().material();
375 const auto &containerMaterial = sample.getEnvironment().getContainer().material();
378 const auto &sampleShape = sample.getShape();
379 const auto &containerShape = sample.getEnvironment().getContainer();
389 const int64_t numVolumeElements = numVolumeElementsSample + numVolumeElementsContainer;
390 g_log.
information() <<
"numVolumeElementsSample=" << numVolumeElementsSample
391 <<
", numVolumeElementsContainer=" << numVolumeElementsContainer <<
"\n";
402 std::vector<double> LS1_container(numVolumeElements, 0.0);
403 std::vector<double> LS1_sample(numVolumeElements, 0.0);
404 calculateLS1s(distGraberContainer, distGraberSample, LS1_container, LS1_sample, containerShape, sampleShape);
420 const int64_t len_l12 = numVolumeElements * (numVolumeElements - 1) / 2;
421 std::vector<double> L12_container(len_l12, 0.0);
422 std::vector<double> L12_sample(len_l12, 0.0);
423 calculateL12s(distGraberContainer, distGraberSample, L12_container, L12_sample, containerShape, sampleShape);
425 for (
size_t i = 0; i < size_t(numVolumeElements); ++i) {
426 for (
size_t j = i + 1; j < size_t(numVolumeElements); ++j) {
427 const auto idx = calcLinearIdxFromUpperTriangular(numVolumeElements, i, j);
428 const auto l12 = L12_container[idx] + L12_sample[idx];
430 g_log.
notice() <<
"L12_container(" << i <<
"," << j <<
")=" << L12_container[idx] <<
'\n'
431 <<
"L12_sample(" << i <<
"," << j <<
")=" << L12_sample[idx] <<
'\n';
438 std::vector<double> elementVolumes(distGraberContainer.
m_elementVolumes.begin(),
440 elementVolumes.insert(elementVolumes.end(), distGraberSample.
m_elementVolumes.begin(),
443 for (
size_t i = 0; i < elementVolumes.size(); ++i) {
444 if (elementVolumes[i] < 1e-16) {
445 g_log.
notice() <<
"Element_" << i <<
" has near zero volume: " << elementVolumes[i] <<
'\n';
462 const double unit_scaling = 1e2;
463 const double rho_sample = sampleMaterial.numberDensityEffective();
464 const double sigma_s_sample = sampleMaterial.totalScatterXSection();
465 const double rho_container = containerMaterial.numberDensityEffective();
466 const double sigma_s_container = containerMaterial.totalScatterXSection();
467 const double totScatterCoef_container = rho_container * sigma_s_container * unit_scaling;
468 const double totScatterCoef_sample = rho_sample * sigma_s_sample * unit_scaling;
471 const auto &spectrumInfo =
m_inputWS->spectrumInfo();
472 const auto numHists =
static_cast<int64_t
>(
m_inputWS->getNumberHistograms());
473 const auto specSize =
static_cast<int64_t
>(
m_inputWS->blocksize());
474 Progress prog(
this, 0.0, 1.0, numHists);
477 for (int64_t workspaceIndex = 0; workspaceIndex < numHists; ++workspaceIndex) {
480 if (!spectrumInfo.hasDetectors(workspaceIndex)) {
481 g_log.
information() <<
"Spectrum " << workspaceIndex <<
" does not have a detector defined for it\n";
484 if (spectrumInfo.isMasked(workspaceIndex)) {
487 const auto &det = spectrumInfo.detector(workspaceIndex);
491 std::vector<double> L2D_container(numVolumeElements, 0.0);
492 std::vector<double> L2D_sample(numVolumeElements, 0.0);
493 calculateL2Ds(distGraberContainer, distGraberSample, det, L2D_container, L2D_sample, containerShape, sampleShape);
496 const auto wavelengths =
m_inputWS->points(workspaceIndex);
497 const auto sampleLinearCoefAbs = sampleMaterial.linearAbsorpCoef(wavelengths.cbegin(), wavelengths.cend());
498 const auto containerLinearCoefAbs = containerMaterial.linearAbsorpCoef(wavelengths.cbegin(), wavelengths.cend());
500 auto &output = outws->mutableY(workspaceIndex);
501 for (int64_t wvBinsIndex = 0; wvBinsIndex < specSize; wvBinsIndex +=
m_xStep) {
507 -containerLinearCoefAbs[wvBinsIndex], -sampleLinearCoefAbs[wvBinsIndex],
508 numVolumeElementsContainer, numVolumeElements,
509 totScatterCoef_container, totScatterCoef_sample,
511 LS1_container, LS1_sample,
512 L12_container, L12_sample,
513 L2D_container, L2D_sample,
514 0, numVolumeElements);
516 output[wvBinsIndex] = (A2 / A1) / (4.0 * M_PI);
520 std::ostringstream msg_debug;
521 msg_debug <<
"Det_" << workspaceIndex <<
"@spectrum_" << wvBinsIndex <<
'\n'
522 <<
"-containerLinearCoefAbs[wvBinsIndex] = " << -containerLinearCoefAbs[wvBinsIndex] <<
'\n'
523 <<
"-sampleLinearCoefAbs[wvBinsIndex] = " << -sampleLinearCoefAbs[wvBinsIndex] <<
'\n'
524 <<
"numVolumeElementsContainer = " << numVolumeElementsContainer <<
'\n'
525 <<
"numVolumeElements = " << numVolumeElements <<
'\n'
526 <<
"totScatterCoef_container = " << totScatterCoef_container <<
'\n'
527 <<
"totScatterCoef_sample = " << totScatterCoef_sample <<
'\n'
528 <<
"\tA1 = " << A1 <<
'\n'
529 <<
"\tA2 = " << A2 <<
'\n'
530 <<
"\tms_factor = " << output[wvBinsIndex] <<
'\n';
535 if (
m_xStep > 1 && wvBinsIndex +
m_xStep >= specSize && wvBinsIndex + 1 != specSize) {
536 wvBinsIndex = specSize -
m_xStep - 1;
542 auto histNew = outws->histogram(workspaceIndex);
543 interpolateLinearInplace(histNew,
m_xStep);
544 outws->setHistogram(workspaceIndex, histNew);
561 std::vector<double> &LS1s,
563 const auto &sourcePos =
m_inputWS->getInstrument()->getSource()->getPos();
567 for (int64_t idx = 0; idx < numVolumeElements; ++idx) {
569 const auto vec = getDirection(pos, sourcePos);
571 trackerLS1.reset(pos,
vec);
572 trackerLS1.clearIntersectionResults();
573 LS1s[idx] = getDistanceInsideObject(shape, trackerLS1);
589 std::vector<double> &LS1sContainer,
590 std::vector<double> &LS1sSample,
602 const int64_t numVolumeElements = numVolumeElementsSample + numVolumeElementsContainer;
603 const auto sourcePos =
m_inputWS->getInstrument()->getSource()->getPos();
605 for (int64_t idx = 0; idx < numVolumeElements; ++idx) {
606 const auto pos = idx < numVolumeElementsContainer
609 const auto vec = getDirection(pos, sourcePos);
611 trackerLS1.reset(pos,
vec);
612 trackerLS1.clearIntersectionResults();
613 LS1sContainer[idx] = getDistanceInsideObject(shapeContainer, trackerLS1);
614 trackerLS1.reset(pos,
vec);
615 trackerLS1.clearIntersectionResults();
616 LS1sSample[idx] = getDistanceInsideObject(shapeSample, trackerLS1);
619 std::ostringstream msg_debug;
620 msg_debug <<
"idx=" << idx <<
", pos=" << pos <<
", vec=" <<
vec <<
'\n';
621 if (idx < numVolumeElementsContainer) {
622 msg_debug <<
"Container element " << idx <<
'\n';
624 msg_debug <<
"Sample element " << idx - numVolumeElementsContainer <<
'\n';
626 msg_debug <<
"LS1_container=" << LS1sContainer[idx] <<
", LS1_sample=" << LS1sSample[idx] <<
'\n';
640 std::vector<double> &L12s,
649 for (int64_t indexTo = 0; indexTo < numVolumeElements; ++indexTo) {
654 for (int64_t indexFrom = indexTo + 1; indexFrom < numVolumeElements; ++indexFrom) {
660 const int64_t idx = calcLinearIdxFromUpperTriangular(numVolumeElements, indexTo, indexFrom);
663 const V3D unitVector = getDirection(posFrom, posTo);
666 track.
reset(posFrom, unitVector);
668 const auto rayLengthOne1 = getDistanceInsideObject(shape, track);
670 track.
reset(posTo, unitVector);
672 const auto rayLengthOne2 = getDistanceInsideObject(shape, track);
676 L12s[idx] = checkzero(rayLengthOne1 - rayLengthOne2);
686 std::vector<double> &L12sContainer,
687 std::vector<double> &L12sSample,
692 const int64_t numVolumeElements = numVolumeElementsSample + numVolumeElementsContainer;
708 for (int64_t indexTo = 0; indexTo < numVolumeElements; ++indexTo) {
711 const auto posTo = indexTo < numVolumeElementsContainer
717 for (int64_t indexFrom = indexTo + 1; indexFrom < numVolumeElements; ++indexFrom) {
718 const int64_t idx = calcLinearIdxFromUpperTriangular(numVolumeElements, indexTo, indexFrom);
719 const auto posFrom = indexFrom < numVolumeElementsContainer
722 const V3D unitVector = getDirection(posFrom, posTo);
726 track.
reset(posFrom, unitVector);
727 const auto rayLen1_container = getDistanceInsideObject(shapeContainer, track);
729 track.
reset(posFrom, unitVector);
730 const auto rayLen1_sample = getDistanceInsideObject(shapeSample, track);
732 track.
reset(posTo, unitVector);
733 const auto rayLen2_container = getDistanceInsideObject(shapeContainer, track);
735 track.
reset(posTo, unitVector);
736 const auto rayLen2_sample = getDistanceInsideObject(shapeSample, track);
738 L12sContainer[idx] = checkzero(rayLen1_container - rayLen2_container);
739 L12sSample[idx] = checkzero(rayLen1_sample - rayLen2_sample);
755 const IDetector &detector, std::vector<double> &L2Ds,
758 if (detector.
nDets() > 1) {
762 detector.
getPhi() * RAD2DEG);
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,
784 if (detector.
nDets() > 1) {
788 detector.
getPhi() * RAD2DEG);
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)
#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.
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 IDetector &detector, 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
virtual Kernel::V3D getPos() const =0
Get the position of the IComponent. Tree structure is traverse through the.
Interface class for detector objects.
virtual double getPhi() const =0
Gives the phi of this detector object in radians.
virtual std::size_t nDets() const =0
Get the number of physical detectors this object represents.
virtual double getTwoTheta(const Kernel::V3D &observer, const Kernel::V3D &axis) const =0
Gives the angle of this detector object with respect to an axis.
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.