13#include "MantidHistogramData/Counts.h"
14#include "MantidHistogramData/Histogram.h"
15#include "MantidHistogramData/Points.h"
20const double specialWavelengthCutoff = -1.0;
21const double specialTimeOfFlightCutoff = -1.0;
22const int specialIndex = -1;
25 MinAndMaxTof(
double minTof,
double maxTof) : minTof(minTof), maxTof(maxTof) {}
30struct MinAndMaxIndex {
31 MinAndMaxIndex(
int minIndex,
int maxIndex) : minIndex(minIndex), maxIndex(maxIndex) {}
50MinAndMaxTof getMinAndMaxTofForDistanceFromSoure(
double distanceFromSource,
double lowerWavelengthLimit,
51 double upperWavelengthLimit) {
53 const double angstromConversion = 1e10;
54 const double microsecondConversion = 1e6;
55 const double conversionConstant =
58 const double minTof = lowerWavelengthLimit == specialWavelengthCutoff ? specialTimeOfFlightCutoff
59 : conversionConstant * lowerWavelengthLimit;
60 const double maxTof = upperWavelengthLimit == specialWavelengthCutoff ? specialTimeOfFlightCutoff
61 : conversionConstant * upperWavelengthLimit;
62 return MinAndMaxTof(minTof, maxTof);
67 const auto &detector = spectrumInfo.
detector(workspaceIndex);
72 size_t workspaceIndex,
double lowerWavelengthLimit,
double upperWavelengthLimit) {
73 const auto distanceFromSource = getDistanceFromSourceForWorkspaceIndex(
workspace, spectrumInfo, workspaceIndex);
74 return getMinAndMaxTofForDistanceFromSoure(distanceFromSource, lowerWavelengthLimit, upperWavelengthLimit);
86 auto points =
workspace->points(workspaceIndex);
87 std::vector<double> doubledData(2 * points.size(), 0);
88 std::copy(std::begin(points), std::end(points), std::begin(doubledData));
98 auto firstTof = points.front();
99 auto lastTof = points.back();
100 auto doubledDataIterator = doubledData.begin();
101 std::advance(doubledDataIterator, points.size());
103 double lastElementToNewElementSpacing = 0.0;
104 if (doubledData.size() > 1) {
105 lastElementToNewElementSpacing = doubledData[1] - doubledData[0];
108 for (
auto pointsIterator = points.begin(); doubledDataIterator != doubledData.end();
109 ++doubledDataIterator, ++pointsIterator) {
110 auto newValue = lastTof + lastElementToNewElementSpacing + (*pointsIterator - firstTof);
111 *doubledDataIterator = newValue;
114 return Mantid::HistogramData::Points{doubledData};
117MinAndMaxIndex getMinAndMaxIndex(
const MinAndMaxTof &minMaxTof,
const Mantid::HistogramData::Points &points) {
118 int minIndex = specialIndex;
119 int maxIndex = specialIndex;
120 const auto minCutOff = minMaxTof.minTof;
121 const auto maxCutOff = minMaxTof.maxTof;
123 for (
const auto &element : points) {
124 if (element < minCutOff) {
128 if (element > maxCutOff) {
142 if (maxIndex == specialIndex) {
143 if (points[points.size() - 1] < maxCutOff) {
144 maxIndex =
static_cast<int>(points.size()) - 1;
153 return MinAndMaxIndex(minIndex, maxIndex);
156void setTofBelowLowerBoundToZero(std::vector<double> &doubledData,
int minIndex) {
157 if (minIndex == specialIndex) {
160 auto begin = doubledData.begin();
162 std::advance(end, minIndex);
163 std::fill(begin, end, 0.0);
166void setTofAboveUpperBoundToZero(std::vector<double> &doubledData,
int maxIndex) {
167 if (maxIndex >=
static_cast<int>(doubledData.size()) - 1) {
170 auto begin = doubledData.begin();
171 std::advance(begin, maxIndex);
172 auto end = doubledData.end();
173 std::fill(begin, end, 0.0);
187 const MinAndMaxTof &minMaxTof,
const Mantid::HistogramData::Points &points) {
189 auto counts =
workspace->counts(workspaceIndex);
190 std::vector<double> doubledData(2 * counts.size(), 0);
191 auto doubledDataIterator = doubledData.begin();
192 std::copy(std::begin(counts), std::end(counts), doubledDataIterator);
193 std::advance(doubledDataIterator, counts.size());
194 std::copy(std::begin(counts), std::end(counts), doubledDataIterator);
198 auto minAndMaxIndex = getMinAndMaxIndex(minMaxTof, points);
199 if (minMaxTof.minTof != specialTimeOfFlightCutoff) {
200 setTofBelowLowerBoundToZero(doubledData, minAndMaxIndex.minIndex);
203 if (minMaxTof.maxTof != specialTimeOfFlightCutoff) {
204 setTofAboveUpperBoundToZero(doubledData, minAndMaxIndex.maxIndex);
206 return Mantid::HistogramData::Counts(doubledData);
219 std::vector<size_t> workspaceIndices;
220 auto monitorWorkspace =
workspace->monitorWorkspace();
221 if (monitorWorkspace) {
222 auto numberOfHistograms = monitorWorkspace->getNumberHistograms();
225 auto spectrumNumber = spectrum.getSpectrumNo();
226 auto workspaceIndex =
workspace->getIndexFromSpectrumNumber(spectrumNumber);
227 workspaceIndices.emplace_back(workspaceIndex);
230 auto numberOfHistograms =
workspace->getNumberHistograms();
231 const auto &spectrumInfo =
workspace->spectrumInfo();
232 for (
size_t workspaceIndex = 0; workspaceIndex < numberOfHistograms; ++workspaceIndex) {
233 if (spectrumInfo.
isMonitor(workspaceIndex)) {
234 workspaceIndices.emplace_back(workspaceIndex);
238 return workspaceIndices;
263 return "Takes a TOF input workspace that contains 'raw' data and unwraps "
265 "according to a specified wavelength range. The monitor spectra are "
267 "doubled and then trimmed to the specified wavelength range. If no "
269 "range is specified (-1), then the doubled data is not trimmed. The "
270 "units of the output "
271 "workspace is in TOF. Note that currently only workspaces with "
272 "linearly binned monitor data "
273 "can be handled correctly.";
282 "An input workspace.");
285 "An output workspace.");
286 declareProperty<double>(
"WavelengthMin", specialWavelengthCutoff,
"A lower bound of the wavelength range.");
287 declareProperty<double>(
"WavelengthMax", specialWavelengthCutoff,
"An upper bound of the wavelength range.");
301 const double lowerWavelengthLimit =
getProperty(
"WavelengthMin");
302 const double upperWavelengthLimit =
getProperty(
"WavelengthMax");
305 const auto workspaceIndices = getWorkspaceIndicesForMonitors(outputWorkspace.get());
307 const auto &spectrumInfo = outputWorkspace->spectrumInfo();
309 for (
const auto &workspaceIndex : workspaceIndices) {
310 const auto minMaxTof = getMinAndMaxTof(outputWorkspace.get(), spectrumInfo, workspaceIndex, lowerWavelengthLimit,
311 upperWavelengthLimit);
312 auto points = getPoints(outputWorkspace.get(), workspaceIndex);
313 auto counts = getCounts(outputWorkspace.get(), workspaceIndex, minMaxTof, points);
315 auto inputHistogram = inputWorkspace->histogram(workspaceIndex);
316 auto spectrumIsHistogramData = inputHistogram.xMode() == Mantid::HistogramData::Histogram::XMode::BinEdges;
317 if (spectrumIsHistogramData) {
318 Mantid::HistogramData::BinEdges binEdges(points);
319 Mantid::HistogramData::Histogram histogram(binEdges, counts);
320 outputWorkspace->setHistogram(workspaceIndex, histogram);
322 Mantid::HistogramData::Histogram histogram(points, counts);
323 outputWorkspace->setHistogram(workspaceIndex, histogram);
334 std::map<std::string, std::string> invalidProperties;
337 const double lowerWavelengthLimit =
getProperty(
"WavelengthMin");
338 const double upperWavelengthLimit =
getProperty(
"WavelengthMax");
339 if (lowerWavelengthLimit != specialWavelengthCutoff && lowerWavelengthLimit < 0.0) {
340 invalidProperties[
"WavelengthMin"] =
"The lower wavelength limit must be set to a positive value.";
343 if (upperWavelengthLimit != specialWavelengthCutoff && upperWavelengthLimit < 0.0) {
344 invalidProperties[
"WavelengthMax"] =
"The upper wavelength limit must be set to a positive value.";
347 if (lowerWavelengthLimit != specialWavelengthCutoff && upperWavelengthLimit != specialWavelengthCutoff &&
348 lowerWavelengthLimit >= upperWavelengthLimit) {
349 invalidProperties[
"WavelengthMin"] =
"The lower wavelength limit must be "
350 "smaller than the upper wavelnegth "
352 invalidProperties[
"WavelengthMax"] =
"The lower wavelength limit must be "
353 "smaller than the upper wavelnegth "
357 return invalidProperties;
#define DECLARE_ALGORITHM(classname)
IPeaksWorkspace_sptr workspace
std::map< DeltaEMode::Type, std::string > index
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.
Base MatrixWorkspace Abstract Class.
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.
const Geometry::IDetector & detector(const size_t index) const
Return a const reference to the detector or detector group of the spectrum with given index.
A property class for workspaces.
UnwrapMonitorsInTOF : Handles workspaces which contain monitors that recorded data which spills over ...
const std::string category() const override
Algorithm's category for identification.
int version() const override
Algorithm's version for identification.
const std::string summary() const override
Algorithm's summary for use in the GUI and help.
void exec() override
Execute the algorithm.
void init() override
Initialize the algorithm's properties.
std::map< std::string, std::string > validateInputs() override
Check the inputs for invalid values.
double getDistance(const IComponent &comp) const override=0
Get the distance of this detector object from another Component.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
static constexpr double NeutronMass
Mass of the neutron in kg.
static constexpr double h
Planck constant in J*s.
Describes the direction (within an algorithm) of a Property.
@ Input
An input workspace.
@ Output
An output workspace.