Mantid
Loading...
Searching...
No Matches
CalculateDynamicRange.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 +
8#include "MantidAPI/Axis.h"
9#include "MantidAPI/Run.h"
13#include "MantidHistogramData/HistogramIterator.h"
15#include "MantidKernel/Unit.h"
16
17namespace {
23double calculateQ(const double lambda, const double twoTheta) {
24 return (4 * M_PI * std::sin(twoTheta * (M_PI / 180) / 2)) / (lambda);
25}
26} // namespace
27
28namespace Mantid::Algorithms {
29
30using namespace Mantid::API;
31using namespace Mantid::Kernel;
32using namespace Mantid::Geometry;
33
34// Register the algorithm into the AlgorithmFactory
35DECLARE_ALGORITHM(CalculateDynamicRange)
36
37//----------------------------------------------------------------------------------------------
38
39
40const std::string CalculateDynamicRange::name() const { return "CalculateDynamicRange"; }
41
43int CalculateDynamicRange::version() const { return 1; }
44
46const std::string CalculateDynamicRange::category() const { return "Utility\\Workspaces"; }
47
49const std::string CalculateDynamicRange::summary() const {
50 return "Calculates and sets Qmin and Qmax of a SANS workspace";
51}
52
54std::map<std::string, std::string> CalculateDynamicRange::validateInputs() {
55 std::map<std::string, std::string> issues;
57 if (!workspace) {
58 issues["InputWorkspace"] = "The InputWorkspace must be a MatrixWorkspace.";
59 } else if (workspace->getAxis(0)->unit()->unitID() != "Wavelength" && !workspace->run().hasProperty("wavelength")) {
60 issues["InputWorkspace"] = "If the workspace is not in units of wavelength it must have a sample log wavelength.";
61 }
62 return issues;
63}
64
65//----------------------------------------------------------------------------------------------
70 "An input workspace.");
71
72 declareProperty(std::make_unique<Mantid::Kernel::ArrayProperty<std::string>>("ComponentNames"),
73 "List of component names to calculate the q ranges for.");
74}
75
82void CalculateDynamicRange::calculateQMinMax(const MatrixWorkspace_sptr &workspace, const std::vector<size_t> &indices,
83 const std::string &compName = "") {
84 const auto &spectrumInfo = workspace->spectrumInfo();
85 const auto unit = workspace->getAxis(0)->unit()->unitID();
86 double constantLambda = 0;
87 if (workspace->run().hasProperty("wavelength"))
88 constantLambda = workspace->run().getLogAsSingleValue("wavelength");
89 double min = std::numeric_limits<double>::max(), max = std::numeric_limits<double>::lowest();
90 // PARALLEL_FOR_NO_WSP_CHECK does not work with range-based for so NOLINT this
91 // block
93 for (int64_t index = 0; index < static_cast<int64_t>(indices.size()); ++index) { // NOLINT (modernize-for-loop)
94 if (spectrumInfo.hasDetectors(indices[index]) && !spectrumInfo.isMonitor(indices[index]) &&
95 !spectrumInfo.isMasked(indices[index])) {
96 const auto &spectrum = workspace->histogram(indices[index]);
97 const Kernel::V3D detPos = spectrumInfo.position(indices[index]);
98 double r, theta, phi;
99 detPos.getSpherical(r, theta, phi);
100 if (unit != "Wavelength") {
101 const double q = calculateQ(constantLambda, theta);
103 min = std::min(min, q);
104 max = std::max(max, q);
105 }
106 } else {
107 // Use the bin centers
108 const double q1 = calculateQ(spectrum.begin()->center(), theta);
109 const double q2 = calculateQ(std::prev(spectrum.end())->center(), theta);
111 min = std::min(min, std::min(q1, q2));
112 max = std::max(max, std::max(q1, q2));
113 }
114 }
115 }
116 }
117 auto &run = workspace->mutableRun();
118 std::string qminLogName = "qmin";
119 std::string qmaxLogName = "qmax";
120 if (!compName.empty()) {
121 qminLogName += "_" + compName;
122 qmaxLogName += "_" + compName;
123 }
124 run.addProperty<double>(qminLogName, min, true);
125 run.addProperty<double>(qmaxLogName, max, true);
126}
127
128//----------------------------------------------------------------------------------------------
133 const size_t nHist = workspace->getNumberHistograms();
134 std::vector<size_t> allIndices(nHist);
135 for (size_t i = 0; i < nHist; ++i) {
136 allIndices.emplace_back(i);
137 }
138 calculateQMinMax(workspace, allIndices);
139 const std::vector<std::string> componentNames = getProperty("ComponentNames");
140 if (!componentNames.empty()) {
141 const auto instrument = workspace->getInstrument();
142 if (!instrument) {
143 g_log.error() << "No instrument in input workspace. Ignoring ComponentList\n";
144 return;
145 }
146 for (const auto &compName : componentNames) {
147 std::vector<detid_t> detIDs;
148 std::vector<IDetector_const_sptr> dets;
149 instrument->getDetectorsInBank(dets, compName);
150 if (dets.empty()) {
151 const auto component = instrument->getComponentByName(compName);
152 const auto det = std::dynamic_pointer_cast<const IDetector>(component);
153 if (!det) {
154 g_log.error() << "No detectors found in component '" << compName << "'\n";
155 continue;
156 }
157 dets.emplace_back(det);
158 }
159 if (!dets.empty()) {
160 detIDs.reserve(dets.size());
161 std::transform(dets.begin(), dets.end(), std::back_inserter(detIDs),
162 [](const auto &det) { return det->getID(); });
163
164 const auto indices = workspace->getIndicesFromDetectorIDs(detIDs);
165 calculateQMinMax(workspace, indices, compName);
166 }
167 }
168 }
169}
170
171} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
const std::vector< double > * lambda
IPeaksWorkspace_sptr workspace
Definition: IndexPeaks.cpp:114
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
#define PARALLEL_FOR_NO_WSP_CHECK()
#define PARALLEL_CRITICAL(name)
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
Definition: Algorithm.cpp:1913
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
Kernel::Logger & g_log
Definition: Algorithm.h:451
A property class for workspaces.
CalculateDynamicRange Calculates the Qmin and Qmax of SANS workspace, sets to sample logs.
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 init() override
Initialize the algorithm's properties.
void calculateQMinMax(const API::MatrixWorkspace_sptr &, const std::vector< size_t > &, const std::string &)
Calculates the max and min Q for given list of workspace indices.
std::map< std::string, std::string > validateInputs() override
Validate inputs.
const std::string category() const override
Algorithm's category for identification.
void exec() override
Execute the algorithm.
Support for a property that holds an array of values.
Definition: ArrayProperty.h:28
void error(const std::string &msg)
Logs at error level.
Definition: Logger.cpp:77
Class for 3D vectors.
Definition: V3D.h:34
void getSpherical(double &R, double &theta, double &phi) const noexcept
Return the vector's position in spherical coordinates.
Definition: V3D.cpp:117
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
STL namespace.
@ InOut
Both an input & output workspace.
Definition: Property.h:55