Mantid
Loading...
Searching...
No Matches
SofQWPolygon.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
17#include "MantidIndexing/IndexInfo.h"
19#include "MantidTypes/SpectrumDefinition.h"
20
21namespace Mantid::Algorithms {
22
23// Register the algorithm into the AlgorithmFactory
24DECLARE_ALGORITHM(SofQWPolygon)
25
26using namespace Mantid::API;
27using namespace Mantid::Kernel;
28using namespace Mantid::Geometry;
29
31SofQWPolygon::SofQWPolygon() : Rebin2D(), m_Qout(), m_thetaPts(), m_thetaWidth(0.0) {}
32
37
42 MatrixWorkspace_const_sptr inputWS = getProperty("InputWorkspace");
43
44 // Progress reports & cancellation
45 const auto blocksize = inputWS->blocksize();
46 const auto nreports(static_cast<size_t>(inputWS->getNumberHistograms() * blocksize));
47 m_progress = std::make_unique<API::Progress>(this, 0.0, 1.0, nreports);
48 // Compute input caches
49 this->initCachedValues(inputWS);
50
51 MatrixWorkspace_sptr outputWS = SofQW::setUpOutputWorkspace<DataObjects::Workspace2D>(
52 *inputWS, getProperty("QAxisBinning"), m_Qout, getProperty("EAxisBinning"), m_EmodeProperties);
53 setProperty("OutputWorkspace", outputWS);
54 const size_t nenergyBins = blocksize;
55
56 const size_t nTheta = m_thetaPts.size();
57 const auto &X = inputWS->x(0);
58
59 // Holds the spectrum-detector mapping
60 std::vector<SpectrumDefinition> detIDMapping(outputWS->getNumberHistograms());
61
62 PARALLEL_FOR_IF(Kernel::threadSafe(*inputWS, *outputWS))
63 for (int64_t i = 0; i < static_cast<int64_t>(nTheta); ++i) // signed for openmp
64 {
66
67 const double theta = m_thetaPts[i];
68 if (theta < 0.0) // One to skip
69 {
70 continue;
71 }
72
73 const auto &spectrumInfo = inputWS->spectrumInfo();
74 const auto *det = m_EmodeProperties.m_emode == 1 ? nullptr : &spectrumInfo.detector(i);
75 const double halfWidth(0.5 * m_thetaWidth);
76 const double thetaLower = theta - halfWidth;
77 const double thetaUpper = theta + halfWidth;
78
79 for (size_t j = 0; j < nenergyBins; ++j) {
80 m_progress->report("Computing polygon intersections");
81 // For each input polygon test where it intersects with
82 // the output grid and assign the appropriate weights of Y/E
83 const double dE_j = X[j];
84 const double dE_jp1 = X[j + 1];
85
86 const double lrQ = m_EmodeProperties.q(dE_jp1, thetaLower, det);
87
88 const V2D ll(dE_j, m_EmodeProperties.q(dE_j, thetaLower, det));
89 const V2D lr(dE_jp1, lrQ);
90 const V2D ur(dE_jp1, m_EmodeProperties.q(dE_jp1, thetaUpper, det));
91 const V2D ul(dE_j, m_EmodeProperties.q(dE_j, thetaUpper, det));
92 Quadrilateral inputQ = Quadrilateral(ll, lr, ur, ul);
93
94 DataObjects::FractionalRebinning::rebinToOutput(inputQ, inputWS, i, j, *outputWS, m_Qout);
95
96 // Find which q bin this point lies in
97 const MantidVec::difference_type qIndex = std::upper_bound(m_Qout.begin(), m_Qout.end(), lrQ) - m_Qout.begin();
98 if (qIndex != 0 && qIndex < static_cast<int>(m_Qout.size())) {
99 // Add this spectra-detector pair to the mapping
100 PARALLEL_CRITICAL(SofQWPolygon_spectramap) {
101 // Could do a more complete merge of spectrum definitions here, but
102 // historically only the ID of the first detector in the spectrum is
103 // used, so I am keeping that for now.
104 detIDMapping[qIndex - 1].add(spectrumInfo.spectrumDefinition(i)[0].first);
105 }
106 }
107 }
108
110 }
112
114
115 // Set the output spectrum-detector mapping
116 auto outputIndices = outputWS->indexInfo();
117 outputIndices.setSpectrumDefinitions(std::move(detIDMapping));
118 outputWS->setIndexInfo(outputIndices);
119
120 // Replace any NaNs in outputWorkspace with zeroes
121 if (this->getProperty("ReplaceNaNs")) {
122 auto replaceNans = this->createChildAlgorithm("ReplaceSpecialValues");
123 replaceNans->setChild(true);
124 replaceNans->initialize();
125 replaceNans->setProperty("InputWorkspace", outputWS);
126 replaceNans->setProperty("OutputWorkspace", outputWS);
127 replaceNans->setProperty("NaNValue", 0.0);
128 replaceNans->setProperty("InfinityValue", 0.0);
129 replaceNans->setProperty("BigNumberThreshold", DBL_MAX);
130 replaceNans->execute();
131 }
132}
133
140 // Index theta cache
142}
143
153 const size_t nhist = workspace.getNumberHistograms();
154 m_thetaPts = std::vector<double>(nhist);
155 size_t ndets(0);
156 double minTheta(DBL_MAX), maxTheta(-DBL_MAX);
157
158 const auto &spectrumInfo = workspace.spectrumInfo();
159 for (int64_t i = 0; i < static_cast<int64_t>(nhist); ++i) {
160 m_progress->report("Calculating detector angles");
161 m_thetaPts[i] = -1.0; // Indicates a detector to skip
162 if (!spectrumInfo.hasDetectors(i) || spectrumInfo.isMonitor(i))
163 continue;
164 // Check to see if there is an EFixed, if not skip it
165 try {
166 m_EmodeProperties.getEFixed(spectrumInfo.detector(i));
167 } catch (std::runtime_error &) {
168 continue;
169 }
170 ++ndets;
171 const double theta = spectrumInfo.twoTheta(i);
172 m_thetaPts[i] = theta;
173 minTheta = std::min(minTheta, theta);
174 maxTheta = std::max(maxTheta, theta);
175 }
176
177 if (0 == ndets)
178 throw std::runtime_error("Unexpected inconsistency found. The number of detectors is 0"
179 ", and the theta width parameter cannot be calculated.");
180
181 m_thetaWidth = (maxTheta - minTheta) / static_cast<double>(ndets);
182 g_log.information() << "Calculated detector width in theta=" << (m_thetaWidth * 180.0 / M_PI) << " degrees.\n";
183}
184
185} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
IPeaksWorkspace_sptr workspace
Definition: IndexPeaks.cpp:114
#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...
Definition: MultiThreaded.h:94
#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.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
virtual std::shared_ptr< Algorithm > createChildAlgorithm(const std::string &name, const double startProgress=-1., const double endProgress=-1., const bool enableLogging=true, const int &version=-1)
Create a Child Algorithm.
Definition: Algorithm.cpp:842
Kernel::Logger & g_log
Definition: Algorithm.h:451
Base MatrixWorkspace Abstract Class.
Rebins both axes of a two-dimensional workspace to the given parameters.
Definition: Rebin2D.h:24
std::unique_ptr< API::Progress > m_progress
Progress reporter.
Definition: Rebin2D.h:41
double m_thetaWidth
Theta width.
Definition: SofQWPolygon.h:76
void init() override
Initialize the algorithm.
void initThetaCache(const API::MatrixWorkspace &workspace)
Init the theta index.
std::vector< double > m_thetaPts
Input theta points.
Definition: SofQWPolygon.h:74
SofQWPolygon()
Default constructor.
void initCachedValues(const API::MatrixWorkspace_const_sptr &workspace)
Init variables cache base on the given workspace.
void exec() override
Run the algorithm.
std::vector< double > m_Qout
Output Q axis.
Definition: SofQWPolygon.h:72
static void createCommonInputProperties(API::Algorithm &alg)
Create the input properties on the given algorithm object.
Definition: SofQW.cpp:69
A ConvexPolygon with only 4 vertices.
Definition: Quadrilateral.h:24
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void information(const std::string &msg)
Logs at information level.
Definition: Logger.cpp:105
Implements a 2-dimensional vector embedded in a 3D space, i.e.
Definition: V2D.h:29
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
MANTID_DATAOBJECTS_DLL void normaliseOutput(const API::MatrixWorkspace_sptr &outputWS, const API::MatrixWorkspace_const_sptr &inputWS, API::Progress *progress=nullptr)
Compute sqrt of errors and put back in bin width division if necessary.
MANTID_DATAOBJECTS_DLL void rebinToOutput(const Geometry::Quadrilateral &inputQ, const API::MatrixWorkspace_const_sptr &inputWS, const size_t i, const size_t j, API::MatrixWorkspace &outputWS, const std::vector< double > &verticalAxis)
Rebin the input quadrilateral to to output grid.
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.
Definition: MultiThreaded.h:22
double getEFixed(const Geometry::IDetector &det) const
Get the efixed value for the given detector.
Definition: SofQCommon.cpp:72
double q(const double deltaE, const double twoTheta, const Geometry::IDetector *det) const
Calculate the Q value.
Definition: SofQCommon.cpp:101
void initCachedValues(const API::MatrixWorkspace &workspace, API::Algorithm *const hostAlgorithm)
The procedure analyses emode and efixed properties provided to the algorithm and identify the energy ...
Definition: SofQCommon.cpp:25