Mantid
Loading...
Searching...
No Matches
SCDPanelErrors.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 +
12#include "MantidAPI/Sample.h"
22#include <algorithm>
23#include <boost/math/special_functions/round.hpp>
24#include <cmath>
25#include <fstream>
26#include <sstream>
27#include <utility>
28
29namespace Mantid::Crystal {
30
31using namespace CurveFitting;
32
33using namespace Kernel;
34
35using namespace API;
36
37namespace {
39Logger g_log("SCDPanelErrors");
40} // namespace
41
42DECLARE_FUNCTION(SCDPanelErrors)
43
45
47SCDPanelErrors::SCDPanelErrors() : m_setupFinished(false) {
48 declareParameter("XShift", 0.0, "Shift factor in X");
49 declareParameter("YShift", 0.0, "Shift factor in Y");
50 declareParameter("ZShift", 0.0, "Shift factor in Z");
51 declareParameter("XRotate", 0.0, "Rotate angle in X");
52 declareParameter("YRotate", 0.0, "Rotate angle in Y");
53 declareParameter("ZRotate", 0.0, "Rotate angle in Z");
54 declareParameter("ScaleWidth", 1.0, "Scale width of detector");
55 declareParameter("ScaleHeight", 1.0, "Scale height of detector");
56 declareParameter("T0Shift", 0.0, "Shift for TOF");
57 declareAttribute("FileName", Attribute("", true));
58 declareAttribute("Workspace", Attribute(""));
59 declareAttribute("Bank", Attribute(""));
60}
75void SCDPanelErrors::moveDetector(double x, double y, double z, double rotx, double roty, double rotz, double scalex,
76 double scaley, std::string detname, const Workspace_sptr &inputW) const {
77 if (detname.compare("none") == 0.0)
78 return;
79 // CORELLI has sixteenpack under bank
81 Kernel::DynamicPointerCastHelper::dynamicPointerCastWithCheck<DataObjects::PeaksWorkspace, API::Workspace>(
82 inputW);
83 Geometry::Instrument_sptr inst = std::const_pointer_cast<Geometry::Instrument>(inputP->getInstrument());
84 if (inst->getName().compare("CORELLI") == 0.0 && detname != "moderator")
85 detname.append("/sixteenpack");
86
87 if (x != 0.0 || y != 0.0 || z != 0.0) {
88 auto alg1 = Mantid::API::AlgorithmFactory::Instance().create("MoveInstrumentComponent", -1);
89 alg1->initialize();
90 alg1->setChild(true);
91 alg1->setLogging(false);
92 alg1->setProperty<Workspace_sptr>("Workspace", inputW);
93 alg1->setPropertyValue("ComponentName", detname);
94 // Move in m
95 alg1->setProperty("X", x);
96 alg1->setProperty("Y", y);
97 alg1->setProperty("Z", z);
98 alg1->setPropertyValue("RelativePosition", "1");
99 alg1->execute();
100 }
101
102 if (rotx != 0.0) {
103 auto algx = Mantid::API::AlgorithmFactory::Instance().create("RotateInstrumentComponent", -1);
104 algx->initialize();
105 algx->setChild(true);
106 algx->setLogging(false);
107 algx->setProperty<Workspace_sptr>("Workspace", inputW);
108 algx->setPropertyValue("ComponentName", detname);
109 algx->setProperty("X", 1.0);
110 algx->setProperty("Y", 0.0);
111 algx->setProperty("Z", 0.0);
112 algx->setProperty("Angle", rotx);
113 algx->setPropertyValue("RelativeRotation", "1");
114 algx->execute();
115 }
116
117 if (roty != 0.0) {
118 auto algy = Mantid::API::AlgorithmFactory::Instance().create("RotateInstrumentComponent", -1);
119 algy->initialize();
120 algy->setChild(true);
121 algy->setLogging(false);
122 algy->setProperty<Workspace_sptr>("Workspace", inputW);
123 algy->setPropertyValue("ComponentName", detname);
124 algy->setProperty("X", 0.0);
125 algy->setProperty("Y", 1.0);
126 algy->setProperty("Z", 0.0);
127 algy->setProperty("Angle", roty);
128 algy->setPropertyValue("RelativeRotation", "1");
129 algy->execute();
130 }
131
132 if (rotz != 0.0) {
133 auto algz = Mantid::API::AlgorithmFactory::Instance().create("RotateInstrumentComponent", -1);
134 algz->initialize();
135 algz->setChild(true);
136 algz->setLogging(false);
137 algz->setProperty<Workspace_sptr>("Workspace", inputW);
138 algz->setPropertyValue("ComponentName", detname);
139 algz->setProperty("X", 0.0);
140 algz->setProperty("Y", 0.0);
141 algz->setProperty("Z", 1.0);
142 algz->setProperty("Angle", rotz);
143 algz->setPropertyValue("RelativeRotation", "1");
144 algz->execute();
145 }
146 if (scalex != 1.0 || scaley != 1.0) {
147 Geometry::IComponent_const_sptr comp = inst->getComponentByName(detname);
148 std::shared_ptr<const Geometry::RectangularDetector> rectDet =
149 std::dynamic_pointer_cast<const Geometry::RectangularDetector>(comp);
150 if (rectDet) {
151 Geometry::ParameterMap &pmap = inputP->instrumentParameters();
152 auto oldscalex = pmap.getDouble(rectDet->getName(), "scalex");
153 auto oldscaley = pmap.getDouble(rectDet->getName(), "scaley");
154 double relscalex = scalex;
155 double relscaley = scaley;
156 if (!oldscalex.empty())
157 relscalex /= oldscalex[0];
158 if (!oldscaley.empty())
159 relscaley /= oldscaley[0];
160 pmap.addDouble(rectDet.get(), "scalex", scalex);
161 pmap.addDouble(rectDet.get(), "scaley", scaley);
162 applyRectangularDetectorScaleToComponentInfo(inputP->mutableComponentInfo(), rectDet->getComponentID(), relscalex,
163 relscaley);
164 }
165 }
166}
167
169void SCDPanelErrors::eval(double xshift, double yshift, double zshift, double xrotate, double yrotate, double zrotate,
170 double scalex, double scaley, double *out, const double *xValues, const size_t nData,
171 double tShift) const {
172 UNUSED_ARG(xValues);
173 if (nData == 0)
174 return;
175
176 setupData();
177
178 std::shared_ptr<API::Workspace> cloned = m_workspace->clone();
179 moveDetector(xshift, yshift, zshift, xrotate, yrotate, zrotate, scalex, scaley, m_bank, cloned);
180
181 auto inputP =
182 Kernel::DynamicPointerCastHelper::dynamicPointerCastWithCheck<DataObjects::PeaksWorkspace, API::Workspace>(
183 std::move(cloned));
184 auto inst = inputP->getInstrument();
185 Geometry::OrientedLattice lattice = inputP->mutableSample().getOrientedLattice();
186 for (int i = 0; i < inputP->getNumberPeaks(); i++) {
187 const DataObjects::Peak &peak = inputP->getPeak(i);
188 V3D hkl = V3D(boost::math::iround(peak.getH()), boost::math::iround(peak.getK()), boost::math::iround(peak.getL()));
189 V3D Q2 = lattice.qFromHKL(hkl);
190 try {
191 if (hkl == V3D(0, 0, 0))
192 throw std::runtime_error("unindexed peak");
193 DataObjects::Peak peak2(inst, peak.getDetectorID(), peak.getWavelength(), hkl, peak.getGoniometerMatrix());
195
196 wl.initialize(peak2.getL1(), 0, {{UnitParams::l2, peak2.getL2()}, {UnitParams::twoTheta, peak2.getScattering()}});
197 peak2.setWavelength(wl.singleFromTOF(peak.getTOF() + tShift));
198 V3D Q3 = peak2.getQSampleFrame();
199 out[i * 3] = Q3[0] - Q2[0];
200 out[i * 3 + 1] = Q3[1] - Q2[1];
201 out[i * 3 + 2] = Q3[2] - Q2[2];
202 } catch (std::runtime_error &) {
203 // set penalty for unindexed peaks greater than tolerance
204 out[i * 3] = 0.15;
205 out[i * 3 + 1] = 0.15;
206 out[i * 3 + 2] = 0.15;
207 }
208 }
209}
210
217void SCDPanelErrors::function1D(double *out, const double *xValues, const size_t nData) const {
218 const double xshift = getParameter("XShift");
219 const double yshift = getParameter("YShift");
220 const double zshift = getParameter("ZShift");
221 const double xrotate = getParameter("XRotate");
222 const double yrotate = getParameter("YRotate");
223 const double zrotate = getParameter("ZRotate");
224 const double scalex = getParameter("ScaleWidth");
225 const double scaley = getParameter("ScaleHeight");
226 const double tShift = getParameter("T0Shift");
227 eval(xshift, yshift, zshift, xrotate, yrotate, zrotate, scalex, scaley, out, xValues, nData, tShift);
228}
229
237void SCDPanelErrors::functionDeriv1D(API::Jacobian *out, const double *xValues, const size_t nData) {
238 FunctionDomain1DView domain(xValues, nData);
239 this->calNumericalDeriv(domain, *out);
240}
241
243void SCDPanelErrors::clear() const { m_setupFinished = false; }
244
249void SCDPanelErrors::setAttribute(const std::string &attName, const IFunction::Attribute &value) {
250 if (attName == "FileName") {
251 std::string fileName = value.asUnquotedString();
252 if (fileName.empty()) {
253 storeAttributeValue("FileName", Attribute("", true));
254 return;
255 }
256 FileValidator fval;
257 std::string error = fval.isValid(fileName);
258 if (error.empty()) {
259 storeAttributeValue(attName, Attribute(fileName, true));
260 storeAttributeValue("Workspace", Attribute(""));
261 } else {
262 // file not found
263 throw Kernel::Exception::FileError(error, fileName);
264 }
265 load(fileName);
266 } else if (attName == "Workspace") {
267 std::string wsName = value.asString();
268 if (!wsName.empty()) {
269 storeAttributeValue(attName, value);
270 storeAttributeValue("FileName", Attribute("", true));
271 loadWorkspace(wsName);
272 }
273 } else {
275 m_setupFinished = false;
276 }
277}
278
283void SCDPanelErrors::load(const std::string &fname) {
284 auto loadAlg = Mantid::API::AlgorithmFactory::Instance().create("Load", -1);
285 loadAlg->initialize();
286 loadAlg->setChild(true);
287 loadAlg->setLogging(false);
288 try {
289 loadAlg->setPropertyValue("Filename", fname);
290 loadAlg->setPropertyValue("OutputWorkspace", "_SCDPanelErrors_fit_data_");
291 loadAlg->execute();
292 } catch (std::runtime_error &) {
293 throw std::runtime_error("Unable to load Nexus file for SCDPanelErrors function.");
294 }
295
296 Workspace_sptr ws = loadAlg->getProperty("OutputWorkspace");
297 API::Workspace_sptr resData = std::dynamic_pointer_cast<Mantid::API::Workspace>(ws);
298 loadWorkspace(resData);
299}
300
305void SCDPanelErrors::loadWorkspace(const std::string &wsName) const {
306 auto ws = AnalysisDataService::Instance().retrieveWS<API::Workspace>(wsName);
307 loadWorkspace(ws);
308}
309
314void SCDPanelErrors::loadWorkspace(std::shared_ptr<API::Workspace> ws) const {
315 m_workspace = std::move(ws);
316 m_setupFinished = false;
317}
318
322void SCDPanelErrors::setupData() const {
323 if (m_setupFinished) {
324 g_log.debug() << "Re-setting isn't required.";
325 return;
326 }
327
328 if (!m_workspace) {
329 std::string wsName = getAttribute("Workspace").asString();
330 if (wsName.empty())
331 throw std::invalid_argument("Data not set for function " + this->name());
332 else
333 loadWorkspace(wsName);
334 }
335
336 m_bank = getAttribute("Bank").asString();
337
338 g_log.debug() << "Setting up " << m_workspace->getName() << " bank " << m_bank << '\n';
339
340 m_setupFinished = true;
341}
342
343} // namespace Mantid::Crystal
std::string name
Definition Run.cpp:60
double value
The value of the point.
Definition FitMW.cpp:51
#define DECLARE_FUNCTION(classname)
Macro for declaring a new type of function to be used with the FunctionFactory.
double error
Mantid::API::IFunction::Attribute Attribute
#define UNUSED_ARG(x)
Function arguments are sometimes unused in certain implmentations but are required for documentation ...
Definition System.h:48
1D domain - a wrapper around an array of doubles.
Attribute is a non-fitting parameter.
Definition IFunction.h:285
void declareAttribute(const std::string &name, const API::IFunction::Attribute &defaultValue)
Declare a single attribute.
virtual void setAttribute(const std::string &name, const Attribute &)
Set a value to attribute attName.
Represents the Jacobian in IFitFunction::functionDeriv.
Definition Jacobian.h:22
void declareParameter(const std::string &name, double initValue=0, const std::string &description="") override
Declare a new parameter.
Base Workspace Abstract Class.
Definition Workspace.h:29
void moveDetector(double x, double y, double z, double rotx, double roty, double rotz, double scalex, double scaley, std::string detname, const API::Workspace_sptr &inputW) const
Move detectors with parameters.
std::string m_bank
Stores bank.
static const int defaultIndexValue
The default value for the workspace index.
std::shared_ptr< API::Workspace > m_workspace
Temporary workspace holder.
void setupData() const
Fill in the workspace and bank names.
void eval(double xshift, double yshift, double zshift, double xrotate, double yrotate, double zrotate, double scalex, double scaley, double *out, const double *xValues, const size_t nData, double tShift) const
Evaluate the function for a list of arguments and given scaling factor.
double getL() const override
Get the L index of the peak.
Definition BasePeak.cpp:99
double getK() const override
Get the K index of the peak.
Definition BasePeak.cpp:96
double getH() const override
Get the H index of the peak.
Definition BasePeak.cpp:93
Mantid::Kernel::Matrix< double > getGoniometerMatrix() const override
Get the goniometer rotation matrix at which this peak was measured.
Definition BasePeak.cpp:209
Structure describing a single-crystal peak.
Definition Peak.h:34
double getL1() const override
Return the L1 flight path length (source to sample), in meters.
Definition Peak.cpp:724
int getDetectorID() const override
Get the ID of the detector at the center of the peak
Definition Peak.cpp:265
double getWavelength() const override
Calculate the neutron wavelength (in angstroms) at the peak (Note for inelastic scattering - it is th...
Definition Peak.cpp:358
double getTOF() const override
Calculate the time of flight (in microseconds) of the neutrons for this peak, using the geometry of t...
Definition Peak.cpp:373
Class to implement UB matrix.
Kernel::V3D qFromHKL(const Kernel::V3D &hkl) const
Calculate the hkl corresponding to a given Q-vector.
Records the filename and the description of failure.
Definition Exception.h:98
FileValidator is a validator that checks that a filepath is valid.
void debug(const std::string &msg)
Logs at debug level.
Definition Logger.cpp:145
void initialize(const double &_l1, const int &_emode, const UnitParametersMap &params)
Initialize the unit to perform conversion using singleToTof() and singleFromTof()
Definition Unit.cpp:133
Wavelength in Angstrom.
Definition Unit.h:267
Class for 3D vectors.
Definition V3D.h:34
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
Kernel::Logger g_log("ExperimentInfo")
static logger object
MANTID_API_DLL void applyRectangularDetectorScaleToComponentInfo(Geometry::ComponentInfo &componentInfo, Geometry::IComponent *componentId, const double scaleX, const double scaleY)
Helpers for resizing RectangularDetectors.
std::shared_ptr< PeaksWorkspace > PeaksWorkspace_sptr
Typedef for a shared pointer to a peaks workspace.
std::shared_ptr< const IComponent > IComponent_const_sptr
Typdef of a shared pointer to a const IComponent.
Definition IComponent.h:167
std::shared_ptr< Instrument > Instrument_sptr
Shared pointer to an instrument object.
Generate a tableworkspace to store the calibration results.
adjust instrument component position and orientation
: detector size scale at y-direction