PeakTest.h 20.9 KB
Newer Older
1
2
3
4
#ifndef MANTID_DATAOBJECTS_PEAKTEST_H_
#define MANTID_DATAOBJECTS_PEAKTEST_H_

#include <cxxtest/TestSuite.h>
5
#include "MockObjects.h"
6
7
#include "MantidKernel/Timer.h"
#include "MantidKernel/System.h"
8
9
10
#include "MantidKernel/UnitFactory.h"
#include "MantidKernel/Unit.h"
#include "MantidKernel/V3D.h"
11
#include "MantidKernel/make_unique.h"
12
13
#include "MantidKernel/PhysicalConstants.h"
#include "MantidGeometry/Instrument/ReferenceFrame.h"
14
#include <gmock/gmock.h>
15
16

#include "MantidDataObjects/Peak.h"
17
#include "MantidTestHelpers/ComponentCreationHelper.h"
18
19

using namespace Mantid::DataObjects;
20
21
using namespace Mantid::Geometry;
using namespace Mantid::Kernel;
22

Hahn, Steven's avatar
Hahn, Steven committed
23
24
25
26
27
28
29
30
31
32
33
namespace boost {
template <class CharType, class CharTrait>
std::basic_ostream<CharType, CharTrait> &
operator<<(std::basic_ostream<CharType, CharTrait> &out,
           optional<double> const &maybe) {
  if (maybe)
    out << maybe;
  return out;
}
}

34
class PeakTest : public CxxTest::TestSuite {
35
private:
36
37
38
  /// Common instrument
  Instrument_sptr inst;
  Instrument_sptr m_minimalInstrument;
39

40
public:
41
42
  // This pair of boilerplate methods prevent the suite being created statically
  // This means the constructor isn't called when running other tests
43
  static PeakTest *createSuite() { return new PeakTest(); }
44
45
46
  static void destroySuite(PeakTest *suite) { delete suite; }

