69using namespace Kernel;
70using namespace Geometry;
72using namespace DataObjects;
76 :
API::
Algorithm(), m_smu(0.), m_amu(0.), m_radius(0.), m_power_th(0.), m_lamda_weight(),
77 m_onlySphericalAbsorption(false), m_returnTransmissionOnly(false), m_useScaleFactors(false) {}
82 auto wsValidator = std::make_shared<InstrumentValidator>();
86 "The X values for the input workspace must be in units of wavelength or TOF");
88 "Output workspace name");
90 auto mustBePositive = std::make_shared<BoundedValidator<double>>();
91 mustBePositive->setLower(0.0);
93 "Linear scattering coefficient in 1/cm. "
94 "If not provided this will be calculated from the "
95 "material cross-section if present (set with SetSampleMaterial)");
97 "Linear absorption coefficient at 1.8 Angstroms in 1/cm. "
98 "If not provided this will be calculated from the "
99 "material cross-section if present (set with SetSampleMaterial)");
101 "Radius of the sample in centimeters. f not provided the "
102 "radius will be taken from the sample shape if it is a sphere "
103 "(set with SetSample).");
105 "Keep the output workspace as an EventWorkspace, if the "
106 "input has events (default).\n"
107 "If false, then the workspace gets converted to a "
108 "Workspace2D histogram.");
110 "All corrections done if false (default).\n"
111 "If true, only the spherical absorption correction.");
113 "Corrections applied to data if false (default).\n"
114 "If true, only return the transmission coefficient.");
117 "No scale factors if false (default).\n"
118 "If true, use scale factors from instrument parameter map.");
124 std::map<std::string, std::string> result;
130 if (!inputWorkspace) {
131 result[
"InputWorkspace"] =
"The InputWorkspace must be a MatrixWorkspace.";
135 const auto &sampleShape = inputWorkspace->sample().getShape();
136 if (!sampleShape.hasValidShape() ||
138 result[
"Radius"] =
"Please supply a radius or provide a workspace with a spherical sample set.";
156 g_log.
warning() <<
"Lorentz Correction was already done for this "
157 "workspace. OnlySphericalAbsorption was changed to "
163 const std::string &unitStr =
m_inputWS->getAxis(0)->unit()->unitID();
184 const auto numHists =
static_cast<int64_t
>(
m_inputWS->getNumberHistograms());
185 const auto specSize =
static_cast<int64_t
>(
m_inputWS->blocksize());
187 throw std::runtime_error(
"Problem in AnvredCorrection::events not binned");
190 const auto &spectrumInfo =
m_inputWS->spectrumInfo();
191 const auto &componentInfo =
m_inputWS->componentInfo();
192 double L1 = spectrumInfo.l1();
194 Progress prog(
this, 0.0, 1.0, numHists);
197 for (int64_t i = 0; i < int64_t(numHists); ++i) {
201 if (!spectrumInfo.hasDetectors(i) || spectrumInfo.isMonitor(i))
209 double L2 =
pmap.at(UnitParams::l2);
210 double scattering =
pmap.at(UnitParams::twoTheta);
214 double pathlength = 0.0;
216 std::string bankName;
218 const auto &det = spectrumInfo.detector(i);
219 bankName = det.getParent()->getParent()->getName();
220 scale_init(inst, componentInfo, L2, depth, pathlength, bankName);
226 const auto &inSpec =
m_inputWS->getSpectrum(i);
227 correctionFactors->setSharedX(i, inSpec.sharedX());
230 const auto &Yin = inSpec.y();
231 const auto &Ein = inSpec.x();
234 auto &
Y = correctionFactors->mutableY(i);
235 auto &E = correctionFactors->mutableE(i);
237 bool muRTooLarge =
false;
238 for (int64_t j = 0; j < specSize; j++) {
245 const auto eventWeight = this->
getEventWeight(lambda, scattering, muRTooLarge);
246 double scaleFactor(eventWeight);
248 scaleFactor =
scale_exec(bankName,
lambda, depth, inst, pathlength, eventWeight);
250 Y[j] = Yin[j] * scaleFactor;
251 E[j] = Ein[j] * scaleFactor;
256 g_log.
warning(
"Absorption correction not accurate for muR > 8 which was exceeded in spectrum index " +
267 API::Run &run = correctionFactors->mutableRun();
270 run.addProperty<
bool>(
"LorentzCorrection",
true,
true);
281 const auto numHists =
static_cast<int64_t
>(
m_inputWS->getNumberHistograms());
282 std::string unitStr =
m_inputWS->getAxis(0)->unit()->unitID();
283 auto correctionFactors = create<EventWorkspace>(*
m_inputWS);
284 correctionFactors->sortAll(
TOF_SORT,
nullptr);
287 g_log.
debug(
"Correcting EventWorkspace in-place.");
292 const auto &spectrumInfo =
eventW->spectrumInfo();
293 const auto &componentInfo =
eventW->componentInfo();
294 double L1 = spectrumInfo.l1();
296 Progress prog(
this, 0.0, 1.0, numHists);
299 for (int64_t i = 0; i < int64_t(numHists); ++i) {
303 correctionFactors->setHistogram(i,
eventW->binEdges(i));
306 if (!spectrumInfo.hasDetectors(i) || spectrumInfo.isMonitor(i))
313 double L2 =
pmap.at(UnitParams::l2);
314 double scattering =
pmap.at(UnitParams::twoTheta);
321 double pathlength = 0.0;
322 std::string bankName;
324 const auto &det = spectrumInfo.detector(i);
325 bankName = det.getParent()->getParent()->getName();
326 scale_init(inst, componentInfo, L2, depth, pathlength, bankName);
330 bool muRTooLarge =
false;
332 for (
auto &ev : events) {
336 if (
"TOF" == unitStr)
344 ev.m_errorSquared =
static_cast<float>(ev.m_errorSquared *
value *
value);
345 ev.m_weight *=
static_cast<float>(
value);
349 g_log.
warning(
"Absorption correction not accurate for muR > 9 cm^-1 which was exceeded in spectrum index " +
353 correctionFactors->getSpectrum(i) += events;
357 eventW->getSpectrum(i).clear();
366 API::Run &run = correctionFactors->mutableRun();
369 run.addProperty<
bool>(
"LorentzCorrection",
true,
true);
370 setProperty(
"OutputWorkspace", std::move(correctionFactors));
386 if (scatterXSection != 0.0) {
394 m_inputWS->sample().getShape().shapeInfo().sphereGeometry().radius * 100;
398 auto shape = std::shared_ptr<IObject>(
399 m_inputWS->sample().getShape().cloneWithMaterial(
Material(
"SetInAnvredCorrection", neutron, 1.0)));
400 m_inputWS->mutableSample().setShape(shape);
404 <<
"LinearAbsorptionCoef = " <<
m_amu <<
" 1/cm\n"
405 <<
"Radius = " <<
m_radius <<
" cm\n"
406 <<
"Power Lorentz corrections = " <<
m_power_th <<
" \n";
436 double sin_theta = std::sin(two_theta / 2);
437 double pix_weight = sin_theta * sin_theta;
439 double event_weight = pix_weight * lamda_w * transinv;
473 throw std::runtime_error(
"muR cannot be negative");
474 }
else if (mur > 8.0) {
478 auto theta = 0.5 * twoth *
radtodeg;
479 if (theta < 0. || theta > 90.) {
480 std::ostringstream s;
482 throw std::runtime_error(
"theta is not in allowed range :" + s.str());
498 auto ith =
static_cast<size_t>(theta / 5.);
501 size_t ncoef =
sizeof pc /
sizeof pc[0];
502 for (
size_t icoef = 0; icoef < ncoef; icoef++) {
503 lnA_1 = lnA_1 * mur +
pc[icoef][ith];
504 lnA_2 = lnA_2 * mur +
pc[icoef][ith + 1];
506 double A1 = std::exp(lnA_1);
507 double sin_th1_sq = std::pow(sin((
static_cast<double>(ith) * 5.0) /
radtodeg), 2);
508 double A2 = std::exp(lnA_2);
509 double sin_th2_sq = std::pow(sin((
static_cast<double>(ith + 1) * 5.0) /
radtodeg), 2);
512 double L1 = (A1 - A2) / (sin_th1_sq - sin_th2_sq);
513 double L0 = A1 - L1 * sin_th1_sq;
516 return 1 / (L0 + L1 * std::pow(sin(theta /
radtodeg), 2));
554 const double L2,
const double depth,
double &pathlength,
555 const std::string &bankName) {
557 const IComponent *det0 = inst->getComponentByName(bankName).get();
558 if (
"CORELLI" == inst->getName())
560 const size_t bankIndex = componentInfo.
indexOfAny(bankName);
561 const auto children = componentInfo.
children(bankIndex);
562 if (!children.empty()) {
568 pathlength = depth / cosA;
574 const double mu = (9.614 *
lambda) + 0.266;
575 const double eff_center = 1.0 - std::exp(-
mu * depth);
576 const double eff_R = 1.0 - exp(-
mu * pathlength);
577 double scaleFactor(eventWeight * eff_center / eff_R);
579 bankName.erase(remove_if(bankName.begin(), bankName.end(), std::not_fn(::isdigit)), bankName.end());
580 if (inst->hasParameter(
"detScale" + bankName))
581 scaleFactor *=
static_cast<double>(inst->getNumberParameter(
"detScale" + bankName)[0]);
#define DECLARE_ALGORITHM(classname)
const std::vector< double > * lambda
double value
The value of the point.
#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.
Base class from which all concrete algorithm classes should be derived.
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
bool hasProperty(const std::string &name) const
Does the property exist on the object.
void addProperty(Kernel::Property *prop, bool overwrite=false)
Add data to the object in the form of a property.
HeldType getPropertyValueAsType(const std::string &name) const
Get the value of a property as the given TYPE.
Helper class for reporting progress from algorithms.
This class stores information regarding an experimental run as a series of log entries.
A property class for workspaces.
double m_smu
linear scattering coefficient in 1/cm
virtual void defineProperties()
A virtual function in which additional properties of an algorithm should be declared.
double m_radius
sample radius in cm
bool m_onlySphericalAbsorption
std::map< std::string, std::string > validateInputs() override
validate inputs
void execEvent()
Event execution code.
virtual void retrieveProperties()
A virtual function in which additional properties should be retrieved into member variables.
double getEventWeight(const double lamda, const double two_theta, bool &muRTooLarge)
Get the weight factor that would be used for an event occuring at the specified wavelength,...
bool m_returnTransmissionOnly
void init() override
Initialisation code.
double m_amu
linear absoprtion coefficient in 1/cm
void cleanup()
Algorithm cleanup.
void exec() override
Execution code.
double absor_sphere(const double twoth, const double wl, bool &muRTooLarge)
function to calculate a spherical absorption correction and tbar.
DataObjects::EventWorkspace_sptr eventW
Shared pointer to the event workspace.
std::vector< double > m_lamda_weight
lmabda weights
double m_power_th
Power of lamda in BuildLamdaWeights.
static double calc_Astar(const double theta, const double mur)
void scale_init(const Geometry::Instrument_const_sptr &inst, const Geometry::ComponentInfo &componentInfo, const double L2, const double depth, double &pathlength, const std::string &bankName)
void BuildLamdaWeights()
Build the list of weights corresponding to different wavelengths.
AnvredCorrection()
(Empty) Constructor
API::MatrixWorkspace_sptr m_inputWS
A pointer to the input workspace.
double scale_exec(std::string &bankName, const double lambda, const double depth, const Geometry::Instrument_const_sptr &inst, const double pathlength, double eventWeight)
void retrieveBaseProperties()
Fetch the properties and set the appropriate member variables.
std::vector< WeightedEventNoTime > & getWeightedEventsNoTime()
Return the list of WeightedEvent contained.
void switchTo(Mantid::API::EventType newType) override
Switch the EventList to use the given EventType (TOF, WEIGHTED, or WEIGHTED_NOTIME)
ComponentInfo : Provides a component centric view on to the instrument.
size_t indexOfAny(const std::string &name) const
const std::vector< size_t > & children(size_t componentIndex) const
const IComponent * componentID(const size_t componentIndex) const
base class for Geometric IComponent
virtual double getDistance(const IComponent &) const =0
Get the distance to another IComponent.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void debug(const std::string &msg)
Logs at debug level.
void notice(const std::string &msg)
Logs at notice level.
void warning(const std::string &msg)
Logs at warning 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.
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.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
double convertSingleFromTOF(const double xvalue, const double &l1, const int &emode, const UnitParametersMap ¶ms)
Convert from the time-of-flight to the concrete unit. TOF is in microseconds.
Time of flight in microseconds.
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
const int NUM_WAVELENGTHS
const double STEPS_PER_ANGSTROM
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.
std::unordered_map< UnitParams, double > UnitParametersMap
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.
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
Generate a tableworkspace to store the calibration results.
std::string to_string(const wide_integer< Bits, Signed > &n)
@ Input
An input workspace.
@ Output
An output workspace.
Structure to store neutronic scattering information for the various elements.
static const double ReferenceLambda
The reference wavelength value for absorption cross sections.