22using namespace Kernel;
31 using namespace Geometry;
39 std::vector<double> verticalAxis;
43 const auto &xAxis = outputWorkspace->binEdges(0).rawData();
46 std::vector<specnum_t> specNumberMapping;
47 std::vector<detid_t> detIDMapping;
49 const auto &detectorInfo = inputWorkspace->detectorInfo();
50 const auto &spectrumInfo = inputWorkspace->spectrumInfo();
51 const V3D beamDir =
normalize(detectorInfo.samplePosition() - detectorInfo.sourcePosition());
52 const double l1 = detectorInfo.l1();
53 g_log.
debug() <<
"Source-sample distance: " << l1 <<
'\n';
57 const size_t numHists = inputWorkspace->getNumberHistograms();
58 const size_t numBins = inputWorkspace->blocksize();
59 Progress prog(
this, 0.0, 1.0, numHists);
60 for (int64_t i = 0; i < int64_t(numHists); ++i) {
61 if (!spectrumInfo.hasDetectors(i) || spectrumInfo.isMonitor(i))
64 const auto &spectrumDet = spectrumInfo.detector(i);
73 const auto &detIDs = inputWorkspace->getSpectrum(i).getDetectorIDs();
74 auto numDets_d =
static_cast<double>(detIDs.size());
75 const auto &
Y = inputWorkspace->y(i);
76 const auto &E = inputWorkspace->e(i);
77 const auto &
X = inputWorkspace->x(i);
80 for (
const auto detID : detIDs) {
82 size_t idet = detectorInfo.indexOf(detID);
84 const V3D scatterDir =
normalize(detectorInfo.position(idet) - detectorInfo.samplePosition());
85 for (
size_t j = 0; j < numBins; ++j) {
86 if (
X[j] < xAxis.front() ||
X[j + 1] > xAxis.back())
89 const double deltaE = 0.5 * (
X[j] +
X[j + 1]);
91 double ei(0.0), ef(0.0);
96 std::string mess =
"Energy transfer requested in Direct mode exceeds incident "
97 "energy.\n Found for det ID: " +
99 " with Ei=" + boost::lexical_cast<std::string>(
efixed) +
100 " and energy transfer: " + boost::lexical_cast<std::string>(deltaE);
101 throw std::runtime_error(mess);
107 std::string mess =
"Incident energy of a neutron is negative. Are you trying to "
108 "process Direct data in Indirect mode?\n Found for det ID: " +
110 " with efied=" + boost::lexical_cast<std::string>(
efixed) +
111 " and energy transfer: " + boost::lexical_cast<std::string>(deltaE);
112 throw std::runtime_error(mess);
117 throw std::runtime_error(
"Negative incident energy. Check binning.");
119 const V3D ki = beamDir * sqrt(ei / E_mev_toNeutronWavenumberSq);
120 const V3D kf = scatterDir * sqrt(ef / E_mev_toNeutronWavenumberSq);
121 const double q = (ki - kf).norm();
124 if (q < verticalAxis.front() || q > verticalAxis.back())
127 const MantidVec::difference_type qIndex =
128 std::upper_bound(verticalAxis.begin(), verticalAxis.end(), q) - verticalAxis.begin() - 1;
130 const MantidVec::difference_type eIndex =
131 std::upper_bound(xAxis.begin(), xAxis.end(), deltaE) - xAxis.begin() - 1;
134 specNumberMapping.emplace_back(outputWorkspace->getSpectrum(qIndex).getSpectrumNo());
135 detIDMapping.emplace_back(detID);
139 outputWorkspace->mutableY(qIndex)[eIndex] +=
Y[j] / numDets_d;
141 outputWorkspace->mutableE(qIndex)[eIndex] =
142 sqrt((pow(outputWorkspace->e(qIndex)[eIndex], 2) + pow(E[j], 2)) / numDets_d);
144 }
catch (std::out_of_range &) {
154 if (inputWorkspace->isDistribution())
159 outputWorkspace->updateSpectraUsing(outputDetectorMap);
164 replaceNans->setChild(
true);
165 replaceNans->initialize();
166 replaceNans->setProperty(
"InputWorkspace", outputWorkspace);
167 replaceNans->setProperty(
"OutputWorkspace", outputWorkspace);
168 replaceNans->setProperty(
"NaNValue", 0.0);
169 replaceNans->setProperty(
"InfinityValue", 0.0);
170 replaceNans->setProperty(
"BigNumberThreshold", DBL_MAX);
171 replaceNans->execute();
180 std::vector<double> widths(qAxis.size());
181 std::adjacent_difference(qAxis.begin(), qAxis.end(), widths.begin());
184 for (
size_t i = 0; i < numQBins; ++i) {
187 using std::placeholders::_1;
188 std::transform(
Y.begin(),
Y.end(),
Y.begin(), std::bind(std::divides<double>(), _1, widths[i + 1]));
189 std::transform(E.begin(), E.end(), E.begin(), std::bind(std::divides<double>(), _1, widths[i + 1]));
#define DECLARE_ALGORITHM(classname)
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.
Base MatrixWorkspace Abstract Class.
virtual std::size_t getNumberHistograms() const =0
Returns the number of histograms in the workspace.
HistogramData::HistogramE & mutableE(const size_t index) &
HistogramData::HistogramY & mutableY(const size_t index) &
Helper class for reporting progress from algorithms.
A minimal class to hold the mapping between the spectrum number and its related detector ID numbers f...
void exec() override
Execution code.
static void makeDistribution(API::MatrixWorkspace &outputWS, const std::vector< double > &qAxis)
Convert the workspace to a distribution.
SofQCommon m_EmodeProperties
void init() override
Initialization code.
static void createCommonInputProperties(API::Algorithm &alg)
Create the input properties on the given algorithm object.
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 report()
Increments the loop counter by 1, then sends the progress notification on behalf of its algorithm.
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
MANTID_KERNEL_DLL V3D normalize(V3D v)
Normalizes a V3D.
static constexpr double E_mev_toNeutronWavenumberSq
Transformation coefficient to transform neutron energy into neutron wavevector: K-neutron[m^-10] = sq...
std::string to_string(const wide_integer< Bits, Signed > &n)
double getEFixed(const Geometry::IDetector &det) const
Get the efixed value for the given detector.
void initCachedValues(const API::MatrixWorkspace &workspace, API::Algorithm *const hostAlgorithm)
The procedure analyses emode and efixed properties provided to the algorithm and identify the energy ...