  // Constructor
47
48
  PeakTest()
      : inst(ComponentCreationHelper::createTestInstrumentRectangular(5, 100)) {
49

50
51
  }

52
  void test_constructor() {
53
54
55
56
57
58
    // detector IDs start at 10000
    Peak p(inst, 10000, 2.0);
    TS_ASSERT_DELTA(p.getH(), 0.0, 1e-5)
    TS_ASSERT_DELTA(p.getK(), 0.0, 1e-5)
    TS_ASSERT_DELTA(p.getL(), 0.0, 1e-5)
    TS_ASSERT_EQUALS(p.getDetectorID(), 10000)
59
60
    TS_ASSERT_EQUALS(p.getDetector()->getID(), 10000)
    TS_ASSERT_EQUALS(p.getInstrument(), inst)
61
    check_Contributing_Detectors(p, std::vector<int>(1, 10000));
62
63
  }

64
  void test_constructorHKL() {
65
    // detector IDs start at 10000
66
    Peak p(inst, 10000, 2.0, V3D(1, 2, 3));
67
68
69
70
71
72
    TS_ASSERT_DELTA(p.getH(), 1.0, 1e-5)
    TS_ASSERT_DELTA(p.getK(), 2.0, 1e-5)
    TS_ASSERT_DELTA(p.getL(), 3.0, 1e-5)
    TS_ASSERT_EQUALS(p.getDetectorID(), 10000)
    TS_ASSERT_EQUALS(p.getDetector()->getID(), 10000)
    TS_ASSERT_EQUALS(p.getInstrument(), inst)
73
    check_Contributing_Detectors(p, std::vector<int>(1, 10000));
74
75
  }

76
77
78
79
80
81
82
83
84
  void test_constructorHKLGon() {
    Matrix<double> mats(3, 3), mat(3, 3);
    for (int x = 0; x < 3; x++)
      for (int y = 0; y < 3; y++)
        mats[x][y] = 1.0 * x + 1.0 * y;
    mat[0][0] = 1.0;
    mat[1][2] = 1.0;
    mat[2][1] = 1.0;

85
    // detector IDs start at 10000
86
87
88
    TS_ASSERT_THROWS_ANYTHING(Peak ps(inst, 10000, 2.0, V3D(1, 2, 3), mats);)
    TS_ASSERT_THROWS_NOTHING(Peak p(inst, 10000, 2.0, V3D(1, 2, 3), mat);)
    Peak p(inst, 10000, 2.0, V3D(1, 2, 3), mat);
89
90
91
92
93
94
    TS_ASSERT_DELTA(p.getH(), 1.0, 1e-5)
    TS_ASSERT_DELTA(p.getK(), 2.0, 1e-5)
    TS_ASSERT_DELTA(p.getL(), 3.0, 1e-5)
    TS_ASSERT_EQUALS(p.getDetectorID(), 10000)
    TS_ASSERT_EQUALS(p.getDetector()->getID(), 10000)
    TS_ASSERT_EQUALS(p.getInstrument(), inst)
95
    TS_ASSERT_EQUALS(p.getGoniometerMatrix(), mat);
96
    check_Contributing_Detectors(p, std::vector<int>(1, 10000));
97
98
  }

99
  void test_ConstructorFromIPeakInterface() {
100
    Peak p(inst, 10102, 2.0);
101
    p.setHKL(1, 2, 3);
102
103
104
    p.setRunNumber(1234);
    p.addContributingDetID(10103);

105
    const Mantid::Geometry::IPeak &ipeak = p;
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
    Peak p2(ipeak);
    TS_ASSERT_EQUALS(p.getRow(), p2.getRow());
    TS_ASSERT_EQUALS(p.getCol(), p2.getCol());
    TS_ASSERT_EQUALS(p.getH(), p2.getH());
    TS_ASSERT_EQUALS(p.getK(), p2.getK());
    TS_ASSERT_EQUALS(p.getL(), p2.getL());
    TS_ASSERT_EQUALS(p.getGoniometerMatrix(), p2.getGoniometerMatrix());
    TS_ASSERT_EQUALS(p.getRunNumber(), p2.getRunNumber());
    TS_ASSERT_EQUALS(p.getDetector(), p2.getDetector())
    TS_ASSERT_EQUALS(p.getInstrument(), p2.getInstrument())
    auto expectedIDs = std::vector<int>(2, 10102);
    expectedIDs[1] = 10103;
    check_Contributing_Detectors(p2, expectedIDs);
  }

121
  void test_copyConstructor() {
122
    Peak p(inst, 10102, 2.0);
123
    p.setHKL(1, 2, 3);
124
125
126
127
128
129
130
131
132
133
    p.setRunNumber(1234);
    // Default (not-explicit) copy constructor
    Peak p2(p);
    TS_ASSERT_EQUALS(p.getRow(), p2.getRow());
    TS_ASSERT_EQUALS(p.getCol(), p2.getCol());
    TS_ASSERT_EQUALS(p.getH(), p2.getH());
    TS_ASSERT_EQUALS(p.getK(), p2.getK());
    TS_ASSERT_EQUALS(p.getL(), p2.getL());
    TS_ASSERT_EQUALS(p.getGoniometerMatrix(), p2.getGoniometerMatrix());
    TS_ASSERT_EQUALS(p.getRunNumber(), p2.getRunNumber());
134
135
    TS_ASSERT_EQUALS(p.getDetector(), p2.getDetector());
    TS_ASSERT_EQUALS(p.getInstrument(), p2.getInstrument());
136
137
    TS_ASSERT_EQUALS(p.getPeakShape().shapeName(),
                     p2.getPeakShape().shapeName());
138
    check_Contributing_Detectors(p2, std::vector<int>(1, 10102));
139
140
  }

141
  void test_getValueByColName() {
142
    Peak p(inst, 10102, 2.0);
143
    p.setHKL(1, 2, 3);
144
145
146
147
148
149
150
151
    p.setRunNumber(1234);
    TS_ASSERT_EQUALS(p.getValueByColName("Row"), p.getRow());
    TS_ASSERT_EQUALS(p.getValueByColName("Col"), p.getCol());
    TS_ASSERT_EQUALS(p.getValueByColName("H"), p.getH());
    TS_ASSERT_EQUALS(p.getValueByColName("K"), p.getK());
    TS_ASSERT_EQUALS(p.getValueByColName("L"), p.getL());
    TS_ASSERT_EQUALS(p.getValueByColName("RunNumber"), p.getRunNumber());
    TS_ASSERT_EQUALS(p.getValueByColName("DetId"), p.getDetectorID())
152
    TS_ASSERT_THROWS_ANYTHING(p.getValueByColName("bankname"));
153
154
  }

155
  /** Set the wavelength and see the other "versions" of it get calculated. */
156
157
  void test_wavelength_conversion() {
    // 1 angstroms wavelength, and at the opposite corner of the detector
158
159
    Peak p(inst, 19999, 1.0);
    // Energy in meV
160
161
    TS_ASSERT_DELTA(p.getInitialEnergy(), 81.805, 1e-3) // Conversion table at :
    // www.ncnr.nist.gov/instruments/dcs/dcs_usersguide/Conversion_Factors.pdf
162
    TS_ASSERT_DELTA(p.getFinalEnergy(), p.getInitialEnergy(), 1e-5)
163
164
165
    V3D dp = p.getDetPos();
    double tt = dp.angle(V3D(0, 0, 1));
    double d = 0.5 / sin(0.5 * tt); // d=lambda/2/sin(theta)=4.5469
166
    TS_ASSERT_DELTA(p.getDSpacing(), d, 1e-3);
167
168
169
170
    TS_ASSERT_DELTA(p.getTOF(), 3823, 1);

    // Back-converting to wavelength should give you the same.
    TS_ASSERT_DELTA(p.getWavelength(), 1.00, 1e-2);
171
172
  }

173
  void test_badDetectorID_throws() {
174
    Peak p(inst, 10000, 2.0);
175
    TS_ASSERT_THROWS_ANYTHING(p.setDetectorID(7));
176
  }
177

178
179
  void
  test_setDetector_Adds_ID_To_Contributing_List_And_Does_Not_Remove_Old_From_Contrib_List() {
180
181
182
183
    int expectedIDs[2] = {10000, 10001};
    Peak peak(inst, expectedIDs[0], 2.0);
    peak.setDetectorID(expectedIDs[1]);

184
185
    check_Contributing_Detectors(
        peak, std::vector<int>(expectedIDs, expectedIDs + 2));
186
187
  }

188
  void test_runNumber() {
189
190
    Peak p(inst, 10000, 2.0);
    p.setRunNumber(12345);
191
    TS_ASSERT_EQUALS(p.getRunNumber(), 12345);
192
193
  }

194
  void test_GoniometerMatrix() {
195
    Peak p(inst, 10000, 2.0);
196
197
198
199
200
201
202
203
204
205
206
207
208
    Matrix<double> mats(3, 3), mat(3, 3);
    for (int x = 0; x < 3; x++)
      for (int y = 0; y < 3; y++)
        mats[x][y] = 1.0 * x + 1.0 * y;
    TS_ASSERT_THROWS_ANYTHING(p.setGoniometerMatrix(mats)); // matrix is
                                                            // singular
    TS_ASSERT_EQUALS(p.getGoniometerMatrix(), mats);
    mat[0][0] = 1.0;
    mat[1][2] = 1.0;
    mat[2][1] = 1.0;
    TS_ASSERT_THROWS_NOTHING(
        p.setGoniometerMatrix(mat)); // matrix is not singular
    TS_ASSERT_EQUALS(p.getGoniometerMatrix(), mat);
209
    // Matrix must be 3x3
210
211
    Matrix<double> mat2(4, 3);
    TS_ASSERT_THROWS_ANYTHING(p.setGoniometerMatrix(mat2));
212
213
  }

214
  void test_HKL() {
215
216
    Peak p(inst, 10000, 2.0);
    p.setHKL(1.0, 2.0, 3.0);
217
218
219
    TS_ASSERT_EQUALS(p.getH(), 1.0);
    TS_ASSERT_EQUALS(p.getK(), 2.0);
    TS_ASSERT_EQUALS(p.getL(), 3.0);
220
221
222
    p.setH(5);
    p.setK(6);
    p.setL(7);
223
224
225
    TS_ASSERT_EQUALS(p.getH(), 5.0);
    TS_ASSERT_EQUALS(p.getK(), 6.0);
    TS_ASSERT_EQUALS(p.getL(), 7.0);
226
    p.setHKL(V3D(1.0, 2.0, 3.0));
227
228
229
230
    TS_ASSERT_EQUALS(p.getH(), 1.0);
    TS_ASSERT_EQUALS(p.getK(), 2.0);
    TS_ASSERT_EQUALS(p.getL(), 3.0);
    TS_ASSERT_EQUALS(p.getHKL(), V3D(1.0, 2.0, 3.0));
231
232
  }

233
  void test_getBank_and_row() {
234
235
236
237
    Peak p(inst, 10000, 2.0);
    TS_ASSERT_EQUALS(p.getBankName(), "bank1")
    TS_ASSERT_EQUALS(p.getRow(), 0)
    TS_ASSERT_EQUALS(p.getCol(), 0)
238
239
240
241
242
243
    p.setDetectorID(10050);
    TS_ASSERT_EQUALS(p.getRow(), 50)
    TS_ASSERT_EQUALS(p.getCol(), 0)
    p.setDetectorID(10100);
    TS_ASSERT_EQUALS(p.getRow(), 0)
    TS_ASSERT_EQUALS(p.getCol(), 1)
244
245
  }

246
  void test_getQSampleFrame() {
247
    // Peak 3 is phi,chi,omega of 90,0,0; giving this matrix:
248
    Matrix<double> r2(3, 3, false);
249
250
251
252
253
254
255
256
257
258
259
    r2[0][2] = 1;
    r2[1][1] = 1;
    r2[2][0] = -1;

    Peak p(inst, 10000, 2.0);
    p.setGoniometerMatrix(r2);

    // Q in the lab frame
    V3D qLab = p.getQLabFrame();
    // q in the sample frame.
    V3D qSample = p.getQSampleFrame();
260
261
    // If we re-rotate q in the sample frame by the gonio matrix, we should get
    // q in the lab frame
262
263
264
265
266
267
    V3D qSampleRotated = r2 * qSample;

    // Did the peak properly invert the rotation matrix?
    TS_ASSERT_EQUALS(qLab, qSampleRotated);
  }

Samuel Jackson's avatar
Samuel Jackson committed
268
  void test_getQLabFrame() {
269
270
271
272
273
274
275
276
277
    Instrument_sptr inst =
        ComponentCreationHelper::createTestInstrumentRectangular2(1, 10);
    Peak p(inst, 0, 1.5);
    p.setQLabFrame(V3D(1, 1, 1));
    auto q = p.getQLabFrame();
    // should be the same
    TS_ASSERT_DELTA(q[0], 1, 1e-5);
    TS_ASSERT_DELTA(q[1], 1, 1e-5);
    TS_ASSERT_DELTA(q[2], 1, 1e-5);
Samuel Jackson's avatar
Samuel Jackson committed
278
279
  }

280
281
  //------------------------------------------------------------------------------------
  /** Can't have Q = 0,0,0 or 0 in the Z direction when creating */
282
  void test_setQLabFrame_ThrowsIfQIsNull() {
283
    Peak p1(inst, 10000, 2.0);
284
    const boost::optional<double> distance = 1.0;
285
286
    TS_ASSERT_THROWS_ANYTHING(Peak p2(inst, V3D(0, 0, 0), distance));
    TS_ASSERT_THROWS_ANYTHING(Peak p2(inst, V3D(1, 2, 0), distance));
287
288
289
  }

