LeanPeak.cpp 11.6 KB
Newer Older
1
2
3
4
5
6
7
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
// 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 +
#include "MantidDataObjects/LeanPeak.h"
#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
LeanPeak::LeanPeak() : 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
LeanPeak::LeanPeak(const Mantid::Kernel::V3D &QSampleFrame) : BasePeak() {
44
45
46
  this->setQSampleFrame(QSampleFrame);
}

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

//----------------------------------------------------------------------------------------------
/** 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).
67
 * @param wavelength :: wavelength in Angstroms.
68
 */
69
LeanPeak::LeanPeak(const Mantid::Kernel::V3D &QSampleFrame, double wavelength)
70
    : BasePeak() {
71
  this->setQSampleFrame(QSampleFrame);
72
73
74
75
76
77
78
79
80
  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
81
 * @param wavelength :: wavelength in Angstroms.
82
83
84
85
 */
LeanPeak::LeanPeak(const Mantid::Kernel::V3D &QSampleFrame,
                   const Mantid::Kernel::Matrix<double> &goniometer,
                   double wavelength)
86
    : BasePeak(goniometer) {
87
88
  this->setQSampleFrame(QSampleFrame);
  this->setWavelength(wavelength);
89
90
91
92
93
94
95
}

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

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

//----------------------------------------------------------------------------------------------
/** Set the detector ID of the pixel at the centre of the peak and look up and
Whitfield, Ross's avatar
Whitfield, Ross committed
108
109
 * 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.
110
 */
Whitfield, Ross's avatar
Whitfield, Ross committed
111
void LeanPeak::setDetectorID(int) {
112
  throw Exception::NotImplementedError(
113
      "LeanPeak::setDetectorID(): Can't set detectorID on LeanPeak");
114
115
116
117
}

//----------------------------------------------------------------------------------------------
/** Get the ID of the detector at the center of the peak  */
118
int LeanPeak::getDetectorID() const { return -1; }
119
120
121
122
123
124

//----------------------------------------------------------------------------------------------
/** Set the instrument (and save the source/sample pos).
 * Call setDetectorID AFTER this call.
 *
 */
Whitfield, Ross's avatar
Whitfield, Ross committed
125
void LeanPeak::setInstrument(const Geometry::Instrument_const_sptr &) {
126
  throw Exception::NotImplementedError(
127
      "LeanPeak::setInstrument(): Can't set instrument on LeanPeak");
128
129
130
131
}

//----------------------------------------------------------------------------------------------
/** Return a shared ptr to the detector at center of peak. */
132
Geometry::IDetector_const_sptr LeanPeak::getDetector() const {
133
134
  throw Exception::NotImplementedError(
      "LeanPeak::getDetector(): Has no detector ID");
135
}
136
137
138

/** Return a shared ptr to the instrument for this peak. */
Geometry::Instrument_const_sptr LeanPeak::getInstrument() const {
139
140
  throw Exception::NotImplementedError(
      "LeanPeak::setInstrument(): Has no instrument");
141
142
143
144
145
146
}

// -------------------------------------------------------------------------------------
/** Calculate the time of flight (in microseconds) of the neutrons for this
 * peak,
 * using the geometry of the detector  */
147
148
149
double LeanPeak::getTOF() const {
  return std::numeric_limits<double>::quiet_NaN();
}
150
151
152
153

// -------------------------------------------------------------------------------------
/** Calculate the scattering angle of the peak  */
double LeanPeak::getScattering() const {
154
  return asin(getWavelength() / (2 * getDSpacing())) * 2;
155
156
157
158
159
}

// -------------------------------------------------------------------------------------
/** Calculate the azimuthal angle of the peak  */
double LeanPeak::getAzimuthal() const {
160
  return std::numeric_limits<double>::quiet_NaN();
161
162
163
164
}

// -------------------------------------------------------------------------------------
/** Calculate the d-spacing of the peak, in 1/Angstroms  */
165
double LeanPeak::getDSpacing() const { return 2 * M_PI / m_Qsample.norm(); }
166
167
168
169
170
171
172
173

//----------------------------------------------------------------------------------------------
/** 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.
 * */
Mantid::Kernel::V3D LeanPeak::getQLabFrame() const {
174
  return getGoniometerMatrix() * m_Qsample;
175
176
177
178
179
}

//----------------------------------------------------------------------------------------------
/** 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. */
180
Mantid::Kernel::V3D LeanPeak::getQSampleFrame() const { return m_Qsample; }
181
182
183
184
185
186
187
188
189
190
191
192

//----------------------------------------------------------------------------------------------
/** 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.
 */
Whitfield, Ross's avatar
Whitfield, Ross committed
193
194
void LeanPeak::setQSampleFrame(const Mantid::Kernel::V3D &QSampleFrame,
                               boost::optional<double>) {
195
  m_Qsample = QSampleFrame;
196
197
198
199
200
201
202
203
204
205
206
207
208
}

//----------------------------------------------------------------------------------------------
/** 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
209
 *        Angstroms).
210
 */
Whitfield, Ross's avatar
Whitfield, Ross committed
211
212
void LeanPeak::setQLabFrame(const Mantid::Kernel::V3D &qLab,
                            boost::optional<double>) {
213
  this->setQSampleFrame(getInverseGoniometerMatrix() * qLab);
214
215
216
217
218
}

/** Set sample position
 *
 */
Whitfield, Ross's avatar
Whitfield, Ross committed
219
void LeanPeak::setSamplePos(double, double, double) {
220
  throw Exception::NotImplementedError("LeanPeak has no sample information");
221
222
223
224
225
}

/** Set sample position
 *
 */
Whitfield, Ross's avatar
Whitfield, Ross committed
226
void LeanPeak::setSamplePos(const Mantid::Kernel::V3D &) {
227
  throw Exception::NotImplementedError("LeanPeak has no sample information");
228
229
230
231
}

// -------------------------------------------------------------------------------------
/** Return the detector position vector */
232
Mantid::Kernel::V3D LeanPeak::getDetPos() const {
233
  throw Exception::NotImplementedError("LeanPeak has no detector information");
234
}
235
236
237

// -------------------------------------------------------------------------------------
/** Return the sample position vector */
238
Mantid::Kernel::V3D LeanPeak::getSamplePos() const {
239
  throw Exception::NotImplementedError("LeanPeak has no sample information");
240
}
241
242
243

// -------------------------------------------------------------------------------------
/** Return the L1 flight path length (source to sample), in meters. */
244
double LeanPeak::getL1() const {
245
  throw Exception::NotImplementedError("LeanPeak has no detector information");
246
}
247
248
249

// -------------------------------------------------------------------------------------
/** Return the L2 flight path length (sample to detector), in meters. */
250
double LeanPeak::getL2() const {
251
  throw Exception::NotImplementedError("LeanPeak has no detector information");
252
}
253
254
255
256
257
258
259
260

/**
 * @brief Assignement operator overload
 * @param other : Other peak object to assign from
 * @return this
 */
LeanPeak &LeanPeak::operator=(const LeanPeak &other) {
  if (&other != this) {
261
    BasePeak::operator=(other);
Whitfield, Ross's avatar
Whitfield, Ross committed
262
    m_Qsample = other.m_Qsample;
263
264
265
266
  }
  return *this;
}

Whitfield, Ross's avatar
Whitfield, Ross committed
267
268
269
270
271
272
273
274
275
/** 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.
 */
276
277
278
bool LeanPeak::findDetector() {
  throw Exception::NotImplementedError("LeanPeak has no detector information");
}
Whitfield, Ross's avatar
Whitfield, Ross committed
279
280
281
282
283
284
285
286

/**
 * 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.
 */
Whitfield, Ross's avatar
Whitfield, Ross committed
287
bool LeanPeak::findDetector(const InstrumentRayTracer &) {
288
  throw Exception::NotImplementedError("LeanPeak has no detector information");
Whitfield, Ross's avatar
Whitfield, Ross committed
289
290
}

291
292
293
294
/**
 Forwarding function. Exposes the detector position directly.
 */
Mantid::Kernel::V3D LeanPeak::getDetectorPositionNoCheck() const {
295
  throw Exception::NotImplementedError("LeanPeak has no detector information");
296
297
298
299
300
301
302
}

/**
 Forwarding function. Exposes the detector position directly, but checks that
 the detector is not null before accessing its position. Throws if null.
 */
Mantid::Kernel::V3D LeanPeak::getDetectorPosition() const {
303
  throw Exception::NotImplementedError("LeanPeak has no detector information");
304
305
306
307
308
309
}

Mantid::Kernel::Logger LeanPeak::g_log("PeakLogger");

} // namespace DataObjects
} // namespace Mantid