Mantid
Loading...
Searching...
No Matches
TOFSANSResolutionByPixel.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 +
21
22#include "boost/lexical_cast.hpp"
23
24namespace Mantid::Algorithms {
25
26// Register the algorithm into the AlgorithmFactory
27DECLARE_ALGORITHM(TOFSANSResolutionByPixel)
28
29using namespace Kernel;
30using namespace API;
31using namespace Geometry;
32using namespace DataObjects;
33
35
37 declareProperty(std::make_unique<WorkspaceProperty<>>("InputWorkspace", "", Direction::Input,
38 std::make_shared<WorkspaceUnitValidator>("Wavelength")),
39 "Name the workspace to calculate the resolution for, for "
40 "each pixel and wavelength");
41 declareProperty(std::make_unique<WorkspaceProperty<Workspace>>("OutputWorkspace", "", Direction::Output),
42 "Name of the newly created workspace which contains the Q resolution.");
43 auto positiveDouble = std::make_shared<BoundedValidator<double>>();
44 positiveDouble->setLower(0);
45 declareProperty("DeltaR", 0.0, positiveDouble, "Virtual ring width on the detector (mm).");
46 declareProperty("SampleApertureRadius", 0.0, positiveDouble, "Sample aperture radius, R2 (mm).");
47 declareProperty("SourceApertureRadius", 0.0, positiveDouble, "Source aperture radius, R1 (mm).");
48 declareProperty(std::make_unique<WorkspaceProperty<>>("SigmaModerator", "", Direction::Input,
49 std::make_shared<WorkspaceUnitValidator>("Wavelength")),
50 "Moderator time spread (microseconds) as a"
51 "function of wavelength (Angstroms).");
52 declareProperty("CollimationLength", 0.0, positiveDouble, "Collimation length (m)");
53 declareProperty("AccountForGravity", false, "Whether to correct for the effects of gravity");
54 declareProperty("ExtraLength", 0.0, positiveDouble, "Additional length for gravity correction.");
55}
56
57/*
58 * Double Boltzmann fit to the TOF resolution as a function of wavelength
59 */
64
66 MatrixWorkspace_sptr inWS = getProperty("InputWorkspace");
67 double deltaR = getProperty("DeltaR");
68 double R1 = getProperty("SourceApertureRadius");
69 double R2 = getProperty("SampleApertureRadius");
70 const bool doGravity = getProperty("AccountForGravity");
71
72 // Check the input
73 checkInput(inWS);
74
75 // Setup outputworkspace
76 auto outWS = setupOutputWorkspace(inWS);
77
78 // Convert to meters
79 deltaR /= 1000.0;
80 R1 /= 1000.0;
81 R2 /= 1000.0;
82
83 // The moderator workspace needs to match the data workspace
84 // in terms of wavelength binning
85 const MatrixWorkspace_sptr sigmaModeratorVSwavelength = getModeratorWorkspace(inWS);
86
87 // create interpolation table from sigmaModeratorVSwavelength
88 Kernel::Interpolation lookUpTable;
89
90 const auto &xInterpolate = sigmaModeratorVSwavelength->points(0);
91 const auto &yInterpolate = sigmaModeratorVSwavelength->y(0);
92
93 // prefer the input to be a pointworkspace and create interpolation function
94 if (sigmaModeratorVSwavelength->isHistogramData()) {
95 g_log.notice() << "mid-points of SigmaModerator histogram bins will be "
96 "used for interpolation.";
97 }
98
99 for (size_t i = 0; i < xInterpolate.size(); ++i) {
100 lookUpTable.addPoint(xInterpolate[i], yInterpolate[i]);
101 }
102
103 // Calculate the L1 distance
104 const V3D samplePos = inWS->getInstrument()->getSample()->getPos();
105 const V3D sourcePos = inWS->getInstrument()->getSource()->getPos();
106 const V3D SSD = samplePos - sourcePos;
107 const double L1 = SSD.norm();
108
109 // Get the collimation length
110 double LCollim = getProperty("CollimationLength");
111
112 if (LCollim == 0.0) {
113 auto collimationLengthEstimator = SANSCollimationLengthEstimator();
114 LCollim = collimationLengthEstimator.provideCollimationLength(inWS);
115 g_log.information() << "No collimation length was specified. A default "
116 "collimation length was estimated to be "
117 << LCollim << '\n';
118 } else {
119 g_log.information() << "The collimation length is " << LCollim << '\n';
120 }
121
122 const auto numberOfSpectra = static_cast<int>(inWS->getNumberHistograms());
123 Progress progress(this, 0.0, 1.0, numberOfSpectra);
124
125 const auto &spectrumInfo = inWS->spectrumInfo();
126 for (int i = 0; i < numberOfSpectra; i++) {
128 if (!spectrumInfo.hasDetectors(i)) {
129 g_log.information() << "Workspace index " << i << " has no detector assigned to it - discarding\n";
130 continue;
131 }
132 // If no detector found or if it's masked or a monitor, skip onto the next
133 // spectrum
134 if (spectrumInfo.isMonitor(i) || spectrumInfo.isMasked(i))
135 continue;
136
137 const double L2 = spectrumInfo.l2(i);
139 const double waveLengthIndependentFactor = calculator.getWavelengthIndependentFactor(R1, R2, deltaR, LCollim, L2);
140
141 // Multiplicative factor to go from lambda to Q
142 // Don't get fooled by the function name...
143 const double theta = spectrumInfo.twoTheta(i);
144 double sinTheta = sin(0.5 * theta);
145 double factor = 4.0 * M_PI * sinTheta;
146
147 const auto &xIn = inWS->x(i);
148 const size_t xLength = xIn.size();
149
150 // Gravity correction
151 std::unique_ptr<GravitySANSHelper> grav;
152 if (doGravity) {
153 grav = std::make_unique<GravitySANSHelper>(spectrumInfo, i, getProperty("ExtraLength"));
154 }
155
156 // Get handles on the outputWorkspace
157 auto &yOut = outWS->mutableY(i);
158 // for each wavelenght bin of each pixel calculate a q-resolution
159 for (size_t j = 0; j < xLength - 1; j++) {
160 // use the midpoint of each bin
161 const double wl = (xIn[j + 1] + xIn[j]) / 2.0;
162 // Calculate q. Alternatively q could be calculated using ConvertUnit
163 // If we include a gravity correction we need to adjust sinTheta
164 // for each wavelength (in Angstrom)
165 if (doGravity) {
166 double sinThetaGrav = grav->calcSinTheta(wl);
167 factor = 4.0 * M_PI * sinThetaGrav;
168 }
169 const double q = factor / wl;
170
171 // wavelenght spread from bin assumed to be
172 const double sigmaSpreadFromBin = xIn[j + 1] - xIn[j];
173
174 // Get the uncertainty in Q
175 auto sigmaQ = calculator.getSigmaQValue(lookUpTable.value(wl), waveLengthIndependentFactor, q, wl,
176 sigmaSpreadFromBin, L1, L2);
177
178 // Insert the Q value and the Q resolution into the outputworkspace
179 yOut[j] = sigmaQ;
180 }
181 progress.report("Computing Q resolution");
182 }
183
184 // Set the y axis label
185 outWS->setYUnitLabel("QResolution");
186
187 setProperty("OutputWorkspace", outWS);
188}
189
196 auto duplicate = createChildAlgorithm("CloneWorkspace");
197 duplicate->initialize();
198 duplicate->setProperty<Workspace_sptr>("InputWorkspace", inputWorkspace);
199 duplicate->execute();
200 Workspace_sptr temp = duplicate->getProperty("OutputWorkspace");
201 return std::dynamic_pointer_cast<MatrixWorkspace>(temp);
202}
203
211
212 MatrixWorkspace_sptr sigmaModerator = getProperty("SigmaModerator");
213 auto rebinned = createChildAlgorithm("RebinToWorkspace");
214 rebinned->initialize();
215 rebinned->setProperty("WorkspaceToRebin", sigmaModerator);
216 rebinned->setProperty("WorkspaceToMatch", inputWorkspace);
217 rebinned->setPropertyValue("OutputWorkspace", "SigmaModeratorRebinned");
218 rebinned->execute();
219 MatrixWorkspace_sptr outWS = rebinned->getProperty("OutputWorkspace");
220 return outWS;
221}
222
228 // Make sure that input workspace has an instrument as we rely heavily on
229 // thisa
230 auto inst = inWS->getInstrument();
231 if (inst->getName().empty()) {
232 throw std::invalid_argument("TOFSANSResolutionByPixel: The input workspace "
233 "does not contain an instrument");
234 }
235}
236
237} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:538
#define UNUSED_ARG(x)
Function arguments are sometimes unused in certain implmentations but are required for documentation ...
Definition System.h:48
Base class from which all concrete algorithm classes should be derived.
Definition Algorithm.h:76
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
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.
Kernel::Logger & g_log
Definition Algorithm.h:422
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
Helper class for reporting progress from algorithms.
Definition Progress.h:25
A property class for workspaces.
Helper class which provides the uncertainty calculations for the TOFSANSResolutionByPixel class.
double getSigmaQValue(double moderatorValue, double wavlengthIndependentFactor, double q, double wavelength, double deltaWavelength, double l1, double l2) const
double getWavelengthIndependentFactor(double r1, double r2, double deltaR, double lCollim, double l2) const
Calculates the wavelength-independent prefactor for the resolutin calculation.
Mantid::API::MatrixWorkspace_sptr setupOutputWorkspace(const Mantid::API::MatrixWorkspace_sptr &inputWorkspace)
Create an output workspace.
Mantid::API::MatrixWorkspace_sptr getModeratorWorkspace(const Mantid::API::MatrixWorkspace_sptr &inputWorkspace)
Get the moderator workspace.
void checkInput(const Mantid::API::MatrixWorkspace_sptr &inWS)
Check input.
virtual double getTOFResolution(double wl)
Return the TOF resolution for a particular wavelength.
double m_wl_resolution
Wavelength resolution (constant for all wavelengths)
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
Provide interpolation over a series of points.
double value(const double &at) const
get interpolated value at location at
void addPoint(const double &xx, const double &yy)
add data point
void notice(const std::string &msg)
Logs at notice level.
Definition Logger.cpp:126
void information(const std::string &msg)
Logs at information level.
Definition Logger.cpp:136
Class for 3D vectors.
Definition V3D.h:34
double norm() const noexcept
Definition V3D.h:269
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::shared_ptr< const Mantid::Geometry::IDetector > IDetector_const_sptr
Shared pointer to IDetector (const version)
Definition IDetector.h:102
@ Input
An input workspace.
Definition Property.h:53
@ Output
An output workspace.
Definition Property.h:54