Commit 43866074 authored by Savici, Andrei T's avatar Savici, Andrei T
Browse files

Merge pull request #15716 from mantidproject/15712_createDetector_Performance

Instrument Performance Tests and Improvements
parents 3cdb6ad7 eaf1d653
......@@ -27,7 +27,7 @@ enum det_topology {
rect, //< rectangular geometry
cyl, //< cylindrical geometry
undef //< the geometry is yet undefined, if you need to know the geometry, a
// method to identify it must be deployed
// method to identify it must be deployed
};
/** Interface class for detector objects.
......@@ -58,6 +58,9 @@ enum det_topology {
*/
class MANTID_GEOMETRY_DLL IDetector : public virtual IObjComponent {
public:
/// Create a cloned instance with a parameter map applied
virtual IDetector *cloneParameterized(const ParameterMap *map) const = 0;
/// Get the detector ID
virtual detid_t getID() const = 0;
......@@ -108,7 +111,7 @@ public:
/// (Empty) Constructor.
/// prevent Warning C4436
IDetector(){};
IDetector() {}
};
/// Shared pointer to IDetector
......
......@@ -48,8 +48,6 @@ public:
/// A string representation of the component type
std::string type() const override { return "DetectorComponent"; }
/// Constructor for parametrized version
Detector(const Detector *base, const ParameterMap *map);
Detector(const std::string &name, int id, IComponent *parent);
Detector(const std::string &name, int id, boost::shared_ptr<Object> shape,
IComponent *parent);
......@@ -57,6 +55,9 @@ public:
Component *clone() const override { return new Detector(*this); }
// IDetector methods
Detector *cloneParameterized(const ParameterMap *map) const override {
return new Detector(this, map);
}
detid_t getID() const override;
std::size_t nDets() const override {
return 1;
......@@ -88,6 +89,10 @@ private:
const detid_t m_id;
/// Flags if this is a monitor
bool m_isMonitor;
protected:
/// Constructor for parametrized version
Detector(const Detector *base, const ParameterMap *map);
};
} // namespace Geometry
......
......@@ -53,6 +53,9 @@ public:
void addDetector(IDetector_const_sptr det, bool &warn);
// IDetector methods
IDetector *cloneParameterized(const ParameterMap *) const override {
return nullptr;
}
detid_t getID() const override;
std::size_t nDets() const override;
Kernel::V3D getPos() const override;
......@@ -237,11 +240,11 @@ protected:
// functions inherited from IObjComponent
void getBoundingBox(double &, double &, double &, double &, double &,
double &) const {};
double &) const {}
void draw() const override{};
void drawObject() const override{};
void initDraw() const override{};
void draw() const override {}
void drawObject() const override {}
void initDraw() const override {}
/// Returns the shape of the Object
const boost::shared_ptr<const Object> shape() const override {
......
......@@ -49,9 +49,10 @@ class MANTID_GEOMETRY_DLL ParComponentFactory {
public:
/// Create a parameterized detector from the given base component and
/// ParameterMap and
/// return a shared_ptr<Detector>
static boost::shared_ptr<Detector> createDetector(const IDetector *base,
const ParameterMap *map);
/// return a shared_ptr<IDetector>
static boost::shared_ptr<IDetector> createDetector(const IDetector *base,
const ParameterMap *map);
/// Create a parameterized instrument from the given base and ParameterMap
static boost::shared_ptr<Instrument>
createInstrument(boost::shared_ptr<const Instrument> base,
......
......@@ -49,24 +49,32 @@ public:
/// A string representation of the component type
std::string type() const override { return "RectangularDetectorPixel"; }
/// Constructor for parametrized version
RectangularDetectorPixel(const RectangularDetectorPixel *base,
const ParameterMap *map);
RectangularDetectorPixel(const std::string &name, int id,
boost::shared_ptr<Object> shape, IComponent *parent,
RectangularDetector *panel, size_t row, size_t col);
RectangularDetectorPixel();
/// Create a cloned instance with a parameter map applied
RectangularDetectorPixel *
cloneParameterized(const ParameterMap *map) const override {
return new RectangularDetectorPixel(this, map);
}
const Kernel::V3D getRelativePos() const override;
protected:
private:
/// RectangularDetector that is the parent of this pixel.
RectangularDetector *m_panel;
/// Row of the pixel in the panel (y index)
size_t m_row;
/// Column of the pixel in the panel (x index)
size_t m_col;
protected:
/// Constructor for parametrized version
RectangularDetectorPixel(const RectangularDetectorPixel *base,
const ParameterMap *map);
};
} // namespace Geometry
......
......@@ -20,22 +20,12 @@ namespace Geometry {
* @param map A pointer to the ParameterMap
* @returns A pointer to a parameterized component
*/
boost::shared_ptr<Detector>
boost::shared_ptr<IDetector>
ParComponentFactory::createDetector(const IDetector *base,
const ParameterMap *map) {
// RectangularDetectorPixel subclasses Detector so it has to be checked
// before.
const RectangularDetectorPixel *rdp =
dynamic_cast<const RectangularDetectorPixel *>(base);
if (rdp)
return boost::make_shared<RectangularDetectorPixel>(rdp, map);
const Detector *baseDet = dynamic_cast<const Detector *>(base);
if (baseDet)
return boost::shared_ptr<Detector>(
new Detector(baseDet, map)); // g_detPool.create(baseDet,map);
return boost::shared_ptr<Detector>();
// Clone may be a Detector or RectangularDetectorPixel instance (or nullptr)
auto clone = base->cloneParameterized(map);
return boost::shared_ptr<IDetector>(clone);
}
/**
......@@ -63,14 +53,6 @@ ParComponentFactory::createInstrument(boost::shared_ptr<const Instrument> base,
IComponent_sptr
ParComponentFactory::create(boost::shared_ptr<const IComponent> base,
const ParameterMap *map) {
// RectangularDetectorPixel subclasses Detector so it has to be checked
// before.
const RectangularDetectorPixel *rdp =
dynamic_cast<const RectangularDetectorPixel *>(base.get());
if (rdp)
return boost::shared_ptr<IComponent>(
new RectangularDetectorPixel(rdp, map));
boost::shared_ptr<const IDetector> det_sptr =
boost::dynamic_pointer_cast<const IDetector>(base);
if (det_sptr) {
......
......@@ -8,6 +8,8 @@
#include "MantidGeometry/Instrument/RectangularDetector.h"
#include <cxxtest/TestSuite.h>
#include "MantidKernel/DateAndTime.h"
#include "MantidGeometry/Instrument/ParameterMap.h"
#include <boost/make_shared.hpp>
using namespace Mantid;
using namespace Mantid::Kernel;
......@@ -522,4 +524,50 @@ private:
Detector *det, *det2, *det3;
};
class InstrumentTestPerformance : public CxxTest::TestSuite {
public:
// This pair of boilerplate methods prevent the suite being created statically
// This means the constructor isn't called when running other tests
static InstrumentTestPerformance *createSuite() {
return new InstrumentTestPerformance();
}
static void destroySuite(InstrumentTestPerformance *suite) { delete suite; }
InstrumentTestPerformance() {
Mantid::Kernel::V3D sourcePos(0, 0, 0);
Mantid::Kernel::V3D samplePos(0, 0, 1);
Mantid::Kernel::V3D trolley1Pos(0, 0, 3);
Mantid::Kernel::V3D trolley2Pos(0, 0, 6);
m_instrumentNotParameterized = ComponentCreationHelper::sansInstrument(
sourcePos, samplePos, trolley1Pos, trolley2Pos);
auto map = boost::make_shared<ParameterMap>();
m_instrumentParameterized =
boost::make_shared<Instrument>(m_instrumentNotParameterized, map);
}
void test_access_non_parameterized() {
const detid_t nPixels = 100 * 100 * 6;
double pos_x = 0;
for (detid_t i = 1; i <= nPixels; i++) {
pos_x += m_instrumentNotParameterized->getDetector(i)->getPos().X();
}
}
void test_access_parameterized() {
const detid_t nPixels = 100 * 100 * 6;
double pos_x = 0;
for (detid_t i = 1; i <= nPixels; i++) {
pos_x += m_instrumentParameterized->getDetector(i)->getPos().X();
}
}
private:
Instrument_sptr m_instrumentParameterized;
Instrument_sptr m_instrumentNotParameterized;
};
#endif /*INSTRUMENTTEST_H_*/
......@@ -20,7 +20,7 @@ public:
boost::dynamic_pointer_cast<const Detector>(idet).get();
ParameterMap *map = new ParameterMap();
boost::shared_ptr<Detector> pdet;
boost::shared_ptr<IDetector> pdet;
TS_ASSERT_THROWS_NOTHING(pdet =
ParComponentFactory::createDetector(det, map));
TS_ASSERT(pdet);
......
......@@ -14,13 +14,13 @@ public:
Detector det("det1", 0, 0);
ParameterMap_sptr pmap(new ParameterMap());
Detector pdet(&det, pmap.get());
boost::shared_ptr<Detector> pdet(det.cloneParameterized(pmap.get()));
TS_ASSERT_EQUALS(pdet.getName(), "det1");
TS_ASSERT(!pdet.getParent());
TS_ASSERT_EQUALS(pdet.getID(), 0);
TS_ASSERT(!pdet.isMasked());
TS_ASSERT(!pdet.isMonitor());
TS_ASSERT_EQUALS(pdet->getName(), "det1");
TS_ASSERT(!pdet->getParent());
TS_ASSERT_EQUALS(pdet->getID(), 0);
TS_ASSERT(!pdet->isMasked());
TS_ASSERT(!pdet->isMonitor());
}
void testNameParentConstructor() {
......@@ -28,13 +28,13 @@ public:
Detector det("det1", 0, &parent);
ParameterMap_sptr pmap(new ParameterMap());
Detector pdet(&det, pmap.get());
boost::shared_ptr<Detector> pdet(det.cloneParameterized(pmap.get()));
TS_ASSERT_EQUALS(pdet.getName(), "det1");
TS_ASSERT(pdet.getParent());
TS_ASSERT_EQUALS(pdet.getID(), 0);
TS_ASSERT(!pdet.isMasked());
TS_ASSERT(!pdet.isMonitor());
TS_ASSERT_EQUALS(pdet->getName(), "det1");
TS_ASSERT(pdet->getParent());
TS_ASSERT_EQUALS(pdet->getID(), 0);
TS_ASSERT(!pdet->isMasked());
TS_ASSERT(!pdet->isMonitor());
}
void testId() {
......@@ -42,42 +42,42 @@ public:
Detector det("det1", id1, 0);
ParameterMap_sptr pmap(new ParameterMap());
Detector pdet(&det, pmap.get());
boost::shared_ptr<Detector> pdet(det.cloneParameterized(pmap.get()));
TS_ASSERT_EQUALS(pdet.getID(), id1);
TS_ASSERT_EQUALS(pdet->getID(), id1);
}
void testType() {
Detector det("det", 0, 0);
ParameterMap_sptr pmap(new ParameterMap());
Detector pdet(&det, pmap.get());
boost::shared_ptr<Detector> pdet(det.cloneParameterized(pmap.get()));
TS_ASSERT_EQUALS(pdet.type(), "DetectorComponent");
TS_ASSERT_EQUALS(pdet->type(), "DetectorComponent");
}
void testMasked() {
Detector det("det", 0, 0);
ParameterMap_sptr pmap(new ParameterMap());
Detector pdet(&det, pmap.get());
boost::shared_ptr<Detector> pdet(det.cloneParameterized(pmap.get()));
TS_ASSERT(!pdet.isMasked());
TS_ASSERT(!pdet->isMasked());
pmap->addBool(&det, "masked", true);
TS_ASSERT(pdet.isMasked());
TS_ASSERT(pdet->isMasked());
}
void testMonitor() {
Detector det("det", 0, 0);
ParameterMap_sptr pmap(new ParameterMap());
Detector pdet(&det, pmap.get());
boost::shared_ptr<Detector> pdet(det.cloneParameterized(pmap.get()));
TS_ASSERT(!pdet.isMonitor());
TS_ASSERT(!pdet->isMonitor());
TS_ASSERT_THROWS_NOTHING(det.markAsMonitor());
TS_ASSERT(pdet.isMonitor());
TS_ASSERT(pdet->isMonitor());
TS_ASSERT_THROWS_NOTHING(det.markAsMonitor(false));
TS_ASSERT(!pdet.isMonitor());
TS_ASSERT(!pdet->isMonitor());
}
void testGetNumberParameter() {
......@@ -85,8 +85,8 @@ public:
ParameterMap_sptr pmap(new ParameterMap());
pmap->add("double", &det, "testparam", 5.0);
Detector pdet(&det, pmap.get());
IDetector *idet = static_cast<IDetector *>(&pdet);
boost::shared_ptr<Detector> pdet(det.cloneParameterized(pmap.get()));
IDetector *idet = static_cast<IDetector *>(pdet.get());
TS_ASSERT_EQUALS(idet->getNumberParameter("testparam").size(), 1);
TS_ASSERT_DELTA(idet->getNumberParameter("testparam")[0], 5.0, 1e-08);
......@@ -97,8 +97,8 @@ public:
ParameterMap_sptr pmap(new ParameterMap());
pmap->add("V3D", &det, "testparam", Mantid::Kernel::V3D(0.5, 1.0, 1.5));
Detector pdet(&det, pmap.get());
IDetector *idet = static_cast<IDetector *>(&pdet);
boost::shared_ptr<Detector> pdet(det.cloneParameterized(pmap.get()));
IDetector *idet = static_cast<IDetector *>(pdet.get());
std::vector<Mantid::Kernel::V3D> pos =
idet->getPositionParameter("testparam");
......@@ -115,8 +115,8 @@ public:
ParameterMap_sptr pmap(new ParameterMap());
pmap->add("Quat", &det, "testparam",
Mantid::Kernel::Quat(1.0, 0.25, 0.5, 0.75));
Detector pdet(&det, pmap.get());
IDetector *idet = static_cast<IDetector *>(&pdet);
boost::shared_ptr<Detector> pdet(det.cloneParameterized(pmap.get()));
IDetector *idet = static_cast<IDetector *>(pdet.get());
std::vector<Mantid::Kernel::Quat> rot =
idet->getRotationParameter("testparam");
......
......@@ -161,6 +161,12 @@ Mantid::Geometry::Instrument_sptr
createMinimalInstrument(const Mantid::Kernel::V3D &sourcePos,
const Mantid::Kernel::V3D &samplePos,
const Mantid::Kernel::V3D &detectorPos);
Mantid::Geometry::Instrument_sptr
sansInstrument(const Mantid::Kernel::V3D &sourcePos,
const Mantid::Kernel::V3D &samplePos,
const Mantid::Kernel::V3D &trolley1Pos,
const Mantid::Kernel::V3D &trolley2Pos);
}
#endif // COMPONENTCREATIONHELPERS_H_
......@@ -586,4 +586,82 @@ createMinimalInstrument(const Mantid::Kernel::V3D &sourcePos,
return instrument;
}
CompAssembly *makeBank(size_t width, size_t height, Instrument *instrument) {
double width_d = double(width);
double height_d = double(height);
static int bankNo = 1;
auto bank = new CompAssembly("Bank" + std::to_string(bankNo++));
static size_t id = 1;
for (size_t i = 0; i < width; ++i) {
for (size_t j = 0; j < height; ++j) {
Detector *det = new Detector("pixel", int(id++) /*detector id*/, bank);
det->setPos(V3D{double(i), double(j), double(0)});
det->setShape(createSphere(0.01 /*1cm*/, V3D(0, 0, 0), "1"));
bank->add(det);
instrument->markAsDetector(det);
}
}
bank->setPos(V3D{width_d / 2, height_d / 2, 0});
return bank;
}
Instrument_sptr sansInstrument(const Mantid::Kernel::V3D &sourcePos,
const Mantid::Kernel::V3D &samplePos,
const Mantid::Kernel::V3D &trolley1Pos,
const Mantid::Kernel::V3D &trolley2Pos) {
/*
This has been generated for comparison with newer Instrument designs. It is
therefore not
an exact representation of an instrument one might expect to create for SANS.
*/
auto instrument = boost::make_shared<Instrument>();
instrument->setReferenceFrame(boost::make_shared<ReferenceFrame>(
Mantid::Geometry::Y /*up*/, Mantid::Geometry::Z /*along*/, Left,
"0,0,0"));
// A source
ObjComponent *source = new ObjComponent("source");
source->setPos(sourcePos);
source->setShape(createSphere(0.01 /*1cm*/, V3D(0, 0, 0), "1"));
instrument->add(source);
instrument->markAsSource(source);
// A sample
ObjComponent *sample = new ObjComponent("some-surface-holder");
sample->setPos(samplePos);
sample->setShape(createSphere(0.01 /*1cm*/, V3D(0, 0, 0), "1"));
instrument->add(sample);
instrument->markAsSamplePos(sample);
size_t width = 100;
size_t height = 100;
CompAssembly *trolley1 = new CompAssembly("Trolley1");
trolley1->setPos(trolley1Pos);
CompAssembly *trolley2 = new CompAssembly("Trolley2");
trolley2->setPos(trolley2Pos);
CompAssembly *N = makeBank(width, height, instrument.get());
trolley1->add(N);
CompAssembly *E = makeBank(width, height, instrument.get());
trolley1->add(E);
CompAssembly *S = makeBank(width, height, instrument.get());
trolley1->add(S);
CompAssembly *W = makeBank(width, height, instrument.get());
trolley1->add(W);
CompAssembly *l_curtain = makeBank(width, height, instrument.get());
trolley2->add(l_curtain);
CompAssembly *r_curtain = makeBank(width, height, instrument.get());
trolley2->add(r_curtain);
instrument->add(trolley1);
instrument->add(trolley2);
return instrument;
}
}
......@@ -75,6 +75,7 @@ Performance
-----------
- :ref:`ChangeBinOffset <algm-ChangeBinOffset>` should now run faster for a :ref:`MatrixWorkspace <MatrixWorkspace>` (not EventWorkspaces).
- Applying ParameterMaps to Detectors now about 30% faster. Algorithms that involve applying ParameterMaps will see performance improvements.
CurveFitting
------------
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment