Mantid
Loading...
Searching...
No Matches
CalculatePlaczek.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2021 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
7
10#include "MantidAPI/Axis.h"
13#include "MantidAPI/Run.h"
14#include "MantidAPI/Sample.h"
21#include "MantidKernel/Atom.h"
26#include "MantidKernel/Unit.h"
27
28#include <utility>
29
30namespace Mantid::Algorithms {
31
35using PhysicalConstants::E_mev_toNeutronWavenumberSq; // in [meV*Angstrom^2]
36
37namespace { // anonymous namespace
38
39// calculate summation term w/ neutron mass over molecular mass ratio
40// NOTE:
41// - this is directly borrowed from the original CalculatePlaczekSelfScattering
42std::pair<double, double> calculateSummationTerm(const Kernel::Material &material) {
43 std::pair<double, double> s;
44 // add together the weighted sum
45 const auto &formula = material.chemicalFormula();
46 auto sumLambda_first = [](double sum, const auto &formula_unit) {
47 return sum + formula_unit.multiplicity * formula_unit.atom->neutron.tot_scatt_xs / formula_unit.atom->mass;
48 };
49 auto sumLambda_second = [](double sum, const auto &formula_unit) {
50 const double mass_sq = formula_unit.atom->mass * formula_unit.atom->mass;
51 return sum + formula_unit.multiplicity * formula_unit.atom->neutron.tot_scatt_xs / mass_sq;
52 };
53 const double unnormalizedTermFirst = std::accumulate(formula.begin(), formula.end(), 0.0, sumLambda_first);
54 const double unnormalizedTermSecond = std::accumulate(formula.begin(), formula.end(), 0.0, sumLambda_second);
55
56 // neutron mass converted to atomic mass comes out of the sum
58 constexpr double neutronMassSq = neutronMass * neutronMass;
59 // normalizing by totalStoich (number of atoms) comes out of the sum
60 const double totalStoich = material.totalAtoms();
61 // converting scattering cross section to scattering length square comes out of the sum
62 s.first = neutronMass * unnormalizedTermFirst / (4. * M_PI * totalStoich);
63 s.second = neutronMassSq * unnormalizedTermSecond / (4. * M_PI * totalStoich);
64
65 return s;
66}
67
68} // anonymous namespace
69
70// Register the algorithm into the AlgorithmFactory
71DECLARE_ALGORITHM(CalculatePlaczek)
72
73//----------------------------------------------------------------------------------------------
74// NOTE: the template seems to prefer having the implemenation in the cpp file
75
76
77const std::string CalculatePlaczek::name() const { return "CalculatePlaczek"; }
78
80int CalculatePlaczek::version() const { return 1; }
81
83const std::string CalculatePlaczek::category() const { return "CorrectionFunctions"; }
84
86const std::string CalculatePlaczek::summary() const {
87 return "Calculate 1st or 2nd order Placzek correction factors using given workspace and incident spectrums.";
88}
89
91const std::vector<std::string> CalculatePlaczek::seeAlso() const {
92 return {"CalculatePlaczekSelfScattering", "He3TubeEfficiency"};
93}
94
95//----------------------------------------------------------------------------------------------
99 // Mandatory properties
100 // 1. Input workspace should have
101 // - a valid instrument
102 // - a sample with chemical formula
103 auto wsValidator = std::make_shared<Mantid::Kernel::CompositeValidator>();
104 wsValidator->add<Mantid::API::InstrumentValidator>();
106 declareProperty(std::make_unique<API::WorkspaceProperty<API::MatrixWorkspace>>("InputWorkspace", "",
107 Kernel::Direction::Input, wsValidator),
108 "Raw diffraction data workspace for associated correction to be "
109 "calculated for. Workspace must have instrument and sample data.");
110 // 2. Incident spectra should have a unit of wavelength
111 auto inspValidator = std::make_shared<Mantid::Kernel::CompositeValidator>();
112 inspValidator->add<Mantid::API::WorkspaceUnitValidator>("Wavelength");
114 "IncidentSpectra", "", Kernel::Direction::Input, inspValidator),
115 "Workspace of fitted incident spectrum with its derivatives (1st &| 2nd).");
116
117 // Optional properties
119 "EfficiencySpectra", "", Kernel::Direction::Input, API::PropertyMode::Optional),
120 "Workspace of efficiency spectrum with its derivatives (1st &| 2nd)."
121 "Default (not specified) will use LambdaD to calculate the efficiency spectrum.");
122 auto lambdadValidator = std::make_shared<Kernel::BoundedValidator<double>>();
123 lambdadValidator->setExclusive(true);
124 lambdadValidator->setLower(0.0);
126 "LambdaD", 1.44, lambdadValidator,
127 "Reference wavelength in Angstrom, related to detector efficient coefficient alpha."
128 "The coefficient used to generate a generic detector efficiency curve,"
129 "eps = 1 - exp(1 - alpha*lambda), where alpha is 1/LambdaD."
130 "Default is set to 1.44 for ISIS 3He detectors and 1/0.83 for ISIS:LAD circa 1990 scintillator detectors.");
131 declareProperty("CrystalDensity", EMPTY_DBL(), "The crystalographic density of the sample material.");
132 auto orderValidator = std::make_shared<Kernel::BoundedValidator<int>>(1, 2);
133 declareProperty("Order", 1, orderValidator, "Placzek correction order (1 or 2), default to 1 (self scattering).");
134 declareProperty("SampleTemperature", EMPTY_DBL(),
135 "Sample temperature in Kelvin."
136 "The input property is prioritized over the temperature recorded in the sample log."
137 "The temperature is necessary for computing second order correction.");
138 declareProperty("ScaleByPackingFraction", true, "Scale the correction value by packing fraction.");
139
140 // Output property
142 std::make_unique<API::WorkspaceProperty<API::MatrixWorkspace>>("OutputWorkspace", "", Kernel::Direction::Output),
143 "Workspace with the Placzek scattering correction factors.");
144}
145
146//----------------------------------------------------------------------------------------------
152std::map<std::string, std::string> CalculatePlaczek::validateInputs() {
153 std::map<std::string, std::string> issues;
154 const API::MatrixWorkspace_sptr inWS = getProperty("InputWorkspace");
155 const API::SpectrumInfo specInfo = inWS->spectrumInfo();
156 const int order = getProperty("Order");
157
158 // Case0:missing detector info
159 if (specInfo.size() == 0) {
160 issues["InputWorkspace"] = "Input workspace does not have detector information";
161 }
162
163 // Case1: cannot locate sample temperature
164 if (isDefault("SampleTemperature") && (order == 2)) {
165 const auto run = inWS->run();
166 Mantid::Kernel::Property *sampleTempLog = NULL;
167 // ORNL logs use SampleTemp
168 if (run.hasProperty("SampleTemp")) {
169 sampleTempLog = run.getLogData("SampleTemp");
170 }
171 // ISIS logs use sample_temp
172 if (run.hasProperty("sample_temp")) {
173 sampleTempLog = run.getLogData("sample_temp");
174 }
175 if (!sampleTempLog) {
176 issues["SampleTemperature"] = "Cannot locate sample temperature in the run.";
177 }
178 }
179
180 // Case2: check number of spectra in flux workspace match required order
181 const API::MatrixWorkspace_sptr incidentWS = getProperty("IncidentSpectra");
182 const int64_t numHist = incidentWS->spectrumInfo().size();
183 if (order == 2) {
184 // we need three spectra here
185 if (numHist < 3) {
186 issues["IncidentSpectra"] = "Need three spectra here for second order calculation.";
187 } else {
188 // if there are the correct number of spectra make sure all are not empty
189 if (incidentWS->readY(0).empty()) {
190 issues["IncidentSpectra"] = "Flux is empty";
191 }
192 if (incidentWS->readY(1).empty()) {
193 issues["IncidentSpectra"] = "First order derivate of the incident spectrum is empty";
194 }
195 if (incidentWS->readY(2).empty()) {
196 issues["IncidentSpectra"] = "Second order derivate of the incident spectrum is empty";
197 }
198 }
199 } else {
200 // we are at first order here
201 if (numHist < 2) {
202 issues["IncidentSpectra"] = "Need two spectra here for first order calculation.";
203 } else {
204 // if there are the correct number of spectra make sure all are not empty
205 if (incidentWS->readY(0).empty()) {
206 issues["IncidentSpectra"] = "Flux is empty";
207 }
208 if (incidentWS->readY(1).empty()) {
209 issues["IncidentSpectra"] = "First order derivate of the incident spectrum is empty";
210 }
211 }
212 }
213
214 // Case3: check number of spectra in efficiency workspace match required order IF provided
215 const API::MatrixWorkspace_sptr efficiencyWS = getProperty("EfficiencySpectra");
216 if (efficiencyWS) {
217 const int64_t numHistEff = efficiencyWS->spectrumInfo().size();
218 if (order == 2) {
219 // we need three spectra here
220 if (numHistEff < 3) {
221 issues["EfficiencySpectra"] = "Need three spectra here for second order calculation.";
222 } else {
223 // if there are the correct number of spectra make sure all are not empty
224 if (efficiencyWS->readY(0).empty()) {
225 issues["EfficiencySpectra"] = "Detector efficiency is empty";
226 }
227 if (efficiencyWS->readY(1).empty()) {
228 issues["EfficiencySpectra"] = "First order derivate of the efficiency spectrum is empty";
229 }
230 if (efficiencyWS->readY(2).empty()) {
231 issues["EfficiencySpectra"] = "Second order derivate of the efficiency spectrum is empty";
232 }
233 }
234 } else {
235 // we are at first order here
236 if (numHistEff < 2) {
237 issues["EfficiencySpectra"] = "Need two spectra here for first order calculation.";
238 } else {
239 // if there are the correct number of spectra make sure all are not empty
240 if (efficiencyWS->readY(0).empty()) {
241 issues["EfficiencySpectra"] = "Detector efficiency is empty";
242 }
243 if (efficiencyWS->readY(1).empty()) {
244 issues["EfficiencySpectra"] = "First order derivate of the efficiency spectrum is empty";
245 }
246 }
247 }
248 }
249
250 // NOTE: order range check is enforced with validator
251 return issues;
252}
253
254//----------------------------------------------------------------------------------------------
258 // prep input
259 const API::MatrixWorkspace_sptr inWS = getProperty("InputWorkspace");
260 const API::MatrixWorkspace_sptr incidentWS = getProperty("IncidentSpectra");
261 const int order = getProperty("Order");
262 const bool scaleByPackingFraction = getProperty("ScaleByPackingFraction");
263
264 // prep output
265 // build the output workspace
266 // - use instrument information from InputWorkspace
267 // - use the bin Edges from the incident flux
269 DataObjects::create<API::HistoWorkspace>(*inWS, incidentWS->getSpectrum(0).binEdges());
270 outputWS->getAxis(0)->unit() = incidentWS->getAxis(0)->unit();
271 outputWS->setDistribution(true);
272 outputWS->setYUnit("");
273 outputWS->setYUnitLabel("Counts");
274
275 // ---------------------------------------------------------------------------
276 // calculate the Placzek correction (self scattering + optional 2nd order)
277 // ---------------------------------------------------------------------------
278 /* Placzek
279 Original Placzek inelastic correction Ref (for constant wavelength, reactor
280 source): Placzek, Phys. Rev v86, (1952), pp. 377-388 First Placzek
281 correction for time-of-flight, pulsed source (also shows reactor eqs.):
282 Powles, Mol. Phys., v6 (1973), pp.1325-1350
283 Nomenclature and calculation for this program follows Ref:
284 Howe, McGreevy, and Howells, J. Phys.: Condens. Matter v1, (1989), pp.
285 3433-3451 NOTE: Powles's Equation for inelastic self-scattering is equal to
286 Howe's Equation for P(theta) by adding the elastic self-scattering
287 */
288 const auto xLambda = incidentWS->getSpectrum(0).points();
289 // pre-compute the coefficients
290 // - calculate summation term w/ neutron mass over molecular mass ratio
291 const std::pair<double, double> summationTerms = calculateSummationTerm(inWS->sample().getMaterial());
292 const double packingFraction = getPackingFraction(inWS);
293 // NOTE:
294 // - when order==1, we don't care what's inside sampleTemperature.
295 // - when order==2, the value here will be a valid one in K.
296 const double sampleTemperature = getSampleTemperature();
297
298 // NOTE:
299 // The following coefficients are defined in the appendix 1 of
300 // Ref: Howe, McGreevy, and Howells, J. Phys.: Condens. Matter v1, (1989), pp.
301 // doi: 10.1088/0953-8984/1/22/005
302 // The associated analytical forms are given on the second page of
303 // Ref: Howells, W.S., Nuclear Instruments and Methods in Physics Research 223, no. 1 (June 1984): 141–46.
304 // doi: 10.1016/0167-5087(84)90256-4
305 // - 1st order related coefficients
306 const std::vector<double> phi1 = getFluxCoefficient1();
307 const std::vector<double> eps1 = getEfficiencyCoefficient1();
308 // - 2nd order related coefficients
309 const std::vector<double> phi2 = (order == 2) ? getFluxCoefficient2() : std::vector<double>();
310 const std::vector<double> eps2 = (order == 2) ? getEfficiencyCoefficient2() : std::vector<double>();
311
312 // loop over all spectra
313 const API::SpectrumInfo specInfo = inWS->spectrumInfo();
314 const int64_t numHist = specInfo.size();
316 for (int64_t specIndex = 0; specIndex < numHist; specIndex++) {
318 auto &y = outputWS->mutableY(specIndex); // x-axis is directly copied from incident flux
319 // only perform calculation for components that
320 // - is monitor
321 // - at (0,0,0)
322 if (!specInfo.isMonitor(specIndex) && !(specInfo.l2(specIndex) == 0.0)) {
323 Kernel::Units::Wavelength wavelength;
326 double l1 = specInfo.l1();
327 specInfo.getDetectorValues(wavelength, tof, Kernel::DeltaEMode::Elastic, false, specIndex, pmap);
328 double l2 = 0., twoTheta = 0.;
329 if (pmap.find(Kernel::UnitParams::l2) != pmap.end()) {
331 }
332 if (pmap.find(Kernel::UnitParams::twoTheta) != pmap.end()) {
334 }
335 // first order (self scattering) is mandatory, second order is optional
336 // - pre-compute constants that can be cached outside loop
337 const double sinThetaBy2 = sin(twoTheta / 2.0);
338 const double f = l1 / (l1 + l2);
339 wavelength.initialize(specInfo.l1(), 0, pmap);
340 const double kBT = BoltzmannConstant * sampleTemperature; // BoltzmannConstant in meV / K, T in K -> kBT in meV
341 // - convenience variables
342 const double sinHalfAngleSq = sinThetaBy2 * sinThetaBy2;
343 // - loop over all lambda
344 for (size_t xIndex = 0; xIndex < xLambda.size(); xIndex++) {
345 // -- calculate first order correction
346 const double term1 = (f - 1.0) * phi1[xIndex];
347 const double term2 = f * (1.0 - eps1[xIndex]);
348 double inelasticPlaczekCorrection = 2.0 * (term1 + term2 - 3) * sinHalfAngleSq * summationTerms.first;
349 // -- calculate second order correction
350 if (order == 2) {
351 const double k = 2 * M_PI / xLambda[xIndex]; // wave vector in 1/angstrom
352 const double energy = E_mev_toNeutronWavenumberSq * (k * k); // in meV
353 const double kBToverE = kBT / energy; // unitless
354 // NOTE: see the equation A1.15 in Howe et al. The analysis of liquid structure, 1989
355 const double bracket_1 = (8 * f - 9) * (f - 1) * phi1[xIndex] //
356 - 3 * f * (2 * f - 3) * eps1[xIndex] //
357 + 2 * f * (1 - f) * phi1[xIndex] * eps1[xIndex] //
358 + (1 - f) * (1 - f) * phi2[xIndex] //
359 + f * f * eps2[xIndex] //
360 + 3 * (4 * f - 5) * (f - 1);
361 const double P2_part1 = summationTerms.first * (kBToverE / 2.0 + kBToverE * sinHalfAngleSq * bracket_1);
362 const double bracket_2 = (4 * f - 7) * (f - 1) * phi1[xIndex] //
363 + f * (7 - 2 * f) * eps1[xIndex] //
364 + 2 * f * (1 - f) * phi1[xIndex] * eps1[xIndex] //
365 + (1 - f) * (1 - f) * phi2[xIndex] //
366 + f * f * eps2[xIndex] //
367 + (2 * f * f - 7 * f + 8);
368 const double P2_part2 = 2 * sinHalfAngleSq * summationTerms.second * (1 + sinHalfAngleSq * bracket_2);
369 // added to the factor
370 inelasticPlaczekCorrection += P2_part1 + P2_part2;
371 }
372 // -- consolidate
373 y[xIndex] =
374 scaleByPackingFraction ? (1 + inelasticPlaczekCorrection) * packingFraction : inelasticPlaczekCorrection;
375 }
376 } else {
377 for (size_t xIndex = 0; xIndex < xLambda.size(); xIndex++) {
378 y[xIndex] = 0;
379 }
380 }
382 }
384
385 // set output
386 setProperty("OutputWorkspace", outputWS);
387}
388
389//----------------------------------------------------------------------------------------------
397 // get a handle to the material
398 const auto &material = ws->sample().getMaterial();
399
400 // default value is packing fraction
401 double packingFraction = material.packingFraction();
402
403 // see if the user thinks the material wasn't setup right
404 const double crystalDensity = getProperty("CrystalDensity");
405 if (crystalDensity > 0.) {
406 // assume that the number density set in the Material is the effective number density
407 packingFraction = material.numberDensity() / crystalDensity;
408 }
409
410 return packingFraction;
411}
412
419 double sampleTemperature = getProperty("SampleTemperature");
420 const int order = getProperty("Order");
421
422 // get the sample temperature from sample log if not provided by the user
423 // NOTE:
424 // we only need to go the extra mile when we really need a valid sample temperature,
425 // i.e. when calculating the second order correction
426 if (isDefault("SampleTemperature") && (order == 2)) {
427 // get the sample temperature from sample log
428 const API::MatrixWorkspace_sptr inWS = getProperty("InputWorkspace");
429 const auto run = inWS->run();
430 // SampleTemp only valid for ORNL runs
431 if (run.hasProperty("SampleTemp")) {
432 sampleTemperature = run.getPropertyAsSingleValue("SampleTemp");
433 const std::string sampleTempUnit = run.getProperty("SampleTemp")->units();
434 if (sampleTempUnit == "C") {
435 sampleTemperature = sampleTemperature + 273.15; // convert to K
436 }
437 // sample_temp only valid for ISIS runs
438 } else if (run.hasProperty("sample_temp")) {
439 sampleTemperature = run.getPropertyAsSingleValue("sample_temp");
440 const std::string sampleTempUnit = run.getProperty("sample_temp")->units();
441 if (sampleTempUnit == "C") {
442 sampleTemperature = sampleTemperature + 273.15; // convert to K
443 }
444 } else {
445 // the validator should already catch this early on
446 throw std::runtime_error("Sample temperature is not found in the log.");
447 }
448 }
449 return sampleTemperature;
450}
451
458 g_log.information("Compute the flux coefficient phi1.");
459 std::vector<double> phi1;
460
461 const API::MatrixWorkspace_sptr incidentWS = getProperty("IncidentSpectra");
462 const auto xLambda = incidentWS->getSpectrum(0).points();
463 const auto &incident = incidentWS->readY(0);
464 const auto &incidentPrime = incidentWS->readY(1);
465 // phi1 = lambda * phi'(lambda)/phi(lambda)
466 for (size_t i = 0; i < xLambda.size(); i++) {
467 phi1.emplace_back(xLambda[i] * incidentPrime[i] / incident[i]);
468 }
469 return phi1;
470}
471
478 g_log.information("Compute the flux coefficient phi2.");
479 std::vector<double> phi2;
480
481 const API::MatrixWorkspace_sptr incidentWS = getProperty("IncidentSpectra");
482 const auto xLambda = incidentWS->getSpectrum(0).points();
483 const auto &incident = incidentWS->readY(0);
484 const auto &incidentPrime2 = incidentWS->readY(2);
485 // phi2 = lambda^2 * phi''(lambda)/phi(lambda)
486 for (size_t i = 0; i < xLambda.size(); i++) {
487 phi2.emplace_back(xLambda[i] * xLambda[i] * incidentPrime2[i] / incident[i]);
488 }
489 return phi2;
490}
491
499 g_log.information("Compute detector efficiency coefficient 1");
500 std::vector<double> eps1;
501
502 // NOTE: we need the xlambda here to
503 // - compute the coefficient based on an assumed efficiency curve
504 const API::MatrixWorkspace_sptr incidentWS = getProperty("IncidentSpectra");
505 const auto xLambda = incidentWS->getSpectrum(0).points();
506 const API::MatrixWorkspace_sptr efficiencyWS = getProperty("EfficiencySpectra");
507 if (efficiencyWS) {
508 // Use the formula
509 // eps1 = k * eps'/eps, k = 2pi/lambda
510 std::vector<double> eps = efficiencyWS->readY(0);
511 std::vector<double> epsPrime = efficiencyWS->readY(1);
512 for (size_t i = 0; i < xLambda.size(); i++) {
513 double lambda = xLambda[i];
514 double k = 2.0 * M_PI / lambda;
515 double eps_i = (eps[i] + eps[i + 1]) / 2.0;
516 double epsPrime_i = (epsPrime[i] + epsPrime[i + 1]) / 2.0;
517 eps1.emplace_back(k * epsPrime_i / eps_i);
518 }
519 } else {
520 // This is based on an assume efficiency curve from
521 const double LambdaD = getProperty("LambdaD");
522 for (auto x : xLambda) {
523 x /= -LambdaD;
524 eps1.emplace_back(x * exp(x) / (1.0 - exp(x)));
525 }
526 }
527 return eps1;
528}
529
536 g_log.information("Compute detector efficiency coefficient 2");
537 std::vector<double> eps2;
538
539 // NOTE: we need the xlambda here to
540 // - compute the coefficient based on an assumed efficiency curve
541 const API::MatrixWorkspace_sptr incidentWS = getProperty("IncidentSpectra");
542 const auto xLambda = incidentWS->getSpectrum(0).points();
543
544 const API::MatrixWorkspace_sptr efficiencyWS = getProperty("EfficiencySpectra");
545 if (efficiencyWS) {
546 // Use the formula
547 // eps1 = k^2 * eps''/eps, k = 2pi/lambda
548 std::vector<double> eps = efficiencyWS->readY(0);
549 std::vector<double> epsPrime2 = efficiencyWS->readY(2);
550 for (size_t i = 0; i < xLambda.size(); i++) {
551 double lambda = xLambda[i];
552 double k = 2.0 * M_PI / lambda;
553 double eps_i = (eps[i] + eps[i + 1]) / 2.0;
554 double epsPrime2_i = (epsPrime2[i] + epsPrime2[i + 1]) / 2.0;
555 eps2.emplace_back(k * k * epsPrime2_i / eps_i);
556 }
557 } else {
558 // using the analytical formula from the second page of
559 // Ref: Howells, W.S., Nuclear Instruments and Methods in Physics Research 223, no. 1 (June 1984): 141–46.
560 // doi: 10.1016/0167-5087(84)90256-4
561 // DEV NOTE:
562 // The detector efficiency coefficient is denoted with F1 and _2F in the paper instead of the eps1 and eps2
563 // used in the code.
564 const double LambdaD = getProperty("LambdaD");
565 for (auto x : xLambda) {
566 x /= -LambdaD;
567 double eps1 = x * exp(x) / (1.0 - exp(x));
568 eps2.emplace_back((-x - 2.0) * eps1);
569 }
570 }
571 return eps2;
572}
573
574} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
const std::vector< double > * lambda
double energy
Definition: GetAllEi.cpp:157
#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...
Definition: MultiThreaded.h:94
#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.
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
Definition: Algorithm.cpp:1913
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
Kernel::Logger & g_log
Definition: Algorithm.h:451
bool isDefault(const std::string &name) const
Definition: Algorithm.cpp:2084
A validator which checks that a workspace has a valid instrument.
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....
Definition: SpectrumInfo.h:53
bool isMonitor(const size_t index) const
Returns true if the detector(s) associated with the spectrum are monitors.
double l2(const size_t index) const
Returns L2 (distance from sample to spectrum).
size_t size() const
Returns the size of the SpectrumInfo, i.e., the number of spectra.
double l1() const
Returns L1 (distance from source to sample).
void getDetectorValues(const Kernel::Unit &inputUnit, const Kernel::Unit &outputUnit, const Kernel::DeltaEMode::Type emode, const bool signedTheta, int64_t wsIndex, Kernel::UnitParametersMap &pmap) const
Get the detector values relevant to unit conversion for a workspace index.
A property class for workspaces.
A validator which checks that the unit of the workspace referred to by a WorkspaceProperty is the exp...
CalculatePlaczek : Placzek 1st&2nd order correction for inelastic scattering.
std::vector< double > getEfficiencyCoefficient2()
compute the second order detector efficiency coefficient vector
std::map< std::string, std::string > validateInputs() override
validate inputs
const std::string category() const override
Algorithm's category for identification.
void exec() override
Execute the algorithm.
const std::string summary() const override
Algorithm's summary for use in the GUI and help.
const std::vector< std::string > seeAlso() const override
Algorithm's see also for use in the GUI and help.
double getSampleTemperature()
query the sample temperature from input property or sample log
std::vector< double > getFluxCoefficient2()
Compute the flux coefficient for the second order, i.e.
double getPackingFraction(const API::MatrixWorkspace_const_sptr &ws)
compute the packing fraction with given crystal density
std::vector< double > getFluxCoefficient1()
Compute the flux coefficient for the first order, i.e.
int version() const override
Algorithm's version for identification.
std::vector< double > getEfficiencyCoefficient1()
Compute the detector efficiency coefficient based on either given efficiency workspace or a vector de...
void init() override
Initialize the algorithm's properties.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void information(const std::string &msg)
Logs at information level.
Definition: Logger.cpp:105
Base class for properties.
Definition: Property.h:94
void initialize(const double &_l1, const int &_emode, const UnitParametersMap &params)
Initialize the unit to perform conversion using singleToTof() and singleFromTof()
Definition: Unit.cpp:132
Time of flight in microseconds.
Definition: Unit.h:283
Wavelength in Angstrom.
Definition: Unit.h:302
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::unordered_map< UnitParams, double > UnitParametersMap
Definition: Unit.h:30
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.
Definition: MultiThreaded.h:22
static constexpr double BoltzmannConstant
Boltzmann Constant in meV/K Taken from http://physics.nist.gov/cuu/Constants on 10/07/2012.
static constexpr double E_mev_toNeutronWavenumberSq
Transformation coefficient to transform neutron energy into neutron wavevector: K-neutron[m^-10] = sq...
static constexpr double NeutronMass
Mass of the neutron in kg.
static constexpr double AtomicMassUnit
AMU in kg.
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
Definition: EmptyValues.h:43
Generate a tableworkspace to store the calibration results.
STL namespace.
Describes the direction (within an algorithm) of a Property.
Definition: Property.h:50
@ Input
An input workspace.
Definition: Property.h:53
@ Output
An output workspace.
Definition: Property.h:54