15#include "MantidHistogramData/Histogram.h"
16#include "MantidHistogramData/HistogramBuilder.h"
28using namespace Kernel;
30using namespace Geometry;
31using namespace DataObjects;
32using namespace HistogramData;
34constexpr double rad2deg = 180. / M_PI;
39 auto wsVal = std::make_shared<CompositeValidator>();
44 "The name of the input workspace.");
46 "The name to use for the output workspace.");
48 targetOptions.emplace_back(
"theta");
49 targetOptions.emplace_back(
"signed_theta");
50 declareProperty(
"Target",
"", std::make_shared<StringListValidator>(targetOptions),
51 "The unit to which the spectrum axis should be converted. "
52 "This can be either \"theta\" (for <math>\\theta</math> "
53 "degrees), or any of the IDs known to the [[Unit Factory]].");
54 std::vector<std::string> eModeOptions;
55 eModeOptions.emplace_back(
"Direct");
56 eModeOptions.emplace_back(
"Indirect");
57 declareProperty(
"EMode",
"Direct", std::make_shared<StringListValidator>(eModeOptions),
58 "Some unit conversions require this value to be set "
59 "(\"Direct\" or \"Indirect\")");
60 auto mustBePositive = std::make_shared<BoundedValidator<double>>();
61 mustBePositive->setLower(0.0);
63 "Value of fixed energy in meV : EI (EMode=Direct) or EF "
74 std::multimap<double, size_t> indexMap;
75 const size_t nHist = inputWS->getNumberHistograms();
76 const size_t nBins = inputWS->blocksize();
77 const bool isHist = inputWS->isHistogramData();
78 auto &spectrumInfo = inputWS->spectrumInfo();
85 if (unitTarget !=
"theta" && unitTarget !=
"signed_theta") {
88 std::vector<double> emptyVector;
89 const double l1 = spectrumInfo.l1();
93 for (
size_t i = 0; i < nHist; i++) {
94 std::vector<double> xval{inputWS->x(i).front(), inputWS->x(i).back()};
99 pmap[UnitParams::efixed] = efixedProp;
100 g_log.
debug() <<
"Detector: " << spectrumInfo.detector(i).getID() <<
" Efixed: " << efixedProp <<
"\n";
103 spectrumInfo.getDetectorValues(*fromUnit, *toUnit, emode,
false, i,
pmap);
106 fromUnit->toTOF(xval, emptyVector, l1, emode,
pmap);
107 toUnit->fromTOF(xval, emptyVector, l1, emode,
pmap);
108 value = (xval.front() + xval.back()) / 2;
109 }
catch (std::runtime_error &) {
111 g_log.
warning() <<
"Unable to calculate new spectrum axis value for "
114 value = inputWS->getAxis(1)->getValue(i);
116 indexMap.emplace(
value, i);
118 if (nfailures == nHist) {
119 throw std::runtime_error(
"Unable to convert spectrum axis values on all spectra");
124 using namespace std::placeholders;
125 std::function<double(
const IDetector &)> thetaFunction;
126 if (unitTarget ==
"signed_theta") {
132 bool warningGiven =
false;
133 for (
size_t i = 0; i < nHist; ++i) {
137 indexMap.emplace(thetaFunction(*det) *
rad2deg, i);
140 g_log.
warning(
"The instrument definition is incomplete - spectra "
141 "dropped from output");
148 HistogramBuilder builder;
149 builder.setX(nxBins);
151 builder.setDistribution(inputWS->isDistribution());
152 MatrixWorkspace_sptr outputWS = create<MatrixWorkspace>(*inputWS, indexMap.size(), builder.build());
155 auto newAxis = std::make_unique<NumericAxis>(indexMap.size());
156 auto newAxisRaw = newAxis.get();
157 outputWS->replaceAxis(1, std::move(newAxis));
159 if (unitTarget ==
"theta" || unitTarget ==
"signed_theta") {
160 newAxisRaw->unit() = std::make_shared<Units::Degrees>();
164 std::multimap<double, size_t>::const_iterator it;
165 size_t currentIndex = 0;
166 for (it = indexMap.begin(); it != indexMap.end(); ++it) {
168 newAxisRaw->setValue(currentIndex, it->first);
170 outputWS->setHistogram(currentIndex, inputWS->histogram(it->second));
172 outputWS->getSpectrum(currentIndex).copyInfoFrom(inputWS->getSpectrum(it->second));
187 if (inputWS->run().hasProperty(
"Ei")) {
194 g_log.
warning() <<
"Efixed could not be found for detector " << detector.
getID() <<
", set to 0.0\n";
198 g_log.
warning() <<
"Efixed could not be found for detector " << detector.
getID() <<
", set to 0.0\n";
200 }
else if (emode == 2) {
202 if (efixedVec.empty()) {
203 int detid = detector.
getID();
205 efixedVec = detectorSingle->getNumberParameter(
"Efixed");
207 if (!efixedVec.empty()) {
212 g_log.
warning() <<
"Efixed could not be found for detector " << detector.
getID() <<
", set to 0.0\n";
#define DECLARE_ALGORITHM(classname)
double value
The value of the point.
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
A validator which checks that a workspace has a valid instrument.
double detectorSignedTwoTheta(const Geometry::IDetector &det) const
Returns the signed 2Theta scattering angle for a detector.
double detectorTwoTheta(const Geometry::IDetector &det) const
Returns the 2Theta scattering angle for a detector.
A validator which checks whether the input workspace has the Spectra number in the axis.
A property class for workspaces.
void exec() override
Execution code.
double getEfixed(const Mantid::Geometry::IDetector &detector, const API::MatrixWorkspace_const_sptr &inputWS, int emode) const
Getting Efixed.
void init() override
Initialisation code.
virtual std::vector< double > getNumberParameter(const std::string &pname, bool recursive=true) const =0
Get a parameter defined as a double.
Interface class for detector objects.
virtual detid_t getID() const =0
Get the detector ID.
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.
The concrete, templated class for properties.
Base class for properties.
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::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
constexpr double rad2deg
Radians to degrees conversion factor.
std::shared_ptr< const Mantid::Geometry::IDetector > IDetector_const_sptr
Shared pointer to IDetector (const version)
std::unordered_map< UnitParams, double > UnitParametersMap
std::shared_ptr< Unit > Unit_sptr
Shared pointer to the Unit base class.
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
Generate a tableworkspace to store the calibration results.
static Type fromString(const std::string &modeStr)
Returns the emode from the given string.
@ Input
An input workspace.
@ Output
An output workspace.