  /** Compare two peaks, but not the detector IDs etc. */
290
291
292
293
294
295
296
297
298
299
300
301
302
303
  void comparePeaks(Peak &p1, Peak &p2) {
    // TODO. Peak should implement bool operator==(const Peak&) and that should
    // be tested, rather than having external functionality here.
    TS_ASSERT_EQUALS(p1.getQLabFrame(), p2.getQLabFrame());
    TS_ASSERT_EQUALS(p1.getQSampleFrame(), p2.getQSampleFrame());
    TS_ASSERT_EQUALS(p1.getDetPos(), p2.getDetPos());
    TS_ASSERT_EQUALS(p1.getHKL(), p2.getHKL());
    TS_ASSERT_DELTA(p1.getWavelength(), p2.getWavelength(), 1e-5);
    TS_ASSERT_DELTA(p1.getL1(), p2.getL1(), 1e-5);
    TS_ASSERT_DELTA(p1.getL2(), p2.getL2(), 1e-5);
    TS_ASSERT_DELTA(p1.getTOF(), p2.getTOF(), 1e-5);
    TS_ASSERT_DELTA(p1.getInitialEnergy(), p2.getInitialEnergy(), 1e-5);
    TS_ASSERT_DELTA(p1.getFinalEnergy(), p2.getFinalEnergy(), 1e-5);
    TS_ASSERT(p1.getGoniometerMatrix().equals(p2.getGoniometerMatrix(), 1e-5));
304
305
306
  }

