PeakTest.h 19.7 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
11
12
#include "MantidKernel/UnitFactory.h"
#include "MantidKernel/Unit.h"
#include "MantidKernel/V3D.h"
#include "MantidKernel/PhysicalConstants.h"
#include "MantidGeometry/Instrument/ReferenceFrame.h"
13
#include <gmock/gmock.h>
14
15

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

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

Hahn, Steven's avatar
Hahn, Steven committed
22
23
24
25
26
27
28
29
30
31
32
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;
}
}

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

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

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

49
50
  }

51
  void test_constructor() {
52
53
54
55
56
57
    // 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)
58
59
    TS_ASSERT_EQUALS(p.getDetector()->getID(), 10000)
    TS_ASSERT_EQUALS(p.getInstrument(), inst)
60
    check_Contributing_Detectors(p, std::vector<int>(1, 10000));
61
62
  }

63
  void test_constructorHKL() {
64
    // detector IDs start at 10000
65
    Peak p(inst, 10000, 2.0, V3D(1, 2, 3));
66
67
68
69
70
71
    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)
72
    check_Contributing_Detectors(p, std::vector<int>(1, 10000));
73
74
  }

75
76
77
78
79
80
81
82
83
  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;

84
    // detector IDs start at 10000
85
86
87
    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);
88
89
90
91
92
93
    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)
94
    TS_ASSERT_EQUALS(p.getGoniometerMatrix(), mat);
95
    check_Contributing_Detectors(p, std::vector<int>(1, 10000));
96
97
  }

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

104
    const Mantid::Geometry::IPeak &ipeak = p;
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
    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);
  }

120
  void test_copyConstructor() {
121
    Peak p(inst, 10102, 2.0);
122
    p.setHKL(1, 2, 3);
123
124
125
126
127
128
129
130
131
132
    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());
133
134
    TS_ASSERT_EQUALS(p.getDetector(), p2.getDetector());
    TS_ASSERT_EQUALS(p.getInstrument(), p2.getInstrument());
135
136
    TS_ASSERT_EQUALS(p.getPeakShape().shapeName(),
                     p2.getPeakShape().shapeName());
137
    check_Contributing_Detectors(p2, std::vector<int>(1, 10102));
138
139
  }

140
  void test_getValueByColName() {
141
    Peak p(inst, 10102, 2.0);
142
    p.setHKL(1, 2, 3);
143
144
145
146
147
148
149
150
    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())
151
    TS_ASSERT_THROWS_ANYTHING(p.getValueByColName("bankname"));
152
153
  }

154
  /** Set the wavelength and see the other "versions" of it get calculated. */
155
156
  void test_wavelength_conversion() {
    // 1 angstroms wavelength, and at the opposite corner of the detector
157
158
    Peak p(inst, 19999, 1.0);
    // Energy in meV
159
160
    TS_ASSERT_DELTA(p.getInitialEnergy(), 81.805, 1e-3) // Conversion table at :
    // www.ncnr.nist.gov/instruments/dcs/dcs_usersguide/Conversion_Factors.pdf
161
    TS_ASSERT_DELTA(p.getFinalEnergy(), p.getInitialEnergy(), 1e-5)
162
163
164
    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
165
    TS_ASSERT_DELTA(p.getDSpacing(), d, 1e-3);
166
167
168
169
    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);
170
171
  }

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

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

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

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

193
  void test_GoniometerMatrix() {
194
    Peak p(inst, 10000, 2.0);
195
196
197
198
199
200
201
202
203
204
205
206
207
    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);
208
    // Matrix must be 3x3
209
210
    Matrix<double> mat2(4, 3);
    TS_ASSERT_THROWS_ANYTHING(p.setGoniometerMatrix(mat2));
211
212
  }

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

232
  void test_getBank_and_row() {
233
234
235
236
    Peak p(inst, 10000, 2.0);
    TS_ASSERT_EQUALS(p.getBankName(), "bank1")
    TS_ASSERT_EQUALS(p.getRow(), 0)
    TS_ASSERT_EQUALS(p.getCol(), 0)
237
238
239
240
241
242
    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)
243
244
  }

245
  void test_getQSampleFrame() {
246
    // Peak 3 is phi,chi,omega of 90,0,0; giving this matrix:
247
    Matrix<double> r2(3, 3, false);
248
249
250
251
252
253
254
255
256
257
258
    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();
259
260
    // If we re-rotate q in the sample frame by the gonio matrix, we should get
    // q in the lab frame
261
262
263
264
265
266
    V3D qSampleRotated = r2 * qSample;

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

Samuel Jackson's avatar
Samuel Jackson committed
267
268
269
270
271
272
273
274
275
276
277
278
  void test_getQLabFrame() {
      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);
  }

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

  /** Compare two peaks, but not the detector IDs etc. */
289
290
291
292
293
294
295
296
297
298
299
300
301
302
  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));
303
304
305
  }

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

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

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

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

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

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

    // test with & without extended detector space
392
    // extended space is a sphere, so all points should fall radius*detector
393
394
    // direction away from the detector direction with extended space
    auto testQ = [this, &sphereInst, &refFrame, &refBeamDir](const auto q) {
395
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
      // 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)
422
423
424
425
426
427
428
429
430
431
    };

    // 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;
432
433
434
    std::generate(
        xDirections.begin(), xDirections.end(),
        [&index, &startValue]() { return startValue + index++ * 0.1; });
435
436
437
438
439

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

    yDirections = xDirections;

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

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

    // test with & without extended detector space
467
    // extended space is a sphere, so all points should fall radius*detector
468
469
    // direction away from the detector direction with extended space
    auto testTheta = [this, &sphereInst, &radius](const auto theta) {
470
471
472
473
474
475
476
477
478
479
480
481
482
      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);
483
484
485
486
487
    };

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

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

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

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

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

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

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

523
  void test_getDetectorPositionThrows() {
524
525
526
    const int detectorId = 19999;
    const double wavelength = 2;
    Peak p(inst, detectorId, wavelength);
527
528
529
530
531
532
533
    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 &);
534
535
  }

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

542
543
  void test_set_peak_shape() {
    using namespace testing;
544

545
    Peak peak;
546

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

551
552
    const PeakShape &currentShape = peak.getPeakShape();
    currentShape.shapeName();
553

554
    TS_ASSERT(Mock::VerifyAndClearExpectations(replacementShape));
555
556
  }

557
private:
558
559
  void check_Contributing_Detectors(const Peak &peak,
                                    const std::vector<int> &expected) {
560
    auto peakIDs = peak.getContributingDetIDs();
561
    for (auto it = expected.begin(); it != expected.end(); ++it) {
562
      const int id = *it;
563
564
565
      TSM_ASSERT_EQUALS("Expected " + boost::lexical_cast<std::string>(id) +
                            " in contribution list",
                        1, peakIDs.count(id))
566
567
    }
  }
568
569
570
};

#endif /* MANTID_DATAOBJECTS_PEAKTEST_H_ */