Mantid
Loading...
Searching...
No Matches
ConvertToYSpace.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 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 +
8
9#include "MantidAPI/Axis.h"
23#include "MantidKernel/Unit.h"
24#include "MantidTypes/SpectrumDefinition.h"
25
27
28// Register the algorithm into the AlgorithmFactory
29DECLARE_ALGORITHM(ConvertToYSpace)
30
31using namespace API;
32using namespace Kernel;
33
34namespace {
36const double MASS_TO_MEV = 0.5 * PhysicalConstants::NeutronMass / PhysicalConstants::meV;
37} // namespace
38
41ConvertToYSpace::ConvertToYSpace()
42 : Algorithm(), m_inputWS(), m_mass(0.0), m_l1(0.0), m_samplePos(), m_outputWS(), m_qOutputWS() {}
43
45const std::string ConvertToYSpace::name() const { return "ConvertToYSpace"; }
46
48int ConvertToYSpace::version() const { return 1; }
49
51const std::string ConvertToYSpace::category() const { return "Transforms\\Units"; }
52
58DetectorParams ConvertToYSpace::getDetectorParameters(const API::MatrixWorkspace_const_sptr &ws, const size_t index) {
59 auto inst = ws->getInstrument();
60 auto sample = inst->getSample();
61 auto source = inst->getSource();
62 if (!sample || !source) {
63 throw std::invalid_argument("ConvertToYSpace - Workspace has no source/sample.");
64 }
65
66 const auto &spectrumInfo = ws->spectrumInfo();
67 if (!spectrumInfo.hasDetectors(index))
68 throw std::invalid_argument("ConvertToYSpace - Workspace has no detector "
69 "attached to histogram at index " +
71
72 DetectorParams detpar;
73 const auto &componentInfo = ws->componentInfo();
74 const auto &spectrumDefinition = spectrumInfo.spectrumDefinition(index);
75 detpar.l1 = spectrumInfo.l1();
76 detpar.l2 = spectrumInfo.l2(index);
77 detpar.pos = spectrumInfo.position(index);
78 detpar.theta = spectrumInfo.twoTheta(index);
79 detpar.t0 = getComponentParameter(componentInfo, spectrumDefinition, "t0") * 1e-6; // Convert to seconds
80 detpar.efixed = getComponentParameter(componentInfo, spectrumDefinition, "efixed");
81 return detpar;
82}
83
93double ConvertToYSpace::getComponentParameter(const Geometry::IComponent &comp, const Geometry::ParameterMap &pmap,
94 const std::string &name) {
95 double result(0.0);
96 if (const auto &group = dynamic_cast<const Geometry::DetectorGroup *>(&comp)) {
97 double avg(0.0);
98 for (const auto &det : group->getDetectors()) {
99 auto param = pmap.getRecursive(det->getComponentID(), name);
100 if (param)
101 avg += param->value<double>();
102 else
103 throw std::invalid_argument("ComptonProfile - Unable to find "
104 "DetectorGroup component parameter \"" +
105 name + "\".");
106 }
107 result = avg / static_cast<double>(group->nDets());
108 } else {
109 auto param = pmap.getRecursive(comp.getComponentID(), name);
110 if (param) {
111 result = param->value<double>();
112 } else {
113 throw std::invalid_argument("ComptonProfile - Unable to find component parameter \"" + name + "\".");
114 }
115 }
116 return result;
117}
118
128double ConvertToYSpace::getComponentParameter(const Geometry::ComponentInfo &componentInfo,
129 const SpectrumDefinition &spectrumDefinition, const std::string &name) {
130 const bool isGroup = spectrumDefinition.size() > 1;
131 double sum(0.0);
132 for (const auto &specDefItem : spectrumDefinition) {
133 const auto values = componentInfo.getNumberParameter(specDefItem.first, name);
134 if (!values.empty())
135 sum += values.front();
136 else if (isGroup)
137 throw std::invalid_argument("ComptonProfile - Unable to find "
138 "DetectorGroup component parameter \"" +
139 name + "\".");
140 else
141 throw std::invalid_argument("ComptonProfile - Unable to find component parameter \"" + name + "\".");
142 }
143 return sum / static_cast<double>(spectrumDefinition.size());
144}
145
146//----------------------------------------------------------------------------------------------
147
160void ConvertToYSpace::calculateY(double &yspace, double &qspace, double &ei, const double mass, const double tsec,
161 const double k1, const double v1, const DetectorParams &detpar) {
162 const double v0 = detpar.l1 / (tsec - detpar.t0 - (detpar.l2 / v1));
163 ei = MASS_TO_MEV * v0 * v0;
164 const double w = ei - detpar.efixed;
165 const double k0 = std::sqrt(ei / PhysicalConstants::E_mev_toNeutronWavenumberSq);
166 qspace = std::sqrt(k0 * k0 + k1 * k1 - 2.0 * k0 * k1 * std::cos(detpar.theta));
167 const double wreduced = PhysicalConstants::E_mev_toNeutronWavenumberSq * qspace * qspace / mass;
168 yspace = 0.2393 * (mass / qspace) * (w - wreduced);
169}
170
171//----------------------------------------------------------------------------------------------
172
175void ConvertToYSpace::init() {
176 auto wsValidator = std::make_shared<CompositeValidator>();
177 wsValidator->add<HistogramValidator>(false); // point data
178 wsValidator->add<InstrumentValidator>();
179 wsValidator->add<WorkspaceUnitValidator>("TOF");
180 declareProperty(std::make_unique<WorkspaceProperty<>>("InputWorkspace", "", Direction::Input, wsValidator),
181 "The input workspace in Time of Flight");
182
183 auto mustBePositive = std::make_shared<BoundedValidator<double>>();
184 mustBePositive->setLower(0.0);
185 mustBePositive->setLowerExclusive(true); // strictly greater than 0.0
186 declareProperty("Mass", -1.0, mustBePositive, "The mass defining the recoil peak in AMU");
187
188 declareProperty(std::make_unique<WorkspaceProperty<>>("OutputWorkspace", "", Direction::Output),
189 "The output workspace in y-Space");
190
192 "The output workspace in q-Space");
193}
194
195//----------------------------------------------------------------------------------------------
196
199void ConvertToYSpace::exec() {
202
203 const auto nhist = static_cast<int64_t>(m_inputWS->getNumberHistograms());
204 const int64_t nreports = nhist;
205 auto progress = std::make_shared<Progress>(this, 0.0, 1.0, nreports);
206
207 auto &spectrumInfo = m_outputWS->mutableSpectrumInfo();
208 SpectrumInfo *qSpectrumInfo{nullptr};
209 if (m_qOutputWS)
210 qSpectrumInfo = &m_qOutputWS->mutableSpectrumInfo();
211
213 for (int64_t i = 0; i < nhist; ++i) {
215
216 if (!convert(i)) {
217 g_log.warning("No detector defined for index=" + std::to_string(i) + ". Zeroing spectrum.");
218 m_outputWS->getSpectrum(i).clearData();
219 PARALLEL_CRITICAL(setMasked) {
220 spectrumInfo.setMasked(i, true);
221 if (m_qOutputWS) {
222 m_qOutputWS->getSpectrum(i).clearData();
223 qSpectrumInfo->setMasked(i, true);
224 }
225 }
226 }
227 progress->report();
229 }
231
232 setProperty("OutputWorkspace", m_outputWS);
233
234 if (m_qOutputWS)
235 setProperty("QWorkspace", m_qOutputWS);
236}
237
244bool ConvertToYSpace::convert(const size_t index) {
245 try {
247 const double v1 = std::sqrt(detPar.efixed / MASS_TO_MEV);
248 const double k1 = std::sqrt(detPar.efixed / PhysicalConstants::E_mev_toNeutronWavenumberSq);
249
250 auto &outX = m_outputWS->mutableX(index);
251 auto &outY = m_outputWS->mutableY(index);
252 auto &outE = m_outputWS->mutableE(index);
253 const auto &inX = m_inputWS->x(index);
254 const auto &inY = m_inputWS->y(index);
255 const auto &inE = m_inputWS->e(index);
256
257 // The t->y mapping flips the order of the axis so we need to reverse it to
258 // have a monotonically increasing axis
259 const size_t npts = inY.size();
260 for (size_t j = 0; j < npts; ++j) {
261 double ys(0.0), qs(0.0), ei(0.0);
262 calculateY(ys, qs, ei, m_mass, inX[j] * 1e-06, k1, v1, detPar);
263 const size_t outIndex = (npts - j - 1);
264 outX[outIndex] = ys;
265 const double prefactor = qs / pow(ei, 0.1);
266 outY[outIndex] = prefactor * inY[j];
267 outE[outIndex] = prefactor * inE[j];
268
269 if (m_qOutputWS) {
270 m_qOutputWS->mutableX(index)[outIndex] = ys;
271 m_qOutputWS->mutableY(index)[outIndex] = qs;
272 }
273 }
274 return true;
275 } catch (Exception::NotFoundError &) {
276 return false;
277 }
278}
279
283void ConvertToYSpace::retrieveInputs() {
284 m_inputWS = getProperty("InputWorkspace");
285 m_mass = getProperty("Mass");
287}
288
292void ConvertToYSpace::createOutputWorkspace() {
293 // y-Space output workspace
295
296 auto xLabel = std::make_shared<Units::Label>("Momentum", "A^-1");
297 m_outputWS->getAxis(0)->unit() = xLabel;
298 m_outputWS->setYUnit("");
299 m_outputWS->setYUnitLabel("");
300
301 // q-Space output workspace
302 if (!getPropertyValue("QWorkspace").empty()) {
304
305 m_qOutputWS->getAxis(0)->unit() = xLabel;
306 m_qOutputWS->setYUnit("");
307 m_qOutputWS->setYUnitLabel("");
308 }
309}
310
311void ConvertToYSpace::cacheInstrumentGeometry() {
312 auto inst = m_inputWS->getInstrument();
313 auto source = inst->getSource();
314 auto sample = inst->getSample();
315 m_l1 = sample->getDistance(*source);
316 m_samplePos = sample->getPos();
317}
318
319} // namespace Mantid::CurveFitting::Algorithms
std::string name
Definition Run.cpp:60
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:547
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.
Definition Algorithm.h:76
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.
Kernel::Logger & g_log
Definition Algorithm.h:426
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
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....
A property class for workspaces.
A validator which checks that the unit of the workspace referred to by a WorkspaceProperty is the exp...
API::MatrixWorkspace_sptr m_outputWS
Output workspace.
void retrieveInputs()
Check and store appropriate input data.
const std::string name() const override
Algorithm's name for identification.
void cacheInstrumentGeometry()
Compute & store the parameters that are fixed during the correction.
API::MatrixWorkspace_sptr m_inputWS
Input workspace.
static DetectorParams getDetectorParameters(const API::MatrixWorkspace_const_sptr &ws, const size_t index)
Creates a POD struct containing the required detector parameters for this spectrum.
bool convert(const size_t index)
Perform the conversion to Y-space.
static double getComponentParameter(const Geometry::IComponent &det, const Geometry::ParameterMap &pmap, const std::string &name)
Retrieve a component parameter.
void createOutputWorkspace()
Create the output workspace.
static void calculateY(double &yspace, double &qspace, double &ei, const double mass, const double tsec, const double k1, const double v1, const DetectorParams &detpar)
Convert single time value to Y,Q & Ei values.
ComponentInfo : Provides a component centric view on to the instrument.
std::vector< double > getNumberParameter(const size_t componentIndex, const std::string &name, bool recursive=true) const
Holds a collection of detectors.
base class for Geometric IComponent
Definition IComponent.h:53
virtual ComponentID getComponentID() const =0
Returns the ComponentID - a unique identifier of the component.
Parameter map iterator typedef.
Exception for when an item is not found in a collection.
Definition Exception.h:145
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void warning(const std::string &msg)
Logs at warning level.
Definition Logger.cpp:117
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
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.
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 meV
1 meV in Joules.
Generate a tableworkspace to store the calibration results.
std::string to_string(const wide_integer< Bits, Signed > &n)
Simple data structure to store nominal detector values It avoids some functions taking a huge number ...
double theta
scattering angle in radians
double l1
source-sample distance in metres
double l2
sample-detector distance in metres
@ Input
An input workspace.
Definition Property.h:54
@ Output
An output workspace.
Definition Property.h:55