  /** Create peaks using Q in the lab frame */
307
  void test_setQLabFrame() {
308
309
310
311
312
    Peak p1(inst, 19999, 2.0);
    V3D Qlab1 = p1.getQLabFrame();
    V3D detPos1 = p1.getDetPos();

    // Construct using just Q
313
    Peak p2(inst, Qlab1, boost::optional<double>(detPos1.norm()));
314
    comparePeaks(p1, p2);
315
316
317
318
    TS_ASSERT_EQUALS(p2.getBankName(), "None");
    TS_ASSERT_EQUALS(p2.getRow(), -1);
    TS_ASSERT_EQUALS(p2.getCol(), -1);
    TS_ASSERT_EQUALS(p2.getDetectorID(), -1);
319
320
  }

321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
  void test_setQLabFrame2() {
    // Create fictional instrument
    const V3D source(0, 0, 0);
    const V3D sample(15, 0, 0);
    const V3D detectorPos(20, 5, 0);
    const V3D beam1 = sample - source;
    const V3D beam2 = detectorPos - sample;
    auto minimalInstrument = ComponentCreationHelper::createMinimalInstrument(
        source, sample, detectorPos);

    // Derive distances and angles
    const double l1 = beam1.norm();
    const double l2 = beam2.norm();
    const V3D qLabDir = (beam1 / l1) - (beam2 / l2);

    const double microSecsInSec = 1e6;

    // Derive QLab for diffraction
    const double wavenumber_in_angstrom_times_tof_in_microsec =
        (Mantid::PhysicalConstants::NeutronMass * (l1 + l2) * 1e-10 *
         microSecsInSec) /
        Mantid::PhysicalConstants::h_bar;

    V3D qLab = qLabDir * wavenumber_in_angstrom_times_tof_in_microsec;

    Peak peak; // Everything will be default
    peak.setInstrument(
        minimalInstrument); // Can't do anything without the instrument
    peak.setQLabFrame(qLab);
    auto detector = peak.getDetector();

    TSM_ASSERT("No detector", detector);
    TS_ASSERT_EQUALS(1, detector->getID());
    TS_ASSERT_EQUALS(detectorPos, detector->getPos());
355
356
  }

357
  /** Create peaks using Q in sample frame + a goniometer rotation matrix*/
358
  void test_setQSampleFrame() {
359
    // A goniometer rotation matrix
360
    Matrix<double> r2(3, 3, false);
361
362
363
364
    r2[0][2] = 1;
    r2[1][1] = 1;
    r2[2][0] = -1;

365
    Peak p1(inst, 19999, 2.0, V3D(1, 2, 3), r2);
366
367
368
369
370
    V3D q = p1.getQSampleFrame();
    V3D detPos1 = p1.getDetPos();

    // Construct using Q + rotation matrix
    Peak p2(inst, q, r2, detPos1.norm());
371
    p2.setHKL(V3D(1, 2, 3)); // Make sure HKL matches too.
372
    comparePeaks(p1, p2);
373
374
375
376
    TS_ASSERT_EQUALS(p2.getBankName(), "None");
    TS_ASSERT_EQUALS(p2.getRow(), -1);
    TS_ASSERT_EQUALS(p2.getCol(), -1);
    TS_ASSERT_EQUALS(p2.getDetectorID(), -1);
377
378
  }

379
380
  void test_setQSampleFrameVirtualDetectorWithQLab() {
    constexpr auto radius = 10.;
381
382
383
384
    auto sphereInst =
        ComponentCreationHelper::createTestInstrumentRectangular(5, 100);
    auto extendedSpaceObj =
        ComponentCreationHelper::createSphere(10., V3D(0, 0, 0));
385
    auto extendedSpace = Mantid::Kernel::make_unique<ObjComponent>(
386
        "extended-detector-space", extendedSpaceObj, sphereInst.get());
387
    extendedSpace->setPos(V3D(0.0, 0.0, 0.0));
388
    sphereInst->add(extendedSpace.release());
389
390
391
392
    const auto refFrame = sphereInst->getReferenceFrame();
    const auto refBeamDir = refFrame->vecPointingAlongBeam();

    // test with & without extended detector space
393
    // extended space is a sphere, so all points should fall radius*detector
394
    // direction away from the detector direction with extended space
395
    auto testQ = [&](const V3D &q) {
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
      // Compute expected direction
      const auto qBeam = q.scalar_prod(refBeamDir);
      const double norm_q = q.norm();
      const double one_over_wl = (norm_q * norm_q) / (2.0 * qBeam);

      V3D detectorDir = q * -1.0;
      detectorDir[refFrame->pointingAlongBeam()] = one_over_wl - qBeam;
      detectorDir.normalize();

      // test without extended detector space
      // should be a unit vector in the direction of the virtual detector
      // position
      Peak peak1(inst, q);

      // skip tests for which Q actually does intersect with a valid detector
      if (peak1.getDetectorID() > 0) {
        return;
      }

      TS_ASSERT_EQUALS(peak1.getDetectorID(), -1)
      TS_ASSERT_EQUALS(peak1.getDetPos(), detectorDir)

      // test with extended detector space
      // should be the full vector to the virtual detector position
      Peak peak2(sphereInst, q);
      TS_ASSERT_EQUALS(peak2.getDetectorID(), -1)
      TS_ASSERT_EQUALS(peak2.getDetPos(), detectorDir * radius)
423
424
425
426
427
428
429
430
431
432
    };

    // Make hemisphere of q vectors to test
    std::vector<double> xDirections(20);
    std::vector<double> yDirections(20);
    std::vector<double> zDirections(10);

    // create x values of the range -1 to 1
    int index = 0;
    double startValue = -1;
433
434
435
    std::generate(
        xDirections.begin(), xDirections.end(),
        [&index, &startValue]() { return startValue + index++ * 0.1; });
436
437
438
439
440

    // create z values of the range 0.1 to 1
    // ignore negative z values as these are not physical!
    index = 0;
    startValue = 0.1;
441
442
443
    std::generate(
        zDirections.begin(), zDirections.end(),
        [&index, &startValue]() { return startValue + index++ * 0.1; });
444
445
446

    yDirections = xDirections;

447
448
449
450
    for (auto &x : xDirections) {
      for (auto &y : yDirections) {
        for (auto &z : zDirections) {
          testQ(V3D(x, y, z));
451
        }
452
      }
453
454
455
456
    }
  }

