Mantid
Loading...
Searching...
No Matches
SCDCalibratePanels2ObjFunc.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2020 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 +
7
13#include "MantidAPI/Run.h"
14#include "MantidAPI/Sample.h"
19
20#include <boost/math/special_functions/round.hpp>
21#include <cmath>
22
23namespace Mantid::Crystal {
24
25using namespace Mantid::API;
26using namespace Mantid::CurveFitting;
27using namespace Mantid::DataObjects;
28using namespace Mantid::Geometry;
29using namespace Mantid::Kernel;
30
31namespace {
32// static logger
33Logger g_log("SCDCalibratePanels2ObjFunc");
34} // namespace
35
36DECLARE_FUNCTION(SCDCalibratePanels2ObjFunc)
37
38
42 // parameters for translation
43 declareParameter("DeltaX", 0.0, "relative shift along X in meter");
44 declareParameter("DeltaY", 0.0, "relative shift along Y in meter");
45 declareParameter("DeltaZ", 0.0, "relative shift along Z in meter");
46 // parameters for rotation
47 declareParameter("RotX", 0.0, "relative rotation around X in degree");
48 declareParameter("RotY", 0.0, "relative rotation around Y in degree");
49 declareParameter("RotZ", 0.0, "relative rotation around Z in degree");
50 // TOF offset for all peaks
51 // NOTE: need to have a non-zero value here
52 declareParameter("DeltaT0", 0.1, "delta of TOF");
53 // This part is for fine tuning the sample position
54 declareParameter("DeltaSampleX", 0.0, "relative shift of sample position along X.");
55 declareParameter("DeltaSampleY", 0.0, "relative shift of sample position along Y.");
56 declareParameter("DeltaSampleZ", 0.0, "relative shift of sample position along Z.");
57 // Detector size scale factors
58 declareParameter("ScaleX", 1.0, "Scale of detector along X-direction (i.e., width).");
59 declareParameter("ScaleY", 1.0, "Scale of detector along Y-direction (i.e., height).");
60}
61
62void SCDCalibratePanels2ObjFunc::setPeakWorkspace(IPeaksWorkspace_sptr &pws, const std::string &componentName,
63 const std::vector<double> &tofs) {
64 m_pws = pws->clone();
65 m_cmpt = componentName;
66
67 // Special adjustment for CORELLI
68 Instrument_sptr inst = std::const_pointer_cast<Instrument>(m_pws->getInstrument());
69 if (inst->getName().compare("CORELLI") == 0 && m_cmpt != "moderator")
70 // the second check is just to ensure that no accidental passing in
71 // a bank name with sixteenpack already appended
72 if (!m_cmpt.ends_with("/sixteenpack"))
73 m_cmpt.append("/sixteenpack");
74
75 // Get the experimentally measured TOFs
76 m_tofs = tofs;
77
78 // Set the iteration count
79 n_iter = 0;
80}
81
90void SCDCalibratePanels2ObjFunc::function1D(double *out, const double *xValues, const size_t order) const {
91 // Get the feature vector component (numeric type)
92 //-- delta in translation
93 const double dx = getParameter("DeltaX");
94 const double dy = getParameter("DeltaY");
95 const double dz = getParameter("DeltaZ");
96 //-- delta in rotation
97 const double drx = getParameter("RotX");
98 const double dry = getParameter("RotY");
99 const double drz = getParameter("RotZ");
100 //-- delta in TOF
101 // NOTE: The T0 here is a universal offset for all peaks
102 double dT0 = getParameter("DeltaT0");
103 //-- delta of sample position
104 const double dsx = getParameter("DeltaSampleX");
105 const double dsy = getParameter("DeltaSampleY");
106 const double dsz = getParameter("DeltaSampleZ");
107 //-- scale of the detector size
108 const double scalex = getParameter("ScaleX");
109 const double scaley = getParameter("ScaleY");
110
111 //-- NOTE: given that these components are never used as
112 // one vector, there is no need to construct a
113 // xValues
114 UNUSED_ARG(xValues);
115 UNUSED_ARG(order);
116
117 // -- always working on a copy only
118 IPeaksWorkspace_sptr pws = m_pws->clone();
119
120 // NOTE: when optimizing T0, a none component will be passed in.
121 // -- For Corelli, this will be none/sixteenpack
122 // -- For others, this will be none
123 bool calibrateT0 = (m_cmpt == "none/sixteenpack") || (m_cmpt == "none");
124 // we don't need to move the instrument if we are calibrating T0
125 if (!calibrateT0) {
127
128 // translation
129 pws = moveInstruentComponentBy(dx, dy, dz, m_cmpt, pws);
130
131 // rotation
132 pws = rotateInstrumentComponentBy(drx, dry, drz, m_cmpt, pws);
133 }
134
135 // tweak sample position
136 pws = moveInstruentComponentBy(dsx, dsy, dsz, "sample-position", pws);
137
138 // calculate residual
139 // double residual = 0.0;
140 for (int i = 0; i < pws->getNumberPeaks(); ++i) {
141 // use the provided cached tofs
142 const double tof = m_tofs[i];
143
144 Peak pk = Peak(pws->getPeak(i));
145 // update instrument
146 // - this will update the instrument position attached to the peak
147 // - this will update the sample position attached to the peak
148 pk.setInstrument(pws->getInstrument());
149 // update detector ID
151 // calculate&set wavelength based on new instrument
153 wl.initialize(pk.getL1(), 0,
154 {{UnitParams::l2, pk.getL2()},
155 {UnitParams::twoTheta, pk.getScattering()},
156 {UnitParams::efixed, pk.getInitialEnergy()}});
157 pk.setWavelength(wl.singleFromTOF(tof + dT0));
158
159 V3D qv = pk.getQSampleFrame();
160 for (int j = 0; j < 3; ++j)
161 out[i * 3 + j] = qv[j];
162
163 // check the difference between n and target
164 // auto ubm = pws->sample().getOrientedLattice().getUB();
165 // V3D qv_target = ubm * pws->getPeak(i).getIntHKL();
166 // qv_target *= 2 * PI;
167 // V3D delta_qv = qv - qv_target;
168 // residual += delta_qv.norm2();
169 }
170
171 n_iter += 1;
172
173 // V3D dtrans = V3D(dx, dy, dz);
174 // V3D drots = V3D(drx, dry, drz);
175 // residual /= pws->getNumberPeaks();
176 // std::ostringstream msgiter;
177 // msgiter.precision(8);
178 // msgiter << "residual@iter_" << n_iter << ": " << residual << "\n"
179 // << "-- (dx, dy, dz) = " << dtrans << "\n"
180 // << "-- (drx, dry, drz) = " << drots << "\n"
181 // << "-- dT0 = " << dT0 << "\n\n";
182 // g_log.notice() << msgiter.str();
183}
184
185// -------///
186// Helper ///
187// -------///
188
198IPeaksWorkspace_sptr SCDCalibratePanels2ObjFunc::moveInstruentComponentBy(double deltaX, double deltaY, double deltaZ,
199 const std::string &componentName,
200 IPeaksWorkspace_sptr &pws) const {
201 // Workspace_sptr inputws = std::dynamic_pointer_cast<Workspace>(pws);
202
203 // move instrument is really fast, even with zero input
204 auto mv_alg = Mantid::API::AlgorithmFactory::Instance().create("MoveInstrumentComponent", -1);
205 mv_alg->initialize();
206 mv_alg->setChild(true);
207 mv_alg->setLogging(LOGCHILDALG);
208 mv_alg->setProperty("Workspace", pws);
209 mv_alg->setProperty("ComponentName", componentName);
210 mv_alg->setProperty("X", deltaX);
211 mv_alg->setProperty("Y", deltaY);
212 mv_alg->setProperty("Z", deltaZ);
213 mv_alg->setProperty("RelativePosition", true);
214 mv_alg->executeAsChildAlg();
215
216 return pws;
217}
218
229IPeaksWorkspace_sptr SCDCalibratePanels2ObjFunc::rotateInstrumentComponentBy(double rotX, double rotY, double rotZ,
230 const std::string &componentName,
231 IPeaksWorkspace_sptr &pws) const {
232 // rotate
233 auto rot_alg = Mantid::API::AlgorithmFactory::Instance().create("RotateInstrumentComponent", -1);
234 // around X
235 rot_alg->initialize();
236 rot_alg->setChild(true);
237 rot_alg->setLogging(LOGCHILDALG);
238 rot_alg->setProperty("Workspace", pws);
239 rot_alg->setProperty("ComponentName", componentName);
240 rot_alg->setProperty("X", 1.0);
241 rot_alg->setProperty("Y", 0.0);
242 rot_alg->setProperty("Z", 0.0);
243 rot_alg->setProperty("Angle", rotX);
244 rot_alg->setProperty("RelativeRotation", true);
245 rot_alg->executeAsChildAlg();
246 // around Y
247 rot_alg->initialize();
248 rot_alg->setChild(true);
249 rot_alg->setLogging(LOGCHILDALG);
250 rot_alg->setProperty("Workspace", pws);
251 rot_alg->setProperty("ComponentName", componentName);
252 rot_alg->setProperty("X", 0.0);
253 rot_alg->setProperty("Y", 1.0);
254 rot_alg->setProperty("Z", 0.0);
255 rot_alg->setProperty("Angle", rotY);
256 rot_alg->setProperty("RelativeRotation", true);
257 rot_alg->executeAsChildAlg();
258 // around Z
259 rot_alg->initialize();
260 rot_alg->setChild(true);
261 rot_alg->setLogging(LOGCHILDALG);
262 rot_alg->setProperty("Workspace", pws);
263 rot_alg->setProperty("ComponentName", componentName);
264 rot_alg->setProperty("X", 0.0);
265 rot_alg->setProperty("Y", 0.0);
266 rot_alg->setProperty("Z", 1.0);
267 rot_alg->setProperty("Angle", rotZ);
268 rot_alg->setProperty("RelativeRotation", true);
269 rot_alg->executeAsChildAlg();
270
271 return pws;
272}
273
275SCDCalibratePanels2ObjFunc::scaleRectagularDetectorSize(const double &scalex, const double &scaley,
276 const std::string &componentName,
278
279 Geometry::Instrument_sptr inst = std::const_pointer_cast<Geometry::Instrument>(pws->getInstrument());
280 Geometry::IComponent_const_sptr comp = inst->getComponentByName(componentName);
281 std::shared_ptr<const Geometry::RectangularDetector> rectDet =
282 std::dynamic_pointer_cast<const Geometry::RectangularDetector>(comp);
283 if (rectDet) {
284 // get instrument parameter map and find out whether the
285 const Geometry::ParameterMap &pmap = pws->instrumentParameters();
286 auto oldscalex = pmap.getDouble(rectDet->getName(), "scalex");
287 auto oldscaley = pmap.getDouble(rectDet->getName(), "scaley");
288 double relscalex{scalex}, relscaley{scaley};
289 if (!oldscalex.empty())
290 relscalex /= oldscalex[0];
291 if (!oldscaley.empty())
292 relscaley /= oldscaley[0];
293 applyRectangularDetectorScaleToComponentInfo(pws->mutableComponentInfo(), rectDet->getComponentID(), relscalex,
294 relscaley);
295 }
296
297 return pws;
298}
299
300} // namespace Mantid::Crystal
#define DECLARE_FUNCTION(classname)
Macro for declaring a new type of function to be used with the FunctionFactory.
#define UNUSED_ARG(x)
Function arguments are sometimes unused in certain implmentations but are required for documentation ...
Definition System.h:48
double getParameter(size_t i) const override
Get i-th parameter.
SCDCalibratePanels2ObjFunc : TODO: DESCRIPTION.
Mantid::API::IPeaksWorkspace_sptr rotateInstrumentComponentBy(double rotX, double rotY, double rotZ, const std::string &componentName, Mantid::API::IPeaksWorkspace_sptr &pws) const
Rotate the instrument by angle axis.
void setPeakWorkspace(Mantid::API::IPeaksWorkspace_sptr &pws, const std::string &componentName, const std::vector< double > &tofs)
Mantid::API::IPeaksWorkspace_sptr scaleRectagularDetectorSize(const double &scalex, const double &scaley, const std::string &componentName, Mantid::API::IPeaksWorkspace_sptr &pws) const
void function1D(double *out, const double *xValues, const size_t order) const override
base objective function
Mantid::API::IPeaksWorkspace_sptr moveInstruentComponentBy(double deltaX, double deltaY, double deltaZ, const std::string &componentName, Mantid::API::IPeaksWorkspace_sptr &pws) const
helper functions
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
void setDetectorID(int id)
Set the detector ID of the pixel at the centre of the peak and look up and cache values related to it...
Definition Peak.cpp:206
int getDetectorID() const override
Get the ID of the detector at the center of the peak
Definition Peak.cpp:265
void setInstrument(const Geometry::Instrument_const_sptr &inst)
Set the instrument (and save the source/sample pos).
Definition Peak.cpp:294
The Logger class is in charge of the publishing messages from the framework through various channels.
Definition Logger.h:51
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< IPeaksWorkspace > IPeaksWorkspace_sptr
shared pointer to Mantid::API::IPeaksWorkspace
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< 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