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 useAlgorithm("SofQWNormalisedPolygon");
33 deprecatedDate("2024-11-07");
34}
35
40
45 MatrixWorkspace_const_sptr inputWS = getProperty("InputWorkspace");
46
47 // Progress reports & cancellation
48 const auto blocksize = inputWS->blocksize();
49 const auto nreports(static_cast<size_t>(inputWS->getNumberHistograms() * blocksize));
50 m_progress = std::make_unique<API::Progress>(this, 0.0, 1.0, nreports);
51 // Compute input caches
52 this->initCachedValues(inputWS);
53
54 MatrixWorkspace_sptr outputWS = SofQW::setUpOutputWorkspace<DataObjects::Workspace2D>(
55 *inputWS, getProperty("QAxisBinning"), m_Qout, getProperty("EAxisBinning"), m_EmodeProperties);
56 setProperty("OutputWorkspace", outputWS);
57 const size_t nenergyBins = blocksize;
58
59 const size_t nTheta = m_thetaPts.size();
60 const auto &X = inputWS->x(0);
61
62 // Holds the spectrum-detector mapping
63 std::vector<SpectrumDefinition> detIDMapping(outputWS->getNumberHistograms());
64
65 PARALLEL_FOR_IF(Kernel::threadSafe(*inputWS, *outputWS))
66 for (int64_t i = 0; i < static_cast<int64_t>(nTheta); ++i) // signed for openmp
67 {
69
70 const double theta = m_thetaPts[i];
71 if (theta < 0.0) // One to skip
72 {
73 continue;
74 }
75
76 const auto &spectrumInfo = inputWS->spectrumInfo();
77 const auto *det = m_EmodeProperties.m_emode == 1 ? nullptr : &spectrumInfo.detector(i);
78 const double halfWidth(0.5 * m_thetaWidth);
79 const double thetaLower = theta - halfWidth;
80 const double thetaUpper = theta + halfWidth;
81
82 for (size_t j = 0; j < nenergyBins; ++j) {
83 m_progress->report("Computing polygon intersections");
84 // For each input polygon test where it intersects with
85 // the output grid and assign the appropriate weights of Y/E
86 const double dE_j = X[j];
87 const double dE_jp1 = X[j + 1];
88
89 const double lrQ = m_EmodeProperties.q(dE_jp1, thetaLower, det);
90
91 const V2D ll(dE_j, m_EmodeProperties.q(dE_j, thetaLower, det));
92 const V2D lr(dE_jp1, lrQ);
93 const V2D ur(dE_jp1, m_EmodeProperties.q(dE_jp1, thetaUpper, det));
94 const V2D ul(dE_j, m_EmodeProperties.q(dE_j, thetaUpper, det));
95 Quadrilateral inputQ = Quadrilateral(ll, lr, ur, ul);
96
97 DataObjects::FractionalRebinning::rebinToOutput(inputQ, inputWS, i, j, *outputWS, m_Qout);
98
99 // Find which q bin this point lies in
100 const MantidVec::difference_type qIndex = std::upper_bound(m_Qout.begin(), m_Qout.end(), lrQ) - m_Qout.begin();
101 if (qIndex != 0 && qIndex < static_cast<int>(m_Qout.size())) {
102 // Add this spectra-detector pair to the mapping
103 PARALLEL_CRITICAL(SofQWPolygon_spectramap) {
104 // Could do a more complete merge of spectrum definitions here, but
105 // historically only the ID of the first detector in the spectrum is
106 // used, so I am keeping that for now.
107 detIDMapping[qIndex - 1].add(spectrumInfo.spectrumDefinition(i)[0].first);
108 }
109 }
110 }
111
113 }
115
117
118 // Set the output spectrum-detector mapping
119 auto outputIndices = outputWS->indexInfo();
120 outputIndices.setSpectrumDefinitions(std::move(detIDMapping));
121 outputWS->setIndexInfo(outputIndices);
122
123 // Replace any NaNs in outputWorkspace with zeroes
124 if (this->getProperty("ReplaceNaNs")) {
125 auto replaceNans = this->createChildAlgorithm("ReplaceSpecialValues");
126 replaceNans->setChild(true);
127 replaceNans->initialize();
128 replaceNans->setProperty("InputWorkspace", outputWS);
129 replaceNans->setProperty("OutputWorkspace", outputWS);
130 replaceNans->setProperty("NaNValue", 0.0);
131 replaceNans->setProperty("InfinityValue", 0.0);
132 replaceNans->setProperty("BigNumberThreshold", DBL_MAX);
133 replaceNans->execute();
134 }
135}
136
146
156 const size_t nhist = workspace.getNumberHistograms();
157 m_thetaPts = std::vector<double>(nhist);
158 size_t ndets(0);
159 double minTheta(DBL_MAX), maxTheta(-DBL_MAX);
160
161 const auto &spectrumInfo = workspace.spectrumInfo();
162 for (int64_t i = 0; i < static_cast<int64_t>(nhist); ++i) {
163 m_progress->report("Calculating detector angles");
164 m_thetaPts[i] = -1.0; // Indicates a detector to skip
165 if (!spectrumInfo.hasDetectors(i) || spectrumInfo.isMonitor(i))
166 continue;
167 // Check to see if there is an EFixed, if not skip it
168 try {
169 m_EmodeProperties.getEFixed(spectrumInfo.detector(i));
170 } catch (std::runtime_error &) {
171 continue;
172 }
173 ++ndets;
174 const double theta = spectrumInfo.twoTheta(i);
175 m_thetaPts[i] = theta;
176 minTheta = std::min(minTheta, theta);
177 maxTheta = std::max(maxTheta, theta);
178 }
179
180 if (0 == ndets)
181 throw std::runtime_error("Unexpected inconsistency found. The number of detectors is 0"
182 ", and the theta width parameter cannot be calculated.");
183
184 m_thetaWidth = (maxTheta - minTheta) / static_cast<double>(ndets);
185 g_log.information() << "Calculated detector width in theta=" << (m_thetaWidth * 180.0 / M_PI) << " degrees.\n";
186}
187
188} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:538
IPeaksWorkspace_sptr workspace
#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.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
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.
void deprecatedDate(const std::string &)
The date the algorithm was deprecated on.
void useAlgorithm(const std::string &, const int version=-1)
The algorithm to use instead of this one.
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.
void init() override
Initialize the algorithm.
void initThetaCache(const API::MatrixWorkspace &workspace)
Init the theta index.
std::vector< double > m_thetaPts
Input theta points.
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.
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.
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:136
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
Kernel::Logger g_log("DetermineSpinStateOrder")
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.
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 ...
double getEFixed(const Geometry::IDetector &det) const
Get the efixed value for the given detector.
double q(const double deltaE, const double twoTheta, const Geometry::IDetector *det) const
Calculate the Q value.