  void test_setQSampleFrameVirtualDetectorWithScatteringAngle() {
457
458
459
460
    auto sphereInst =
        ComponentCreationHelper::createTestInstrumentRectangular(5, 100);
    auto extendedSpaceObj =
        ComponentCreationHelper::createSphere(10., V3D(0, 0, 0));
461
    auto extendedSpace = Mantid::Kernel::make_unique<ObjComponent>(
462
        "extended-detector-space", extendedSpaceObj, sphereInst.get());
463
    extendedSpace->setPos(V3D(0.0, 0.0, 0.0));
464
    sphereInst->add(extendedSpace.release());
465
466

    // test with & without extended detector space
467
    // extended space is a sphere, so all points should fall radius*detector
468
    // direction away from the detector direction with extended space
Hahn, Steven's avatar
Hahn, Steven committed
469
    auto testTheta = [this, &sphereInst](const double theta) {
Hahn, Steven's avatar
Hahn, Steven committed
470
      constexpr auto radius = 10.;
471
472
473
474
475
476
477
478
479
480
481
482
483
      const auto expectedDir = V3D(sin(theta), 0., cos(theta));

      // test without extended detector space
      // should be {sin(theta), 0, cos(theta)}
      Peak p1(this->inst, theta, 2.0);
      V3D detPos1 = p1.getDetPos();
      TS_ASSERT_EQUALS(detPos1, expectedDir);

      // test with extended detector space
      // should be radius*{sin(theta), 0, cos(theta)}
      Peak p2(sphereInst, theta, 2.0);
      V3D detPos2 = p2.getDetPos();
      TS_ASSERT_EQUALS(detPos2, expectedDir * radius);
484
485
486
487
488
    };

    // generate & test a range of angles from 0 - 360
    int index = 0;
    std::vector<double> angles(8);
489
    std::generate(angles.begin(), angles.end(), [&index, &angles]() {
490
491
      return static_cast<double>(index++) * M_PI /
             static_cast<double>(angles.size());
492
    });
493
494
495
496

    std::for_each(angles.begin(), angles.end(), testTheta);
  }

497
498
  /** Create peaks using Q in the lab frame,
   * then find the corresponding detector ID */
499
  void test_findDetector() {
500
501
502
503
504
    Peak p1(inst, 19999, 2.0);
    V3D Qlab1 = p1.getQLabFrame();
    V3D detPos1 = p1.getDetPos();

    // Construct using just Q
505
    Peak p2(inst, Qlab1, boost::optional<double>(detPos1.norm()));
506
    TS_ASSERT(p2.findDetector());
507
    comparePeaks(p1, p2);
508
509
510
511
    TS_ASSERT_EQUALS(p2.getBankName(), "bank1");
    TS_ASSERT_EQUALS(p2.getRow(), 99);
    TS_ASSERT_EQUALS(p2.getCol(), 99);
    TS_ASSERT_EQUALS(p2.getDetectorID(), 19999);
512
513
  }

514
  void test_getDetectorPosition() {
515
516
517
518
519
    const int detectorId = 19999;
    const double wavelength = 2;
    Peak p(inst, detectorId, wavelength);

    V3D a = p.getDetectorPosition();
Owen Arnold's avatar
Owen Arnold committed
520
    V3D b = p.getDetectorPositionNoCheck();
521
522
523
524

    TSM_ASSERT_EQUALS("Results should be the same", a, b);
  }

525
  void test_getDetectorPositionThrows() {
526
527
528
    const int detectorId = 19999;
    const double wavelength = 2;
    Peak p(inst, detectorId, wavelength);
529
530
531
532
533
534
535
    TSM_ASSERT_THROWS_NOTHING("Nothing wrong here, detector is valid",
                              p.getDetectorPosition());
    p.setQLabFrame(
        V3D(1, 1, 1),
        1.0); // This sets the detector pointer to null and detector id to -1;
    TSM_ASSERT_THROWS("Detector is not valid", p.getDetectorPosition(),
                      Mantid::Kernel::Exception::NullPointerException &);
536
537
  }

538
539
540
541
  void test_get_peak_shape_default() {
    Peak peak;
    const PeakShape &integratedShape = peak.getPeakShape();
    TS_ASSERT_EQUALS("none", integratedShape.shapeName());
542
543
  }

544
545
  void test_set_peak_shape() {
    using namespace testing;
546

547
    Peak peak;
548

549
550
551
    MockPeakShape *replacementShape = new MockPeakShape;
    EXPECT_CALL(*replacementShape, shapeName()).Times(1);
    peak.setPeakShape(replacementShape);
552

553
554
    const PeakShape &currentShape = peak.getPeakShape();
    currentShape.shapeName();
555

556
    TS_ASSERT(Mock::VerifyAndClearExpectations(replacementShape));
557
558
  }

Samuel Jackson's avatar
Samuel Jackson committed
559
560
561
  void test_get_intensity_over_sigma() {
    const int detectorId = 19999;
    const double wavelength = 2;
562
563
    const double intensity{100};
    const double sigma{10};
Samuel Jackson's avatar
Samuel Jackson committed
564
565
566
567
568
    Peak p(inst, detectorId, wavelength);

    p.setIntensity(intensity);
    p.setSigmaIntensity(sigma);

569
    TS_ASSERT_EQUALS(p.getIntensityOverSigma(), intensity / sigma);
Samuel Jackson's avatar
Samuel Jackson committed
570
571
572
573
574
  }

