31#include <boost/algorithm/string/classification.hpp>
32#include <boost/algorithm/string/split.hpp>
43using namespace Kernel;
45using namespace Geometry;
46using namespace DataObjects;
49 auto wsValidator = std::make_shared<CompositeValidator>(CompositeRelation::OR);
50 auto monoValidator = std::make_shared<CompositeValidator>(CompositeRelation::AND);
51 auto monoUnitValidator = std::make_shared<CompositeValidator>(CompositeRelation::OR);
52 auto tofValidator = std::make_shared<CompositeValidator>(CompositeRelation::AND);
57 monoValidator->add(monoUnitValidator);
65 wsValidator->add(monoValidator);
66 wsValidator->add(tofValidator);
69 "Input workspace containing the SANS 2D data");
71 "Workspace that will contain the I(Q) data");
73 "The new bin boundaries in the form: :math:`x_1,\\Delta x_1,x_2,\\Delta "
76 auto positiveInt = std::make_shared<BoundedValidator<int>>();
77 positiveInt->setLower(0);
78 auto positiveDouble = std::make_shared<BoundedValidator<double>>();
79 positiveDouble->setLower(0);
82 "Number of sub-pixels used for each detector pixel in each "
83 "direction.The total number of sub-pixels will be "
84 "NPixelDivision*NPixelDivision.");
87 declareProperty(
"NumberOfWedges", 2, positiveInt,
"Number of wedges to calculate.");
88 declareProperty(
"WedgeAngle", 30.0, positiveDouble,
"Opening angle of the wedge, in degrees.");
89 declareProperty(
"WedgeOffset", 0.0, positiveDouble,
"Wedge offset relative to the horizontal axis, in degrees.");
92 "Name for the WorkspaceGroup containing the wedge I(q) distributions.");
94 declareProperty(
"PixelSizeX", 5.15, positiveDouble,
"Pixel size in the X direction (mm).");
95 declareProperty(
"PixelSizeY", 5.15, positiveDouble,
"Pixel size in the Y direction (mm).");
96 declareProperty(
"ErrorWeighting",
false,
"Choose whether each pixel contribution will be weighted by 1/error^2.");
98 declareProperty(
"AsymmetricWedges",
false,
"Choose to produce the results for asymmetric wedges.");
100 declareProperty(
"AccountForGravity",
false,
"Take the nominal gravity drop into account.");
104 "Table workspace containing the shapes (sectors only) drawn in the "
105 "instrument viewer; if specified, the wedges properties defined above "
106 "are not taken into account.");
136 const std::vector<double> binParams =
getProperty(
"OutputBinning");
142 m_nSpec = inputWS->getNumberHistograms();
145 m_nBins = inputWS->readY(0).size();
156 const double wedgeOffset =
getProperty(
"WedgeOffset");
157 const double wedgeAngle =
getProperty(
"WedgeAngle");
160 for (
size_t iw = 0; iw <
m_nWedges; ++iw) {
161 double innerRadius = 0.;
164 double outerRadius = -1.;
167 double angleRange = wedgeAngle *
deg2rad;
168 double midAngle = M_PI *
static_cast<double>(iw) /
static_cast<double>(
m_nWedges);
171 midAngle += wedgeOffset *
deg2rad;
174 Q1DWeighted::Wedge(innerRadius, outerRadius, centerX, centerY, midAngle, angleRange));
177 g_log.
warning(
"This option is still in active development and might be "
178 "subject to changes in the next version.");
189 m_intensities = std::vector<std::vector<std::vector<double>>>(
202 size_t rowCount = shapeWs->rowCount();
204 std::map<std::string, std::vector<double>> viewportParams;
209 for (
size_t i = 0; i < rowCount - 1; ++i) {
210 std::map<std::string, std::vector<std::string>> paramMap;
211 std::vector<std::string> splitParams;
212 boost::algorithm::split(splitParams, shapeWs->String(i, 1), boost::algorithm::is_any_of(
"\n"));
213 std::vector<std::string> params;
214 for (std::string val : splitParams) {
217 boost::algorithm::split(params, val, boost::algorithm::is_any_of(
"\t"));
220 paramMap[params[0]] = params;
222 if (paramMap[
"Type"][1] ==
"sector")
225 g_log.
information() <<
"Shape " << i + 1 <<
" is of type " << paramMap[
"Type"][1]
226 <<
" which is not supported. This shape is ignored." << std::endl;
231 return wedgeA.angleMiddle < wedgeB.angleMiddle;
245 std::map<std::string, std::vector<double>> &viewportParams) {
247 std::vector<std::string> params;
248 boost::algorithm::split(params, viewport, boost::algorithm::is_any_of(
"\t, \n"));
250 if (params[0] !=
"Translation") {
252 "No viewport found in the shape table. Please provide a table using shapes drawn in the Full3D projection.");
256 viewportParams[params[0]] = std::vector<double>(2);
257 viewportParams[params[0]][0] = std::stod(params[1]);
258 viewportParams[params[0]][1] = std::stod(params[2]);
261 viewportParams[params[3]] = std::vector<double>(1);
262 viewportParams[params[3]][0] = std::stod(params[4]);
265 viewportParams[params[5]] = std::vector<double>(4);
266 viewportParams[params[5]][0] = std::stod(params[6]);
267 viewportParams[params[5]][1] = std::stod(params[7]);
268 viewportParams[params[5]][2] = std::stod(params[8]);
269 viewportParams[params[5]][3] = std::stod(params[9]);
271 double epsilon = 1e-10;
273 if (std::fabs(viewportParams[
"Rotation"][0]) > epsilon || std::fabs(viewportParams[
"Rotation"][1]) > epsilon ||
274 std::fabs(viewportParams[
"Rotation"][3]) > epsilon || std::fabs(viewportParams[
"Rotation"][2] - 1) > epsilon) {
275 g_log.
warning(
"The shapes were created using a rotated viewport not using Z- projection, which is not supported. "
276 "Results are likely to be erroneous. Consider freezing the rotation in the instrument viewer.");
286 const std::map<std::string, std::vector<double>> &viewport) {
287 double zoom = viewport.at(
"Zoom")[0];
289 double innerRadius = std::stod(params[1]) / zoom;
290 double outerRadius = std::stod(params[2]) / zoom;
292 double startAngle = std::stod(params[3]);
293 double endAngle = std::stod(params[4]);
295 double centerAngle = (startAngle + endAngle) / 2;
296 if (endAngle < startAngle)
297 centerAngle = std::fmod(centerAngle + M_PI, 2 * M_PI);
299 double angleRange = std::fmod(endAngle - startAngle, 2 * M_PI);
300 angleRange = angleRange >= 0 ? angleRange : angleRange + 2 * M_PI;
303 centerAngle = std::fmod(3 * M_PI - centerAngle, 2 * M_PI);
305 double xOffset = viewport.at(
"Translation")[0];
306 double yOffset = viewport.at(
"Translation")[1];
308 double centerX = -(std::stod(params[5]) - xOffset) / zoom;
309 double centerY = (std::stod(params[6]) - yOffset) / zoom;
327 [&wedge](
const auto ¶ms) { return wedge.isSymmetric(params); });
340 <<
" degrees." << std::endl;
355 const auto &spectrumInfo = inputWS->spectrumInfo();
356 const V3D sourcePos = spectrumInfo.sourcePosition();
357 const V3D samplePos = spectrumInfo.samplePosition();
359 const V3D beamLine = samplePos - sourcePos;
361 const auto up = inputWS->getInstrument()->getReferenceFrame()->vecPointingUp();
362 double monoWavelength = 0;
364 if (inputWS->run().hasProperty(
"wavelength")) {
365 monoWavelength = inputWS->run().getPropertyAsSingleValue(
"wavelength");
367 throw std::runtime_error(
"Could not find wavelength in the sample logs.");
374 const auto i =
static_cast<size_t>(
index);
376 if (!spectrumInfo.hasDetectors(i) || spectrumInfo.isMonitor(i) || spectrumInfo.isMasked(i)) {
381 std::vector<size_t> maskedBins;
383 if (inputWS->hasMaskedBins(i)) {
384 maskedBins = inputWS->maskedBinsIndices(i);
388 const auto &XIn = inputWS->x(i);
389 const auto &YIn = inputWS->y(i);
390 const auto &EIn = inputWS->e(i);
393 const V3D pos = spectrumInfo.position(i) - samplePos;
400 for (
size_t j = 0; j <
m_nBins; ++j) {
403 if (std::binary_search(maskedBins.cbegin(), maskedBins.cend(), j)) {
407 const double wavelength =
m_isMonochromatic ? monoWavelength : (XIn[j] + XIn[j + 1]) / 2.;
426 const double sinTheta = sin(0.5 *
position.angle(beamLine));
427 const double q = 4.0 * M_PI * sinTheta / wavelength;
456 m_errors[0][j][k] += w * w * EIn[j] * EIn[j];
460 for (
size_t iw = 0; iw <
m_nWedges; ++iw) {
466 double angle = std::fabs((subPix - center).angle(
V3D(cos(centerAngle), sin(centerAngle), 0.0)));
470 bool isWithinAngularRange =
476 if (isWithinAngularRange && isWithinRadii) {
480 m_errors[iw + 1][j][k] += w * w * EIn[j] * EIn[j];
504 auto wsgroup = std::make_shared<WorkspaceGroup>();
507 for (
size_t iw = 0; iw <
m_nWedges; ++iw) {
510 wsgroup->addWorkspace(wedgeWs);
514 if (outputWSGroupName.empty()) {
516 outputWSGroupName = outputWSName +
"_wedges";
522 for (
size_t iout = 0; iout <
m_nWedges + 1; ++iout) {
524 auto ws = (iout == 0) ? outputWS : std::dynamic_pointer_cast<MatrixWorkspace>(wsgroup->getItem(iout - 1));
543 for (
size_t iSample = 0; iSample <
m_nBins; ++iSample) {
544 auto &YOut = outputWS->mutableY(iSample);
545 auto &EOut = outputWS->mutableE(iSample);
548 for (
int iq = 0; iq < static_cast<int>(
m_nQ); ++iq) {
553 EOut[iq] =
m_errors[iout][iSample][iq] / (norm * norm);
568 auto &YOut = outputWS->mutableY(0);
569 auto &EOut = outputWS->mutableE(0);
571 std::vector<double> normLambda(
m_nQ, 0.0);
573 for (
size_t il = 0; il <
m_nBins; ++il) {
575 for (
int iq = 0; iq < static_cast<int>(
m_nQ); ++iq) {
580 EOut[iq] +=
m_errors[iout][il][iq] / (norm * norm);
581 normLambda[iq] += 1.;
588 for (
size_t i = 0; i <
m_nQ; ++i) {
589 YOut[i] /= normLambda[i];
590 EOut[i] = sqrt(EOut[i]) / normLambda[i];
603 const std::vector<double> &binEdges,
const size_t nSpectra) {
606 outputWS->getAxis(0)->unit() = UnitFactory::Instance().create(
"MomentumTransfer");
607 for (
size_t iSpectra = 0; iSpectra <
nSpectra; ++iSpectra) {
608 outputWS->setBinEdges(iSpectra, binEdges);
610 outputWS->setYUnitLabel(
"1/cm");
611 outputWS->setDistribution(
true);
#define DECLARE_ALGORITHM(classname)
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.
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.
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
bool isDefault(const std::string &name) const
void setPropertyValue(const std::string &name, const std::string &value) override
Set the value of a property by string N.B.
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.
Helper class for reporting progress from algorithms.
A property class for workspaces.
A validator which checks that the unit of the workspace referred to by a WorkspaceProperty is the exp...
A helper class for calculating neutron's gravitional drop.
double gravitationalDrop(const double wav) const
void getTableShapes()
Q1DWeighted::getTableShapes if the user provided a shape table, parse the stored values and get the v...
void bootstrap(const API::MatrixWorkspace_const_sptr &)
Q1DWeighted::bootstrap initializes the user inputs.
void fillTOFOutput(API::MatrixWorkspace_sptr &, const size_t)
Q1DWeighted::fillTOFOutput Fill in the output workspace for TOF input, averaging over lambda bins.
std::vector< Wedge > m_wedgesParameters
std::vector< std::vector< std::vector< double > > > m_intensities
bool checkIfSymetricalWedge(Wedge &Wedge)
Q1DWeighted::checkIfSymetricalWedge Check if the symetrical wedge to the one defined by the parameter...
void fillMonochromaticOutput(API::MatrixWorkspace_sptr &, const size_t)
Q1DWeighted::fillMonochromaticOutput Fill the output workspace for monochromatic, kinetic input.
std::vector< std::vector< std::vector< double > > > m_errors
void finalize(const API::MatrixWorkspace_const_sptr &)
Q1DWeighted::finalize performs final averaging and sets the output workspaces.
void init() override
Initialisation code.
void getViewportParams(const std::string &, std::map< std::string, std::vector< double > > &)
Q1DWeighted::getViewportParams get the parameters defining the viewport of the instrument view when t...
std::vector< double > m_qBinEdges
void getWedgeParams(const std::vector< std::string > &, const std::map< std::string, std::vector< double > > &)
Q1DWeighted::getWedgeParams.
std::vector< std::vector< std::vector< double > > > m_normalisation
API::MatrixWorkspace_sptr createOutputWorkspace(const API::MatrixWorkspace_const_sptr &, const size_t, const std::vector< double > &, const size_t)
Create an output workspace.
void checkIfSuperposedWedges()
Q1DWeighted::checkIfSuperposedWedges Check if some wedges ahev the same angleMiddle,...
void calculate(const API::MatrixWorkspace_const_sptr &)
Q1DWeighted::calculate Performs the azimuthal averaging for each wavelength bin.
void exec() override
Execution code.
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 error(const std::string &msg)
Logs at error level.
void warning(const std::string &msg)
Logs at warning level.
void information(const std::string &msg)
Logs at information level.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
double distance(const V3D &v) const noexcept
Calculates the distance between two vectors.
std::shared_ptr< ITableWorkspace > ITableWorkspace_sptr
shared pointer to Mantid::API::ITableWorkspace
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 deg2rad
Defines units/enum for Crystal work.
size_t MANTID_KERNEL_DLL indexOfValueFromEdges(const std::vector< double > &bin_edges, const double value)
Gets the bin of a value from a vector of bin edges.
int MANTID_KERNEL_DLL createAxisFromRebinParams(const std::vector< double > ¶ms, std::vector< double > &xnew, const bool resize_xnew=true, const bool full_bins_only=false, const double xMinHint=std::nan(""), const double xMaxHint=std::nan(""), const bool useReverseLogarithmic=false, const double power=-1)
Creates a new output X array given a 'standard' set of rebinning parameters.
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.