25#include "MantidTypes/SpectrumDefinition.h"
35using namespace Kernel;
37using namespace Geometry;
38using namespace DataObjects;
43const double KSquaredToE = 2.07212466;
45const short NUMCOEFS = 25;
47const double c_eff_f[] = {
48 0.7648360390553052, -0.3700950778935237, 0.1582704090813516, -6.0170218669705407E-02,
49 2.0465515957968953E-02, -6.2690181465706840E-03, 1.7408667184745830E-03, -4.4101378999425122E-04,
50 1.0252117967127217E-04, -2.1988904738111659E-05, 4.3729347905629990E-06, -8.0998753944849788E-07,
51 1.4031240949230472E-07, -2.2815971698619819E-08, 3.4943984983382137E-09, -5.0562696807254781E-10,
52 6.9315483353094009E-11, -9.0261598195695569E-12, 1.1192324844699897E-12, -1.3204992654891612E-13,
53 1.4100387524251801E-14, -8.6430862467068437E-16, -1.1129985821867194E-16, -4.5505266221823604E-16,
54 3.8885561437496108E-16};
56const double c_eff_g[] = {
57 2.033429926215546, -2.3123407369310212E-02, 7.0671915734894875E-03, -7.5970017538257162E-04,
58 7.4848652541832373E-05, 4.5642679186460588E-05, -2.3097291253000307E-05, 1.9697221715275770E-06,
59 2.4115259271262346E-06, -7.1302220919333692E-07, -2.5124427621592282E-07, 1.3246884875139919E-07,
60 3.4364196805913849E-08, -2.2891359549026546E-08, -6.7281240212491156E-09, 3.8292458615085678E-09,
61 1.6451021034313840E-09, -5.5868962123284405E-10, -4.2052310689211225E-10, 4.3217612266666094E-11,
62 9.9547699528024225E-11, 1.2882834243832519E-11, -1.9103066351000564E-11, -7.6805495297094239E-12,
63 1.8568853399347773E-12};
67const double g_helium_prefactor = 2.0 * 143.23 * 3.49416 / 10.0;
73const std::string PRESSURE_PARAM =
"TubePressure";
75const std::string THICKNESS_PARAM =
"TubeThickness";
81 :
Algorithm(), m_inputWS(), m_outputWS(), m_Ei(-1.0), m_ki(-1.0), m_shapeCache(), m_samplePos(),
90 auto val = std::make_shared<CompositeValidator>();
95 "The workspace to correct for detector efficiency");
97 "The name of the workspace in which to store the result. Each histogram "
98 "from the input workspace maps to a histogram in this workspace that has "
99 "just one value which indicates if there was a bad detector.");
100 auto checkEi = std::make_shared<BoundedValidator<double>>();
101 checkEi->setLower(0.0);
103 "The energy of neutrons leaving the source as can be "
104 "calculated by :ref:`algm-GetEi`. If this value is provided, "
105 "uses property value, if it is not present, needs Ei log "
106 "value set on the workspace.");
120 m_ki = std::sqrt(
m_Ei / KSquaredToE);
125 int64_t numHists =
m_inputWS->getNumberHistograms();
126 auto numHists_d =
static_cast<double>(numHists);
127 const auto progStep =
static_cast<int64_t
>(ceil(numHists_d / 100.0));
128 auto const &spectrumInfo =
m_inputWS->spectrumInfo();
131 for (int64_t i = 0; i < numHists; ++i) {
145 if (i % progStep == 0) {
146 progress(
static_cast<double>(i) / numHists_d);
169 if (
m_inputWS->run().hasProperty(
"Ei")) {
170 m_Ei =
m_inputWS->run().getPropertyValueAsType<
double>(
"Ei");
173 throw std::invalid_argument(
"No Ei value has been set or stored within the run information.");
207 const auto yValues =
m_inputWS->y(spectraIn);
208 const auto eValues =
m_inputWS->e(spectraIn);
212 std::vector<double> oneOverWaveVectors(yValues.size());
213 const auto &detectorInfo =
m_inputWS->detectorInfo();
214 const auto &componentInfo =
m_inputWS->componentInfo();
217 for (
const auto &
index : spectrumDefinition) {
218 const auto detIndex =
index.first;
219 const auto pressure = componentInfo.getNumberParameter(detIndex, PRESSURE_PARAM);
220 if (pressure.empty()) {
223 const double atms = pressure.front();
224 const auto thickness = componentInfo.getNumberParameter(detIndex, THICKNESS_PARAM);
225 if (thickness.empty()) {
228 const double wallThickness = thickness.front();
229 double detRadius(0.0);
231 if (!componentInfo.hasValidShape(detIndex)) {
240 Quat rot = detectorInfo.rotation(detIndex);
246 double cosTheta = detAxis.
scalar_prod(vectorFromSample);
247 double sinTheta = std::sqrt(1.0 - cosTheta * cosTheta);
249 const double det_const = g_helium_prefactor * (detRadius - wallThickness) * atms / sinTheta;
251 auto yinItr = yValues.cbegin();
252 auto einItr = eValues.cbegin();
253 auto youtItr = yout.begin();
254 auto eoutItr = eout.begin();
255 auto xItr =
m_inputWS->x(spectraIn).cbegin();
256 auto wavItr = oneOverWaveVectors.begin();
258 for (; youtItr != yout.end(); ++youtItr, ++eoutItr) {
259 if (
index == spectrumDefinition[0]) {
264 const double oneOverWave = *wavItr;
265 const auto nDets(
static_cast<double>(spectrumDefinition.size()));
267 *youtItr += (*yinItr) * factor;
268 *eoutItr += (*einItr) * factor;
287 double energy =
m_Ei - 0.5 * (uppBinBound + loBinBound);
288 double oneOverKSquared = KSquaredToE /
energy;
289 return std::sqrt(oneOverKSquared);
298 const IObject *shape_ptr = &shape;
300 std::map<const Geometry::IObject *, std::pair<double, Kernel::V3D>>::const_iterator it =
m_shapeCache.find(shape_ptr);
305 detRadius = zDist / 2.0;
306 detAxis =
V3D(0, 1, 0);
313 detRadius = yDist / 2.0;
314 detAxis =
V3D(1, 0, 0);
322 detRadius = xDist / 2.0;
323 detAxis =
V3D(0, 0, 1);
328 std::pair<double, V3D> geometry = it->second;
329 detRadius = geometry.first;
330 detAxis = geometry.second;
350 Track track(start, direction);
355 if (track.
count() != 1) {
357 throw std::invalid_argument(
"Fatal error interpreting the shape of a detector");
361 return track.
cbegin()->distInsideObject;
372 return 0.25 * M_PI * alpha *
chebevApprox(0.0, 10.0, c_eff_f, alpha);
375 double y = 1.0 - 18.0 / alpha;
376 return 1.0 -
chebevApprox(-1.0, 1.0, c_eff_g,
y) / (alpha * alpha);
378 double eff_f = 0.25 * M_PI * alpha *
chebevApprox(0.0, 10.0, c_eff_f, alpha);
379 double y = 1.0 - 18.0 / alpha;
380 double eff_g = 1.0 -
chebevApprox(-1.0, 1.0, c_eff_g,
y) / (alpha * alpha);
381 return (10.0 - alpha) * eff_f + (alpha - 9.0) * eff_g;
398 double y = (2.0 *
x - a - b) / (b - a);
400 for (
int j = NUMCOEFS - 1; j > 0; j -= 1) {
402 d = y2 *
d - dd + exspansionCoefs[j];
405 return y *
d - dd + 0.5 * exspansionCoefs[0];
417 <<
" spectra that could not be corrected out of total: " << totalNDetectors <<
'\n';
419 g_log.
debug() <<
" Nullified spectra numbers: ";
#define DECLARE_ALGORITHM(classname)
const double DIST_TO_UNIVERSE_EDGE
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_CRITICAL(name)
#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.
void clear() override
Clears all properties under management.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
void interruption_point()
This is called during long-running operations, and check if the algorithm has requested that it be ca...
A validator which checks that a workspace contains histogram data (the default) or point data as requ...
A validator which checks that a workspace has a valid instrument.
API::SpectrumInfo is an intermediate step towards a SpectrumInfo that is part of Instrument-2....
bool isMonitor(const size_t index) const
Returns true if the detector(s) associated with the spectrum are monitors.
bool hasDetectors(const size_t index) const
Returns true if the spectrum is associated with detectors in the instrument.
bool isMasked(const size_t index) const
Returns true if the detector(s) associated with the spectrum are masked.
const SpectrumDefinition & spectrumDefinition(const size_t index) const
Returns a const reference to the SpectrumDefinition of the spectrum.
A property class for workspaces.
A validator which checks that the unit of the workspace referred to by a WorkspaceProperty is the exp...
Kernel::V3D m_samplePos
Sample position.
double calculateOneOverK(double loBinBound, double uppBinBound) const
Calculate one over the wave vector for 2 bin bounds.
double distToSurface(const Kernel::V3D &start, const Geometry::IObject *shape) const
Computes the distance to the given shape from a starting point.
double m_ki
stores the wave number of incidient neutrons, calculated from the energy
void exec() override
Executes the algorithm.
std::list< int64_t > m_spectraSkipped
The spectra numbers that were skipped.
std::map< const Geometry::IObject *, std::pair< double, Kernel::V3D > > m_shapeCache
A lookup of previously seen shape objects used to save calculation time as most detectors have the sa...
API::MatrixWorkspace_const_sptr m_inputWS
the user selected workspace
API::MatrixWorkspace_sptr m_outputWS
output workspace, maybe the same as the input one
double m_Ei
stores the user selected value for incidient energy of the neutrons
void init() override
Declare algorithm properties.
void retrieveProperties()
Retrieve algorithm properties.
void getDetectorGeometry(const Geometry::IObject &shape, double &detRadius, Kernel::V3D &detAxis)
Sets the detector geometry cache if necessary.
double detectorEfficiency(const double alpha) const
Computes the detector efficiency for a given paramater.
double chebevApprox(double a, double b, const double exspansionCoefs[], double x) const
Computes an approximate expansion of a Chebysev polynomial.
void correctForEfficiency(int64_t spectraIn, const API::SpectrumInfo &spectrumInfo)
Correct the given spectra index for efficiency.
void logErrors(size_t totalNDetectors) const
Log any errors with spectra that occurred.
IObject : Interface for geometry objects.
virtual int interceptSurface(Geometry::Track &) const =0
Defines a track as a start point and a direction.
int count() const
Returns the number of links.
LType::const_iterator cbegin() const
Returns an interator to the start of the set of links (const version)
Exception for when an item is not found in a collection.
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 warning(const std::string &msg)
Logs at warning level.
void rotate(V3D &) const
Rotate a vector.
constexpr double scalar_prod(const V3D &v) const noexcept
Calculates the cross product.
double normalize()
Make a normalized vector (return norm value)
MANTID_KERNEL_DLL bool withinAbsoluteDifference(T const x, T const y, S const tolerance)
Test whether x, y are within absolute tolerance tol.
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 double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
@ Input
An input workspace.
@ Output
An output workspace.