  void test_get_intensity_over_sigma_empty_sigma() {
    const int detectorId = 19999;
    const double wavelength = 2;
575
    const double intensity{10};
576
    const double sigma{0};
Samuel Jackson's avatar
Samuel Jackson committed
577
578
579
580
581
    Peak p(inst, detectorId, wavelength);

    p.setIntensity(intensity);
    p.setSigmaIntensity(sigma);

582
583
584
    const double expectedResult {0.0};
    const double tolerance {1e-10};
    TS_ASSERT_DELTA(p.getIntensityOverSigma(), expectedResult, tolerance);
Samuel Jackson's avatar
Samuel Jackson committed
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
  }

  void test_get_energy() {
    const int detectorId = 19999;
    const double wavelength = 2;
    const double initialEnergy{100};
    const double finalEnergy{110};
    Peak p(inst, detectorId, wavelength);

    p.setInitialEnergy(initialEnergy);
    p.setFinalEnergy(finalEnergy);

    TS_ASSERT_EQUALS(p.getEnergy(), initialEnergy - finalEnergy);
  }

600
private:
601
602
  void check_Contributing_Detectors(const Peak &peak,
                                    const std::vector<int> &expected) {
603
    auto peakIDs = peak.getContributingDetIDs();
604
    for (auto it = expected.begin(); it != expected.end(); ++it) {
605
      const int id = *it;
606
607
608
      TSM_ASSERT_EQUALS("Expected " + boost::lexical_cast<std::string>(id) +
                            " in contribution list",
                        1, peakIDs.count(id))
609
610
    }
  }
611
612
613
};

#endif /* MANTID_DATAOBJECTS_PEAKTEST_H_ */