20#include "MantidHistogramData/LinearGenerator.h"
32#include <boost/math/special_functions/round.hpp>
39using namespace Geometry;
40using namespace HistogramData;
41using namespace DataObjects;
42using namespace Kernel;
46 "The names of the input workspaces as a list. You may also "
47 "group workspaces using the GUI or [[GroupWorkspaces]], and "
48 "specify the name of the group instead.");
50 "Name of the output workspace.");
51 std::vector<std::string> outputTypes{
"2DTubes",
"2D",
"1D"};
52 declareProperty(
"OutputType",
"2D", std::make_shared<StringListValidator>(outputTypes),
53 "Whether to have the output in raw 2D, with no "
54 "Debye-Scherrer cone correction, 2D or 1D.");
57 "A comma separated list of the first scattering angle, the scattering "
58 "angle step size and the final scattering angle. Optionally this can "
59 "also be a single number, which is the angle step size. In this case, "
60 "the boundary of binning will be determined by minimum and maximum "
61 "scattering angle present in the workspaces.");
63 "If true the negative scattering angles are cropped (ignored).");
65 std::make_unique<
ArrayProperty<double>>(
"HeightAxis", std::make_shared<RebinParamsValidator>(
true,
true)),
66 "A comma separated list of the first y value, the y value step size and "
67 "the final y value. This can also be a single number, which "
68 "is the y value step size. In this case, the boundary of binning will "
69 "be determined by minimum and maximum y values present in the "
70 "workspaces. This can also be two numbers to give the range desired.");
72 "If true normalise to the number of entries added for a particular "
73 "scattering angle. ");
75 "A flag to mirror the signed 2thetas. ");
77 "A flag to split the counts between adjacent bins");
78 auto toleranceValidator = std::make_shared<BoundedValidator<double>>(0.0, 0.0);
79 toleranceValidator->clearUpper();
81 "The relative tolerance for the scattering angles before the "
84 std::make_unique<Kernel::EnabledWhenProperty>(
"SplitCounts",
IS_NOT_DEFAULT));
96 outputWS->setDistribution(
false);
99 auto newAxis = std::make_unique<NumericAxis>(
m_heightAxis);
100 newAxis->setUnit(
"Label");
101 auto yLabelUnit = std::dynamic_pointer_cast<Kernel::Units::Label>(newAxis->unit());
102 yLabelUnit->setLabel(
"Height",
"m");
103 newAxis->unit() = yLabelUnit;
104 outputWS->replaceAxis(1, std::move(newAxis));
107 Unit_sptr xUnit = outputWS->getAxis(0)->unit();
108 std::shared_ptr<Units::Label> xLabel = std::dynamic_pointer_cast<Units::Label>(xUnit);
109 xLabel->setLabel(
"Scattering Angle",
"degrees");
115 for (int64_t ii = 0; ii < static_cast<int64_t>(
m_numPoints); ++ii)
118 const auto i =
static_cast<size_t>(ii);
119 if (normalisation[j][i] < 1e-15)
121 outputWS->mutableY(j)[i] /= normalisation[j][i];
122 outputWS->mutableE(j)[i] /= normalisation[j][i];
134 const std::vector<std::string> inputWorkspaces =
getProperty(
"InputWorkspaces");
140 std::string componentName =
"";
141 auto componentNameParam = instrument->getStringParameter(
"detector_for_height_axis");
142 if (!componentNameParam.empty())
143 componentName = componentNameParam[0];
154 const auto &specInfo = ws->spectrumInfo();
155 for (
size_t i = 0; i < specInfo.size(); ++i) {
156 if (specInfo.isMonitor(i) || specInfo.isMasked(i))
158 const auto &pos = specInfo.position(i);
165 const std::vector<double> scatteringBinning =
getProperty(
"ScatteringAngleBinning");
166 if (scatteringBinning.size() == 1) {
171 }
else if (scatteringBinning.size() == 3) {
173 g_log.
warning() <<
"Some detectors outside of scattering angle range.\n";
181 throw std::runtime_error(
"No positive scattering angle range");
195 throw std::runtime_error(
"Wrong scattering angle range, check your binning/data");
200 std::vector<double> heightBinning =
getProperty(
"HeightAxis");
202 if (componentName.length() == 0 && heightBinning.empty())
203 throw std::runtime_error(
"No detector_for_height_axis parameter for this "
204 "instrument. Please enter a value for the "
205 "HeightAxis parameter.");
206 if ((componentName.length() > 0 && heightBinning.empty()) || (
m_outputType !=
"1D" && heightBinning.size() == 2)) {
210 const auto componentIndex = componentInfo.indexOfAny(componentName);
211 const auto &detsInSubtree = componentInfo.detectorsInSubtree(componentIndex);
212 for (
const auto detIndex : detsInSubtree) {
213 const auto posY = componentInfo.position({detIndex, 0}).
Y();
214 if (heightBinning.size() == 2 && (posY < heightBinning[0] || posY > heightBinning[1]))
219 if (heightBinning.size() != 3) {
220 if (heightBinning.size() == 2 &&
m_outputType ==
"1D") {
224 throw std::runtime_error(
"Height binning must have start, step and end "
225 "values (except for 1D option).");
230 double height = heightBinning[0];
231 while (
height < heightBinning[2]) {
233 height += heightBinning[1];
252 const double scatteringAngleTolerance =
getProperty(
"ScatteringAngleTolerance");
253 const bool splitCounts =
getProperty(
"SplitCounts");
259 m_progress->report(
"Processing workspace " + std::string(ws->getName()));
261 const auto &specInfo = ws->spectrumInfo();
263 for (
int i = 0; i < static_cast<int>(specInfo.size()); ++i) {
265 if (specInfo.isMonitor(i) || specInfo.isMasked(i))
268 const auto &pos = specInfo.position(i);
269 const auto height = pos.Y();
278 }
catch (std::out_of_range &) {
284 angle = atan2(pos.X(), pos.Z());
286 angle = specInfo.signedTwoTheta(i);
293 if (angleIndex < 0 || angleIndex >=
int(
m_numPoints))
297 const auto counts = ws->histogram(i).y()[0];
298 const auto error = ws->histogram(i).e()[0];
301 auto &yData = outputWS->mutableY(heightIndex);
302 auto &eData = outputWS->mutableE(heightIndex);
305 int angleIndexNeighbor;
307 angleIndexNeighbor = angleIndex - 1;
309 angleIndexNeighbor = angleIndex + 1;
314 const auto newError =
error * scalingFactor;
315 yData[angleIndex] += counts * scalingFactor;
316 eData[angleIndex] = sqrt(eData[angleIndex] * eData[angleIndex] + newError * newError);
320 if (angleIndexNeighbor >= 0 && angleIndexNeighbor <
int(
m_numPoints)) {
322 const auto newErrorNeighbor =
error * scalingFactorNeighbor;
323 yData[angleIndexNeighbor] += counts * scalingFactorNeighbor;
324 eData[angleIndexNeighbor] =
325 sqrt(eData[angleIndexNeighbor] * eData[angleIndexNeighbor] + newErrorNeighbor * newErrorNeighbor);
329 yData[angleIndex] += counts;
330 eData[angleIndex] = sqrt(eData[angleIndex] * eData[angleIndex] +
error *
error);
331 normalisation[heightIndex][angleIndex]++;
339 return normalisation;
#define DECLARE_ALGORITHM(classname)
#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_FOR_NO_WSP_CHECK()
#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.
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.
A property class for workspaces.
static std::vector< std::string > unWrapGroups(const std::vector< std::string > &)
Flattens the list of group workspaces (if any) into list of workspaces.
std::list< API::MatrixWorkspace_sptr > validateInputWorkspaces(const std::vector< std::string > &inputWorkspaces, Kernel::Logger &g_log)
Checks that the input workspace all exist, that they are the same size, have the same units and the s...
void exec() override
Virtual method - must be overridden by concrete algorithm.
double distanceFromAngle(const int angleIndex, const double angle) const
std::list< API::MatrixWorkspace_sptr > m_workspaceList
void init() override
Virtual method - must be overridden by concrete algorithm.
std::vector< double > m_heightAxis
std::vector< std::vector< double > > performBinning(API::MatrixWorkspace_sptr &outputWS)
std::unique_ptr< API::Progress > m_progress
holds the sign flipper for 2theta
double m_stepScatteringAngle
double m_endScatteringAngle
void getInputParameters()
void getScatteringAngleBinning()
void getHeightAxis(const std::string &componentName)
double m_startScatteringAngle
Support for a property that holds an array of values.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void setPropertySettings(const std::string &name, std::unique_ptr< IPropertySettings > settings)
void warning(const std::string &msg)
Logs at warning level.
void information(const std::string &msg)
Logs at information level.
The concrete, templated 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< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
size_t MANTID_KERNEL_DLL indexOfValueFromCenters(const std::vector< double > &bin_centers, const double value)
Gets the bin of a value from a vector of bin centers and throws exception if out of range.
std::shared_ptr< Unit > Unit_sptr
Shared pointer to the Unit base class.
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.
@ Input
An input workspace.
@ Output
An output workspace.