LeanElasticPeak.cpp 12.2 KB
Newer Older
1
2
3
4
5
6
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
//   NScD Oak Ridge National Laboratory, European Spallation Source,
//   Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
// SPDX - License - Identifier: GPL - 3.0 +
7
#include "MantidDataObjects/LeanElasticPeak.h"
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include "MantidDataObjects/NoShape.h"
#include "MantidGeometry/Instrument/RectangularDetector.h"
#include "MantidGeometry/Instrument/ReferenceFrame.h"
#include "MantidGeometry/Objects/InstrumentRayTracer.h"
#include "MantidGeometry/Surfaces/LineIntersectVisit.h"
#include "MantidKernel/ConfigService.h"
#include "MantidKernel/Exception.h"
#include "MantidKernel/Strings.h"

#include "boost/make_shared.hpp"

#include <algorithm>
#include <cctype>
#include <string>
#include <utility>

using namespace Mantid;
using namespace Mantid::Kernel;
using namespace Mantid::Geometry;

namespace Mantid {
namespace DataObjects {

//----------------------------------------------------------------------------------------------
/** Default constructor */
33
LeanElasticPeak::LeanElasticPeak() : BasePeak(), m_Qsample(V3D(0, 0, 0)) {}
34

35
36
37
38
39
40
41
42
//----------------------------------------------------------------------------------------------
/** Constructor that uses the Q position of the peak (in the sample frame)
 * and a goniometer rotation matrix.
 * No detector ID is set.
 *
 * @param QSampleFrame :: Q of the center of the peak, in reciprocal space, in
 *the sample frame (goniometer rotation accounted for).
 */
43
44
LeanElasticPeak::LeanElasticPeak(const Mantid::Kernel::V3D &QSampleFrame)
    : BasePeak() {
45
46
47
  this->setQSampleFrame(QSampleFrame);
}

48
49
50
51
//----------------------------------------------------------------------------------------------
/** Constructor that uses the Q position of the peak (in the lab frame).
 * No detector ID is set.
 *
52
 * @param QSampleFrame :: Q of the center of the peak, in reciprocal space
53
 * @param goniometer :: a 3x3 rotation matrix
54
 */
55
56
57
LeanElasticPeak::LeanElasticPeak(
    const Mantid::Kernel::V3D &QSampleFrame,
    const Mantid::Kernel::Matrix<double> &goniometer)
58
    : BasePeak(goniometer) {
59
  this->setQSampleFrame(QSampleFrame);
60
61
62
63
64
65
66
67
68
}

//----------------------------------------------------------------------------------------------
/** Constructor that uses the Q position of the peak (in the sample frame)
 * and a goniometer rotation matrix.
 * No detector ID is set.
 *
 * @param QSampleFrame :: Q of the center of the peak, in reciprocal space, in
 *the sample frame (goniometer rotation accounted for).
69
 * @param wavelength :: wavelength in Angstroms.
70
 */
71
72
LeanElasticPeak::LeanElasticPeak(const Mantid::Kernel::V3D &QSampleFrame,
                                 double wavelength)
73
    : BasePeak() {
74
  this->setQSampleFrame(QSampleFrame);
75
76
77
78
79
80
81
82
83
  this->setWavelength(wavelength);
}

//----------------------------------------------------------------------------------------------
/** Constructor that uses the Q position of the peak (in the lab frame).
 * No detector ID is set.
 *
 * @param QSampleFrame :: Q of the center of the peak, in reciprocal space
 * @param goniometer :: a 3x3 rotation matrix
84
 * @param wavelength :: wavelength in Angstroms.
85
 */
86
87
88
LeanElasticPeak::LeanElasticPeak(
    const Mantid::Kernel::V3D &QSampleFrame,
    const Mantid::Kernel::Matrix<double> &goniometer, double wavelength)
89
    : BasePeak(goniometer) {
90
91
  this->setQSampleFrame(QSampleFrame);
  this->setWavelength(wavelength);
92
93
94
95
96
97
}

/**
 * @brief Copy constructor
 * @param other : Source
 */
98
LeanElasticPeak::LeanElasticPeak(const LeanElasticPeak &other)
99
    : BasePeak(other), m_Qsample(other.m_Qsample) {}
100
101

//----------------------------------------------------------------------------------------------
102
/** Constructor making a LeanElasticPeak from IPeak interface
103
104
105
 *
 * @param ipeak :: const reference to an IPeak object
 */
106
LeanElasticPeak::LeanElasticPeak(const Geometry::IPeak &ipeak)
107
    : BasePeak(ipeak), m_Qsample(ipeak.getQSampleFrame()) {}
108
109
110

//----------------------------------------------------------------------------------------------
/** Set the detector ID of the pixel at the centre of the peak and look up and
Whitfield, Ross's avatar
Whitfield, Ross committed
111
112
 * cache values related to it. It also adds it to the list of contributing
 * detectors for this peak but does NOT remove the old centre.
113
 */
114
void LeanElasticPeak::setDetectorID(int) {
115
  throw Exception::NotImplementedError(
116
117
      "LeanElasticPeak::setDetectorID(): Can't set detectorID on "
      "LeanElasticPeak");
118
119
120
121
}

//----------------------------------------------------------------------------------------------
/** Get the ID of the detector at the center of the peak  */
122
int LeanElasticPeak::getDetectorID() const { return -1; }
123
124
125
126
127
128

//----------------------------------------------------------------------------------------------
/** Set the instrument (and save the source/sample pos).
 * Call setDetectorID AFTER this call.
 *
 */
129
void LeanElasticPeak::setInstrument(const Geometry::Instrument_const_sptr &) {
130
  throw Exception::NotImplementedError(
131
132
      "LeanElasticPeak::setInstrument(): Can't set instrument on "
      "LeanElasticPeak");
133
134
135
136
}

//----------------------------------------------------------------------------------------------
/** Return a shared ptr to the detector at center of peak. */
137
Geometry::IDetector_const_sptr LeanElasticPeak::getDetector() const {
138
  throw Exception::NotImplementedError(
139
      "LeanElasticPeak::getDetector(): Has no detector ID");
140
}
141
142

/** Return a shared ptr to the instrument for this peak. */
143
Geometry::Instrument_const_sptr LeanElasticPeak::getInstrument() const {
144
  throw Exception::NotImplementedError(
145
      "LeanElasticPeak::setInstrument(): Has no instrument");
146
147
148
149
150
151
}

// -------------------------------------------------------------------------------------
/** Calculate the time of flight (in microseconds) of the neutrons for this
 * peak,
 * using the geometry of the detector  */
152
double LeanElasticPeak::getTOF() const {
153
154
  return std::numeric_limits<double>::quiet_NaN();
}
155
156
157

// -------------------------------------------------------------------------------------
/** Calculate the scattering angle of the peak  */
158
double LeanElasticPeak::getScattering() const {
159
  return asin(getWavelength() / (2 * getDSpacing())) * 2;
160
161
162
163
}

// -------------------------------------------------------------------------------------
/** Calculate the azimuthal angle of the peak  */
164
double LeanElasticPeak::getAzimuthal() const {
165
  return std::numeric_limits<double>::quiet_NaN();
166
167
168
169
}

// -------------------------------------------------------------------------------------
/** Calculate the d-spacing of the peak, in 1/Angstroms  */
170
171
172
double LeanElasticPeak::getDSpacing() const {
  return 2 * M_PI / m_Qsample.norm();
}
173
174
175
176
177
178
179

//----------------------------------------------------------------------------------------------
/** Return the Q change (of the lattice, k_i - k_f) for this peak.
 * The Q is in the Lab frame: the goniometer rotation was NOT taken out.
 *
 * Note: There is a 2*pi factor used, so |Q| = 2*pi/wavelength.
 * */
180
Mantid::Kernel::V3D LeanElasticPeak::getQLabFrame() const {
181
  return getGoniometerMatrix() * m_Qsample;
182
183
184
185
186
}

//----------------------------------------------------------------------------------------------
/** Return the Q change (of the lattice, k_i - k_f) for this peak.
 * The Q is in the Sample frame: the goniometer rotation WAS taken out. */
187
188
189
Mantid::Kernel::V3D LeanElasticPeak::getQSampleFrame() const {
  return m_Qsample;
}
190
191
192
193
194
195
196
197
198
199
200
201

//----------------------------------------------------------------------------------------------
/** Set the peak using the peak's position in reciprocal space, in the sample
 *frame.
 * The GoniometerMatrix will be used to find the Q in the lab frame, so it
 *should
 * be set beforehand.
 *
 * @param QSampleFrame :: Q of the center of the peak, in reciprocal space
 *        This is in inelastic convention: momentum transfer of the LATTICE!
 *        Also, q does NOT have a 2pi factor = it is equal to 1/wavelength.
 */
202
203
void LeanElasticPeak::setQSampleFrame(const Mantid::Kernel::V3D &QSampleFrame,
                                      boost::optional<double>) {
204
  m_Qsample = QSampleFrame;
205
206
207
208
209
210
211
212
213
214
215
216
217
}

//----------------------------------------------------------------------------------------------
/** Set the peak using the peak's position in reciprocal space, in the lab
 *frame.
 * The detector position will be determined.
 * DetectorID, row and column will be set to -1 since they are not (necessarily)
 *found.
 * You can call findDetector to look for the detector ID
 *
 * @param qLab :: Q of the center of the peak, in reciprocal space.
 *        This is in inelastic convention: momentum transfer of the LATTICE!
 *        Also, q does have a 2pi factor = it is equal to 2pi/wavelength (in
218
 *        Angstroms).
219
 */
220
221
void LeanElasticPeak::setQLabFrame(const Mantid::Kernel::V3D &qLab,
                                   boost::optional<double>) {
222
  this->setQSampleFrame(getInverseGoniometerMatrix() * qLab);
223
224
225
226
227
}

/** Set sample position
 *
 */
228
229
230
void LeanElasticPeak::setSamplePos(double, double, double) {
  throw Exception::NotImplementedError(
      "LeanElasticPeak has no sample information");
231
232
233
234
235
}

/** Set sample position
 *
 */
236
237
238
void LeanElasticPeak::setSamplePos(const Mantid::Kernel::V3D &) {
  throw Exception::NotImplementedError(
      "LeanElasticPeak has no sample information");
239
240
241
242
}

// -------------------------------------------------------------------------------------
/** Return the detector position vector */
243
244
245
Mantid::Kernel::V3D LeanElasticPeak::getDetPos() const {
  throw Exception::NotImplementedError(
      "LeanElasticPeak has no detector information");
246
}
247
248
249

// -------------------------------------------------------------------------------------
/** Return the sample position vector */
250
251
252
Mantid::Kernel::V3D LeanElasticPeak::getSamplePos() const {
  throw Exception::NotImplementedError(
      "LeanElasticPeak has no sample information");
253
}
254
255
256

// -------------------------------------------------------------------------------------
/** Return the L1 flight path length (source to sample), in meters. */
257
258
259
double LeanElasticPeak::getL1() const {
  throw Exception::NotImplementedError(
      "LeanElasticPeak has no detector information");
260
}
261
262
263

// -------------------------------------------------------------------------------------
/** Return the L2 flight path length (sample to detector), in meters. */
264
265
266
double LeanElasticPeak::getL2() const {
  throw Exception::NotImplementedError(
      "LeanElasticPeak has no detector information");
267
}
268
269
270
271
272
273

/**
 * @brief Assignement operator overload
 * @param other : Other peak object to assign from
 * @return this
 */
274
LeanElasticPeak &LeanElasticPeak::operator=(const LeanElasticPeak &other) {
275
  if (&other != this) {
276
    BasePeak::operator=(other);
Whitfield, Ross's avatar
Whitfield, Ross committed
277
    m_Qsample = other.m_Qsample;
278
279
280
281
  }
  return *this;
}

Whitfield, Ross's avatar
Whitfield, Ross committed
282
283
284
285
286
287
288
289
290
/** After creating a peak using the Q in the lab frame,
 * the detPos is set to the direction of the detector (but the detector is
 *unknown)
 *
 * Using the instrument set in the peak, perform ray tracing
 * to find the exact detector.
 *
 * @return true if the detector ID was found.
 */
291
292
293
bool LeanElasticPeak::findDetector() {
  throw Exception::NotImplementedError(
      "LeanElasticPeak has no detector information");
294
}
Whitfield, Ross's avatar
Whitfield, Ross committed
295
296
297
298
299
300
301
302

/**
 * Performs the same algorithm as findDetector() but uses a pre-existing
 * InstrumentRayTracer object to be able to take adavtange of its caches.
 * This method should be preferred if findDetector is to be called many times
 * over the same instrument.
 * @return true if the detector ID was found.
 */
303
304
305
bool LeanElasticPeak::findDetector(const InstrumentRayTracer &) {
  throw Exception::NotImplementedError(
      "LeanElasticPeak has no detector information");
Whitfield, Ross's avatar
Whitfield, Ross committed
306
307
}

308
309
310
/**
 Forwarding function. Exposes the detector position directly.
 */
311
312
313
Mantid::Kernel::V3D LeanElasticPeak::getDetectorPositionNoCheck() const {
  throw Exception::NotImplementedError(
      "LeanElasticPeak has no detector information");
314
315
316
317
318
319
}

/**
 Forwarding function. Exposes the detector position directly, but checks that
 the detector is not null before accessing its position. Throws if null.
 */
320
321
322
Mantid::Kernel::V3D LeanElasticPeak::getDetectorPosition() const {
  throw Exception::NotImplementedError(
      "LeanElasticPeak has no detector information");
323
324
}

325
Mantid::Kernel::Logger LeanElasticPeak::g_log("PeakLogger");
326
327
328

} // namespace DataObjects
} // namespace Mantid