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);
73 double lowerWavelengthLimit,
double upperWavelengthLimit) {
74 const auto distanceFromSource = getDistanceFromSourceForWorkspaceIndex(
workspace, spectrumInfo, workspaceIndex);
75 return getMinAndMaxTofForDistanceFromSoure(distanceFromSource, lowerWavelengthLimit, upperWavelengthLimit);
87 auto points =
workspace->points(workspaceIndex);
88 std::vector<double> doubledData(2 * points.size(), 0);
89 std::copy(std::begin(points), std::end(points), std::begin(doubledData));
99 auto firstTof = points.front();
100 auto lastTof = points.back();
101 auto doubledDataIterator = doubledData.begin();
102 std::advance(doubledDataIterator, points.size());
104 double lastElementToNewElementSpacing = 0.0;
105 if (doubledData.size() > 1) {
106 lastElementToNewElementSpacing = doubledData[1] - doubledData[0];
109 for (
auto pointsIterator = points.begin(); doubledDataIterator != doubledData.end();
110 ++doubledDataIterator, ++pointsIterator) {
111 auto newValue = lastTof + lastElementToNewElementSpacing + (*pointsIterator - firstTof);
112 *doubledDataIterator = newValue;
115 return Mantid::HistogramData::Points{doubledData};
118MinAndMaxIndex getMinAndMaxIndex(
const MinAndMaxTof &minMaxTof,
const Mantid::HistogramData::Points &points) {
119 int minIndex = specialIndex;
120 int maxIndex = specialIndex;
121 const auto minCutOff = minMaxTof.minTof;
122 const auto maxCutOff = minMaxTof.maxTof;
124 for (
const auto &element : points) {
125 if (element < minCutOff) {
129 if (element > maxCutOff) {
143 if (maxIndex == specialIndex) {
144 if (points[points.size() - 1] < maxCutOff) {
145 maxIndex =
static_cast<int>(points.size()) - 1;
154 return MinAndMaxIndex(minIndex, maxIndex);
157void setTofBelowLowerBoundToZero(std::vector<double> &doubledData,
int minIndex) {
158 if (minIndex == specialIndex) {
161 auto begin = doubledData.begin();
163 std::advance(end, minIndex);
164 std::fill(begin, end, 0.0);
167void setTofAboveUpperBoundToZero(std::vector<double> &doubledData,
int maxIndex) {
168 if (maxIndex >=
static_cast<int>(doubledData.size()) - 1) {
171 auto begin = doubledData.begin();
172 std::advance(begin, maxIndex);
173 auto end = doubledData.end();
174 std::fill(begin, end, 0.0);
188 const MinAndMaxTof &minMaxTof,
const Mantid::HistogramData::Points &points) {
190 auto counts =
workspace->counts(workspaceIndex);
191 std::vector<double> doubledData(2 * counts.size(), 0);
192 auto doubledDataIterator = doubledData.begin();
193 std::copy(std::begin(counts), std::end(counts), doubledDataIterator);
194 std::advance(doubledDataIterator, counts.size());
195 std::copy(std::begin(counts), std::end(counts), doubledDataIterator);
199 auto minAndMaxIndex = getMinAndMaxIndex(minMaxTof, points);
200 if (minMaxTof.minTof != specialTimeOfFlightCutoff) {
201 setTofBelowLowerBoundToZero(doubledData, minAndMaxIndex.minIndex);
204 if (minMaxTof.maxTof != specialTimeOfFlightCutoff) {
205 setTofAboveUpperBoundToZero(doubledData, minAndMaxIndex.maxIndex);
207 return Mantid::HistogramData::Counts(doubledData);
220 std::vector<size_t> workspaceIndices;
221 auto monitorWorkspace =
workspace->monitorWorkspace();
222 if (monitorWorkspace) {
223 auto numberOfHistograms = monitorWorkspace->getNumberHistograms();
226 auto spectrumNumber = spectrum.getSpectrumNo();
227 auto workspaceIndex =
workspace->getIndexFromSpectrumNumber(spectrumNumber);
228 workspaceIndices.emplace_back(workspaceIndex);
231 auto numberOfHistograms =
workspace->getNumberHistograms();
232 const auto &spectrumInfo =
workspace->spectrumInfo();
233 for (
size_t workspaceIndex = 0; workspaceIndex < numberOfHistograms; ++workspaceIndex) {
234 if (spectrumInfo.
isMonitor(workspaceIndex)) {
235 workspaceIndices.emplace_back(workspaceIndex);
239 return workspaceIndices;
267 return "Takes a TOF input workspace that contains 'raw' data and unwraps "
269 "according to a specified wavelength range. The monitor spectra are "
271 "doubled and then trimmed to the specified wavelength range. If no "
273 "range is specified (-1), then the doubled data is not trimmed. The "
274 "units of the output "
275 "workspace is in TOF. Note that currently only workspaces with "
276 "linearly binned monitor data "
277 "can be handled correctly.";
286 "An input workspace.");
289 "An output workspace.");
290 declareProperty<double>(
"WavelengthMin", specialWavelengthCutoff,
"A lower bound of the wavelength range.");
291 declareProperty<double>(
"WavelengthMax", specialWavelengthCutoff,
"An upper bound of the wavelength range.");
305 const double lowerWavelengthLimit =
getProperty(
"WavelengthMin");
306 const double upperWavelengthLimit =
getProperty(
"WavelengthMax");
309 const auto workspaceIndices = getWorkspaceIndicesForMonitors(outputWorkspace.get());
311 const auto &spectrumInfo = outputWorkspace->spectrumInfo();
313 for (
const auto &workspaceIndex : workspaceIndices) {
314 const auto minMaxTof = getMinAndMaxTof(outputWorkspace.get(), spectrumInfo, workspaceIndex, lowerWavelengthLimit,
315 upperWavelengthLimit);
316 auto points = getPoints(outputWorkspace.get(), workspaceIndex);
317 auto counts = getCounts(outputWorkspace.get(), workspaceIndex, minMaxTof, points);
319 auto inputHistogram = inputWorkspace->histogram(workspaceIndex);
320 auto spectrumIsHistogramData = inputHistogram.xMode() == Mantid::HistogramData::Histogram::XMode::BinEdges;
321 if (spectrumIsHistogramData) {
322 Mantid::HistogramData::BinEdges binEdges(points);
323 Mantid::HistogramData::Histogram histogram(binEdges, counts);
324 outputWorkspace->setHistogram(workspaceIndex, histogram);
326 Mantid::HistogramData::Histogram histogram(points, counts);
327 outputWorkspace->setHistogram(workspaceIndex, histogram);
338 std::map<std::string, std::string> invalidProperties;
341 const double lowerWavelengthLimit =
getProperty(
"WavelengthMin");
342 const double upperWavelengthLimit =
getProperty(
"WavelengthMax");
343 if (lowerWavelengthLimit != specialWavelengthCutoff && lowerWavelengthLimit < 0.0) {
344 invalidProperties[
"WavelengthMin"] =
"The lower wavelength limit must be set to a positive value.";
347 if (upperWavelengthLimit != specialWavelengthCutoff && upperWavelengthLimit < 0.0) {
348 invalidProperties[
"WavelengthMax"] =
"The upper wavelength limit must be set to a positive value.";
351 if (lowerWavelengthLimit != specialWavelengthCutoff && upperWavelengthLimit != specialWavelengthCutoff &&
352 lowerWavelengthLimit >= upperWavelengthLimit) {
353 invalidProperties[
"WavelengthMin"] =
"The lower wavelength limit must be "
354 "smaller than the upper wavelnegth "
356 invalidProperties[
"WavelengthMax"] =
"The lower wavelength limit must be "
357 "smaller than the upper wavelnegth "
361 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.
const std::string name() const override
Algorithms name for identification.
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.