27using namespace DataObjects;
28using namespace Kernel;
32using Mantid::HistogramData::HistogramY;
33using Mantid::HistogramData::Points;
36using namespace Geometry;
41static const double CHEBYSHEV[] = {
43 0.730284, -0.249987, 0.019448, -0.000006, 0.000249, -0.000004,
44 0.848859, -0.452690, 0.056557, -0.000009, 0.000000, -0.000006,
45 1.133129, -0.749962, 0.118245, -0.000018, -0.001345, -0.000012,
46 1.641112, -1.241639, 0.226247, -0.000045, -0.004821, -0.000030,
47 0.848859, -0.452690, 0.056557, -0.000009, 0.000000, -0.000006,
48 1.000006, -0.821100, 0.166645, -0.012096, 0.000008, -0.000126,
49 1.358113, -1.358076, 0.348199, -0.038817, 0.000022, -0.000021,
50 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
51 1.133129, -0.749962, 0.118245, -0.000018, -0.001345, -0.000012,
52 1.358113, -1.358076, 0.348199, -0.038817, 0.000022, -0.000021,
53 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
54 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
55 1.641112, -1.241639, 0.226247, -0.000045, -0.004821, -0.000030,
56 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
57 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
58 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
61static const int Z_size = 36;
64static const double Z_initial[] = {
65 1.0, 0.8488263632, 1.0, 1.358122181, 2.0, 3.104279270, 0.8488263632, 0.0, 0.0, 0.0, 0.0, 0.0,
66 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.358122181, 0.0, 0.0, 0.0, 0.0, 0.0,
67 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.104279270, 0.0, 0.0, 0.0, 0.0, 0.0};
69static const double LAMBDA_REF = 1.81;
73static const double COEFF4 = 1.1967;
74static const double COEFF5 = -0.8667;
82 return "CorrectionFunctions\\AbsorptionCorrections";
90 auto wsValidator = std::make_shared<CompositeValidator>();
96 "The name of the input workspace.");
99 "Basename of the output workspace group for corrections."
100 "Absorption suffix = '_abs'. "
101 "Multiple Scattering suffix = '_ms'. ");
102 declareProperty(
"AttenuationXSection", 2.8,
103 "Coefficient 1, absorption cross "
104 "section / 1.81 if not set with "
105 "SetSampleMaterial");
106 declareProperty(
"ScatteringXSection", 5.1,
107 "Coefficient 3, total scattering "
108 "cross section if not set with "
109 "SetSampleMaterial");
110 declareProperty(
"SampleNumberDensity", 0.0721,
"Coefficient 2, density if not set with SetSampleMaterial");
111 declareProperty(
"CylinderSampleRadius", 0.3175,
"Sample radius, in cm");
112 declareProperty(
"Absorption",
true,
"If True then calculates the absorption correction.",
Direction::Input);
113 declareProperty(
"MultipleScattering",
true,
"If True then calculates the multiple scattering correction.",
123 double radius =
getProperty(
"CylinderSampleRadius");
124 double coeff1 =
getProperty(
"AttenuationXSection");
125 double coeff2 =
getProperty(
"SampleNumberDensity");
128 const bool msOn =
getProperty(
"MultipleScattering");
129 const Material &sampleMaterial = inputWksp->sample().getMaterial();
140 NeutronAtom neutron(0, 0, 0.0, 0.0, coeff3, 0.0, coeff3, coeff1);
141 auto shape = std::shared_ptr<IObject>(
142 inputWksp->sample().getShape().cloneWithMaterial(
Material(
"SetInMultipleScattering", neutron, coeff2)));
143 inputWksp->mutableSample().setShape(shape);
145 g_log.
debug() <<
"radius=" << radius <<
" coeff1=" << coeff1 <<
" coeff2=" << coeff2 <<
" coeff3=" << coeff3 <<
"\n";
148 const auto NUM_HIST =
static_cast<int64_t
>(inputWksp->getNumberHistograms());
150 if (instrument ==
nullptr)
151 throw std::runtime_error(
"Failed to find instrument attached to InputWorkspace");
154 if (source ==
nullptr)
155 throw std::runtime_error(
"Failed to find source in the instrument for InputWorkspace");
156 if (sample ==
nullptr)
157 throw std::runtime_error(
"Failed to find sample in the instrument for InputWorkspace");
160 Progress prog(
this, 0.0, 1.0, NUM_HIST);
167 const auto &spectrumInfo = inputWksp->spectrumInfo();
171 if (!spectrumInfo.hasDetectors(
index))
172 throw std::runtime_error(
"Failed to find detector");
173 if (spectrumInfo.isMasked(
index))
175 const double tth_rad = spectrumInfo.twoTheta(
index);
179 absWksp->setSharedX(
index, inputWksp->sharedX(
index));
180 const auto lambdas = inputWksp->points(
index);
181 auto &
y = absWksp->mutableY(
index);
187 msWksp->setSharedX(
index, inputWksp->sharedX(
index));
188 const auto lambdas = inputWksp->points(
index);
189 auto &
y = msWksp->mutableY(
index);
198 absWksp->setDistribution(
true);
199 absWksp->setYUnit(
"");
200 absWksp->setYUnitLabel(
"Attenuation factor");
202 msWksp->setDistribution(
true);
203 msWksp->setYUnit(
"");
204 msWksp->setYUnitLabel(
"Multiple scattering factor");
207 const std::string group_prefix =
getPropertyValue(
"OutputWorkspaceBaseName");
208 auto outputGroup = std::make_shared<API::WorkspaceGroup>();
211 std::string ws_name = group_prefix + std::string(
"_abs");
212 AnalysisDataService::Instance().addOrReplace(ws_name, absWksp);
213 outputGroup->addWorkspace(absWksp);
220 std::string ws_name = group_prefix + std::string(
"_ms");
221 AnalysisDataService::Instance().addOrReplace(ws_name, msWksp);
222 outputGroup->addWorkspace(msWksp);
227 setProperty(
"OutputWorkspaceBaseName", outputGroup);
232vector<double> createZ(
const double angle_rad) {
233 vector<double>
Z(Z_initial, Z_initial + Z_size);
235 const double theta_rad = angle_rad * .5;
239 for (
int i = 1; i <= 4; i++) {
240 for (
int j = 1; j <= 4; j++) {
244 J = 1 + l + 6 * (i - 1) + 6 * 4 * (j - 1);
245 sum = CHEBYSHEV[J - 1];
247 for (l = 1; l <= 5; l++) {
248 J = 1 + l + 6 * (i - 1) + 6 * 4 * (j - 1);
249 sum = sum + CHEBYSHEV[J - 1] * cos(l * theta_rad);
262double AttFac(
const double sigir,
const double sigsr,
const vector<double> &
Z) {
266 for (
size_t i = 0; i <= 5; i++) {
268 for (
size_t j = 0; j <= 5; j++) {
270 size_t J = 1 + i + 6 * j;
271 att = att +
Z[J - 1] * facts * facti;
272 facts = -facts * sigsr /
static_cast<double>(j + 1);
275 facti = -facti * sigir /
static_cast<double>(i + 1);
280double calculate_abs_factor(
const double radius,
const double Q2,
const double sigsct,
const vector<double> &
Z,
281 const double wavelength) {
283 const double sigabs = Q2 * wavelength;
284 const double sigir = (sigabs + sigsct) * radius;
290 const double sigsr = sigir;
292 return AttFac(sigir, sigsr,
Z);
295double calculate_ms_factor(
const double radius,
const double Q2,
const double sigsct,
const vector<double> &
Z,
296 const double wavelength) {
298 const double sigabs = Q2 * wavelength;
299 const double sigir = (sigabs + sigsct) * radius;
305 const double sigsr = sigir;
307 const double delta = COEFF4 * sigir + COEFF5 * sigir * sigir;
308 const double deltp = (
delta * sigsct) / (sigsct + sigabs);
310 double temp = AttFac(sigir, sigsr,
Z);
311 return (deltp / temp);
331 const double coeff1,
const double coeff2,
332 const double coeff3,
const Points &wavelength,
335 const size_t NUM_Y = y_val.size();
336 bool is_histogram =
false;
337 if (wavelength.size() == NUM_Y + 1)
339 else if (wavelength.size() == NUM_Y)
340 is_histogram =
false;
342 throw std::runtime_error(
"Data is neither historgram or density");
345 vector<double>
Z = createZ(angle_deg);
347 const double Q2 = coeff1 * coeff2;
348 const double sigsct = coeff2 * coeff3;
350 for (
size_t j = 0; j < NUM_Y; j++) {
351 double wl_val = wavelength[j];
353 wl_val = .5 * (wl_val + wavelength[j + 1]);
355 y_val[j] = calculate_abs_factor(radius, Q2, sigsct,
Z, wl_val);
360 const double coeff1,
const double coeff2,
361 const double coeff3,
const Points &wavelength,
364 const size_t NUM_Y = y_val.size();
365 bool is_histogram =
false;
366 if (wavelength.size() == NUM_Y + 1)
368 else if (wavelength.size() == NUM_Y)
369 is_histogram =
false;
371 throw std::runtime_error(
"Data is neither historgram or density");
374 vector<double>
Z = createZ(angle_deg);
376 const double Q2 = coeff1 * coeff2;
377 const double sigsct = coeff2 * coeff3;
379 for (
size_t j = 0; j < NUM_Y; j++) {
380 double wl_val = wavelength[j];
382 wl_val = .5 * (wl_val + wavelength[j + 1]);
384 y_val[j] = calculate_ms_factor(radius, Q2, sigsct,
Z, wl_val);
389 const std::string &ylabel)
const {
393 outputWS->setDistribution(
true);
394 outputWS->setYUnit(
"");
395 outputWS->setYUnitLabel(ylabel);
402 alg->setProperty(
"InputWorkspace",
workspace);
404 return alg->getProperty(
"OutputWorkspace");
411 alg->setLogging(
false);
412 alg->setProperty(
"Workspace",
workspace);
#define DECLARE_ALGORITHM(classname)
IPeaksWorkspace_sptr workspace
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::shared_ptr< Algorithm > createChildAlgorithm(const std::string &name, const double startProgress=-1., const double endProgress=-1., const bool enableLogging=true, const int &version=-1) override
Create a Child Algorithm.
Kernel::IPropertyManager::TypedValue getProperty(const std::string &name) const override
Get the property held by this object.
std::string getPropertyValue(const std::string &name) const override
Get the property held by this object.
A validator which checks that a workspace has a valid instrument.
Helper class for reporting progress from algorithms.
A property class for workspaces.
A validator which checks that the unit of the workspace referred to by a WorkspaceProperty is the exp...
void exec() override
Execute the algorithm.
int version() const override
Algorithm's version for identification overriding a virtual method.
const std::string name() const override
Algorithm's name for identification overriding a virtual method.
void calculate_abs_correction(const double angle_deg, const double radius, const double coeff1, const double coeff2, const double coeff3, const HistogramData::Points &wavelength, HistogramData::HistogramY &y_val)
CalculateCarpenterSampleCorrection correction calculation.
void calculate_ms_correction(const double angle_deg, const double radius, const double coeff1, const double coeff2, const double coeff3, const HistogramData::Points &wavelength, HistogramData::HistogramY &y_val)
const std::string category() const override
Algorithm's category for identification overriding a virtual method.
void deleteWorkspace(const API::MatrixWorkspace_sptr &workspace)
void init() override
Initialize the properties to default values.
API::MatrixWorkspace_sptr createOutputWorkspace(const API::MatrixWorkspace_sptr &inputWS, const std::string &) const
API::MatrixWorkspace_sptr setUncertainties(const API::MatrixWorkspace_sptr &workspace)
This class is intended to fulfill the design specified in <https://github.com/mantidproject/documents...
void debug(const std::string &msg)
Logs at debug level.
void information(const std::string &msg)
Logs at information level.
A material is defined as being composed of a given element, defined as a PhysicalConstants::NeutronAt...
double numberDensity() const
Get the number density.
double absorbXSection(const double lambda=PhysicalConstants::NeutronAtom::ReferenceLambda) const
Get the absorption cross section at a given wavelength in barns.
const std::string & name() const
Returns the name of the material.
double totalScatterXSection() const
Return the total scattering cross section for a given wavelength in barns.
void report()
Increments the loop counter by 1, then sends the progress notification on behalf of its algorithm.
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
Kernel::Logger g_log("DetermineSpinStateOrder")
std::shared_ptr< EventWorkspace > EventWorkspace_sptr
shared pointer to the EventWorkspace class
std::shared_ptr< const IComponent > IComponent_const_sptr
Typdef of a shared pointer to a const IComponent.
std::shared_ptr< const Instrument > Instrument_const_sptr
Shared pointer to an const instrument object.
MANTID_KERNEL_DLL bool equals(T const x, T const y)
Test for equality of doubles using compiler-defined precision.
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.
A namespace containing physical constants that are required by algorithms and unit routines.
@ Input
An input workspace.
@ Output
An output workspace.
Structure to store neutronic scattering information for the various elements.