diff --git a/Framework/API/inc/MantidAPI/ComponentInfo.h b/Framework/API/inc/MantidAPI/ComponentInfo.h index c326c90e4e6a328fbb07b77d74d669f7288cc720..6c1221d6818926d2165273445b8daf5cab1c12ec 100644 --- a/Framework/API/inc/MantidAPI/ComponentInfo.h +++ b/Framework/API/inc/MantidAPI/ComponentInfo.h @@ -55,8 +55,9 @@ private: public: ComponentInfo(const Mantid::Beamline::ComponentInfo &componentInfo, - std::vector<Mantid::Geometry::IComponent *> &&componentIds); + const std::vector<Mantid::Geometry::IComponent *> componentIds); std::vector<size_t> detectorIndices(size_t componentIndex) const; + std::vector<Mantid::Geometry::IComponent *> componentIds() const; size_t size() const; size_t indexOf(Geometry::IComponent *id) const; }; diff --git a/Framework/API/inc/MantidAPI/ExperimentInfo.h b/Framework/API/inc/MantidAPI/ExperimentInfo.h index 538c42823090520dfbaf8068e9931bebcb6990e1..ade50cdc70fd750401833d7316f3900eaf1be3df 100644 --- a/Framework/API/inc/MantidAPI/ExperimentInfo.h +++ b/Framework/API/inc/MantidAPI/ExperimentInfo.h @@ -228,6 +228,7 @@ private: boost::shared_ptr<Beamline::ComponentInfo> m_componentInfo; std::unique_ptr<API::ComponentInfo> m_componentInfoWrapper; + std::vector<Geometry::ComponentID> m_componentIds; mutable std::unique_ptr<Beamline::SpectrumInfo> m_spectrumInfo; mutable std::unique_ptr<SpectrumInfo> m_spectrumInfoWrapper; diff --git a/Framework/API/inc/MantidAPI/InfoComponentVisitor.h b/Framework/API/inc/MantidAPI/InfoComponentVisitor.h index 88a877db30c0f1dbd9001aeaad8fa9f32a6a592f..3bc7653106c47c2d0c739590eb3f5864abd4c9b7 100644 --- a/Framework/API/inc/MantidAPI/InfoComponentVisitor.h +++ b/Framework/API/inc/MantidAPI/InfoComponentVisitor.h @@ -64,6 +64,9 @@ private: /// Only Assemblies and other NON-detectors yield ranges std::vector<std::pair<size_t, size_t>> m_ranges; + /// Counter for dropped detectors + size_t m_droppedDetectors = 0; + public: InfoComponentVisitor(const size_t nDetectors, std::function<size_t(Mantid::detid_t)> mapperFunc); diff --git a/Framework/API/src/ComponentInfo.cpp b/Framework/API/src/ComponentInfo.cpp index c221a31e9498396711da22ce303a8ed9209a2ff3..329fd63fae1d34f6afb2b7b022f373b166e78cc9 100644 --- a/Framework/API/src/ComponentInfo.cpp +++ b/Framework/API/src/ComponentInfo.cpp @@ -12,17 +12,19 @@ namespace API { /** * Constructor - * @param componentInfo : Beamline wrapped ComponentInfo - * @param componentIds : Component Ids ordered by component index + * @brief ComponentInfo::ComponentInfo + * @param componentInfo + * @param componentIds : ComponentIDs ordered by component + * index */ -ComponentInfo::ComponentInfo(const Beamline::ComponentInfo &componentInfo, - std::vector<Geometry::ComponentID> &&componentIds) +ComponentInfo::ComponentInfo( + const Mantid::Beamline::ComponentInfo &componentInfo, + std::vector<Mantid::Geometry::IComponent *> componentIds) : m_componentInfo(componentInfo), - m_componentIds( - boost::make_shared<std::vector<Geometry::ComponentID>>(componentIds)), + m_componentIds(boost::make_shared<std::vector<Geometry::ComponentID>>( + std::move(componentIds))), m_compIDToIndex(boost::make_shared< std::unordered_map<Geometry::IComponent *, size_t>>()) { - /* * Ideally we would check here that componentIds.size() == * m_componentInfo.size(). @@ -39,6 +41,10 @@ ComponentInfo::detectorIndices(size_t componentIndex) const { return m_componentInfo.detectorIndices(componentIndex); } +std::vector<Geometry::IComponent *> ComponentInfo::componentIds() const { + return *m_componentIds; +} + size_t ComponentInfo::size() const { return m_componentInfo.size(); } size_t ComponentInfo::indexOf(Geometry::IComponent *id) const { diff --git a/Framework/API/src/ExperimentInfo.cpp b/Framework/API/src/ExperimentInfo.cpp index ec99f2f5170f15b08ecd9bc9cd531637a53b2950..36ae40ce718c98ed33f2f70fafc45cb1d0c1a27e 100644 --- a/Framework/API/src/ExperimentInfo.cpp +++ b/Framework/API/src/ExperimentInfo.cpp @@ -71,6 +71,7 @@ ExperimentInfo::ExperimentInfo() m_detectorInfo(boost::make_shared<Beamline::DetectorInfo>()), m_componentInfo(boost::make_shared<Beamline::ComponentInfo>()) { m_parmap->setDetectorInfo(m_detectorInfo); + m_parmap->setComponentInfo(m_componentInfo, std::vector<ComponentID>{}); m_detectorInfoWrapper = Kernel::make_unique<DetectorInfo>( *m_detectorInfo, getInstrument(), m_parmap.get()); } @@ -102,7 +103,6 @@ void ExperimentInfo::copyExperimentInfoFrom(const ExperimentInfo *other) { for (const auto &chopper : other->m_choppers) { m_choppers.push_back(chopper->clone()); } - *m_detectorInfo = *other->m_detectorInfo; // We do not copy Beamline::SpectrumInfo (which contains detector grouping // information) for now: // - For MatrixWorkspace, grouping information is still stored in ISpectrum @@ -188,22 +188,33 @@ void checkDetectorInfoSize(const Instrument &instr, } boost::shared_ptr<Beamline::ComponentInfo> -makeComponentInfo(const Instrument &oldInstr, +makeComponentInfo(const Instrument &instrument, const API::DetectorInfo &detectorInfo, std::vector<Geometry::ComponentID> &componentIds) { - InfoComponentVisitor visitor( - detectorInfo.size(), - std::bind(&DetectorInfo::indexOf, &detectorInfo, std::placeholders::_1)); + if (instrument.hasComponentInfo()) { + const auto &componentInfo = instrument.componentInfo(); + componentIds = instrument.componentIds(); + return boost::make_shared<Beamline::ComponentInfo>(componentInfo); + } else { + InfoComponentVisitor visitor( + detectorInfo.size(), std::bind(&DetectorInfo::indexOf, &detectorInfo, + std::placeholders::_1)); - // Register everything via visitor - oldInstr.registerContents(visitor); - // Extract component ids. We need this for the ComponentInfo wrapper. - componentIds = visitor.componentIds(); + if (instrument.isParametrized()) { + // Register everything via visitor + instrument.baseInstrument()->registerContents(visitor); + } else { + instrument.registerContents(visitor); + } - return boost::make_shared<Mantid::Beamline::ComponentInfo>( - visitor.assemblySortedDetectorIndices(), - visitor.componentDetectorRanges()); + // Extract component ids. We need this for the ComponentInfo wrapper. + componentIds = visitor.componentIds(); + + return boost::make_shared<Mantid::Beamline::ComponentInfo>( + visitor.assemblySortedDetectorIndices(), + visitor.componentDetectorRanges()); + } } void clearPositionAndRotationsParameters(ParameterMap &pmap, @@ -285,11 +296,10 @@ void ExperimentInfo::setInstrument(const Instrument_const_sptr &instr) { m_detectorInfoWrapper = Kernel::make_unique<DetectorInfo>( *m_detectorInfo, getInstrument(), m_parmap.get()); - std::vector<Geometry::ComponentID> componentIds; - m_componentInfo = - makeComponentInfo(*sptr_instrument, detectorInfo(), componentIds); - m_componentInfoWrapper = Kernel::make_unique<ComponentInfo>( - *m_componentInfo, std::move(componentIds)); + m_componentInfo = makeComponentInfo(*instr, detectorInfo(), m_componentIds); + m_parmap->setComponentInfo(m_componentInfo, m_componentIds); + m_componentInfoWrapper = + Kernel::make_unique<ComponentInfo>(*m_componentInfo, m_componentIds); // Detector IDs that were previously dropped because they were not part of the // instrument may now suddenly be valid, so we have to reinitialize the // detector grouping. Also the index corresponding to specific IDs may have @@ -308,6 +318,7 @@ Instrument_const_sptr ExperimentInfo::getInstrument() const { auto instrument = Geometry::ParComponentFactory::createInstrument( sptr_instrument, m_parmap); instrument->setDetectorInfo(m_detectorInfo); + instrument->setComponentInfo(m_componentInfo, m_componentIds); return instrument; } diff --git a/Framework/API/src/InfoComponentVisitor.cpp b/Framework/API/src/InfoComponentVisitor.cpp index 8043a2202ca54545085739680da10b4e2f217c32..71ef479bf0aa87871c845c9579e4172c59254263 100644 --- a/Framework/API/src/InfoComponentVisitor.cpp +++ b/Framework/API/src/InfoComponentVisitor.cpp @@ -63,8 +63,17 @@ void InfoComponentVisitor::registerGenericComponent( */ void InfoComponentVisitor::registerDetector(const IDetector &detector) { - const auto detectorIndex = - m_detectorIdToIndexMapperFunction(detector.getID()); + size_t detectorIndex = 0; + try { + detectorIndex = m_detectorIdToIndexMapperFunction(detector.getID()); + } catch (std::out_of_range &) { + /* + Do not register a detector with an invalid id. if we can't determine + the index, we cannot register it in the right place! + */ + ++m_droppedDetectors; + return; + } /* Unfortunately Mantid supports having detectors attached to an * instrument that have an an invalid or duplicate detector id. @@ -124,7 +133,9 @@ InfoComponentVisitor::componentIds() const { * @return The total size of the components visited. * This will be the same as the number of IDs. */ -size_t InfoComponentVisitor::size() const { return m_componentIds.size(); } +size_t InfoComponentVisitor::size() const { + return m_componentIds.size() - m_droppedDetectors; +} } // namespace API } // namespace Mantid diff --git a/Framework/API/test/ExperimentInfoTest.h b/Framework/API/test/ExperimentInfoTest.h index f00fbfb9d97ef830dc56302e325bcec50f6b3ac9..f95ecd7902094b18d24dad0b708e2a3eaa40e41b 100644 --- a/Framework/API/test/ExperimentInfoTest.h +++ b/Framework/API/test/ExperimentInfoTest.h @@ -964,4 +964,48 @@ private: } }; +class ExperimentInfoTestPerformance : public CxxTest::TestSuite { +private: + boost::shared_ptr<Mantid::Geometry::Instrument> m_bareInstrument; + boost::shared_ptr<const Mantid::Geometry::Instrument> m_provisionedInstrument; + +public: + // This pair of boilerplate methods prevent the suite being created statically + // This means the constructor isn't called when running other tests + static ExperimentInfoTestPerformance *createSuite() { + return new ExperimentInfoTestPerformance(); + } + static void destroySuite(ExperimentInfoTestPerformance *suite) { + delete suite; + } + + ExperimentInfoTestPerformance() { + + const int nPixels = 1000; + m_bareInstrument = ComponentCreationHelper::createTestInstrumentRectangular( + 1 /*n banks*/, nPixels, 1 /*sample-bank distance*/); + + ExperimentInfo tmp; + tmp.setInstrument(m_bareInstrument); + m_provisionedInstrument = tmp.getInstrument(); + } + + void + test_setInstrument_when_instrument_lacks_detectorInfo_and_componentInfo() { + /* + * This is similar to what will happen during LoadEmptyInstrument + */ + ExperimentInfo expInfo; + expInfo.setInstrument(m_bareInstrument); + } + void test_setInstrument_when_new_instrument_is_fully_provisioned() { + /* + * This should be the case for any workspaces after they have initially had + * an instrument + * set upon them via setInstrument. + */ + ExperimentInfo expInfo; + expInfo.setInstrument(m_provisionedInstrument); + } +}; #endif /* MANTID_API_EXPERIMENTINFOTEST_H_ */ diff --git a/Framework/API/test/InfoComponentVisitorTest.h b/Framework/API/test/InfoComponentVisitorTest.h index 3b64c5c3a1132e681c7895ba1145ec8ded865018..1f9cb1c1f7f673b76a88ad0c778ca8ea67b148a6 100644 --- a/Framework/API/test/InfoComponentVisitorTest.h +++ b/Framework/API/test/InfoComponentVisitorTest.h @@ -36,7 +36,14 @@ public: // Visit everything visitee->registerContents(visitor); - TSM_ASSERT_EQUALS("Should have registered 4 components", visitor.size(), 4); + size_t expectedSize = 0; + ++expectedSize; // source + ++expectedSize; // sample + ++expectedSize; // Detector + ++expectedSize; // instrument + + TSM_ASSERT_EQUALS("Should have registered 4 components", visitor.size(), + expectedSize); } void test_visitor_detector_indexes_check() { @@ -129,6 +136,66 @@ public: TS_ASSERT_EQUALS(ranges[2].first, 0); TS_ASSERT_EQUALS(ranges[2].second, 1); } + + void test_visitor_drops_detectors_without_id() { + /* + We have to go via DetectorInfo::indexOf to get the index of a detector. + if this throws because the detector has an invalid id, we are forced to + drop it. + + Some IDFs i.e. SNAP have montiors with detector ids < 0. + */ + + // Create a very basic instrument to visit + auto visitee = createMinimalInstrument(V3D(0, 0, 0) /*source pos*/, + V3D(10, 0, 0) /*sample pos*/ + , + V3D(11, 0, 0) /*detector position*/); + + // Create the visitor. Note any access to the indexOf lambda will throw for + // detectors. + InfoComponentVisitor visitor(1, [](const Mantid::detid_t) -> size_t { + throw std::out_of_range(""); + }); + + // Visit everything + visitee->registerContents(visitor); + + size_t expectedSize = 0; + ++expectedSize; // source + ++expectedSize; // sample + ++expectedSize; // instrument + // Note no detector counted + TS_ASSERT_EQUALS(visitor.size(), expectedSize); + } }; +class InfoComponentVisitorTestPerformance : public CxxTest::TestSuite { +private: + const int m_nPixels = 1000; + boost::shared_ptr<Mantid::Geometry::Instrument> m_instrument; + +public: + // This pair of boilerplate methods prevent the suite being created statically + // This means the constructor isn't called when running other tests + static InfoComponentVisitorTestPerformance *createSuite() { + return new InfoComponentVisitorTestPerformance(); + } + static void destroySuite(InfoComponentVisitorTestPerformance *suite) { + delete suite; + } + + InfoComponentVisitorTestPerformance() { + m_instrument = ComponentCreationHelper::createTestInstrumentRectangular( + 1 /*n banks*/, m_nPixels, 1 /*sample-bank distance*/); + } + + void test_process_rectangular_instrument() { + InfoComponentVisitor visitor( + m_nPixels * m_nPixels, + [](const Mantid::detid_t id) { return static_cast<size_t>(id); }); + m_instrument->registerContents(visitor); + TS_ASSERT(visitor.size() >= size_t(m_nPixels * m_nPixels)); + } +}; #endif /* MANTID_API_INFOCOMPONENTVISITORTEST_H_ */ diff --git a/Framework/Algorithms/test/DiffractionFocussing2Test.h b/Framework/Algorithms/test/DiffractionFocussing2Test.h index 7f8cb32fdfe1e9cc5d015dfa147344e835e498f9..df4762852c2a30c380907bb6c5963c17a17b77cc 100644 --- a/Framework/Algorithms/test/DiffractionFocussing2Test.h +++ b/Framework/Algorithms/test/DiffractionFocussing2Test.h @@ -262,6 +262,7 @@ public: IAlgorithm_sptr alg = AlgorithmFactory::Instance().create("LoadEmptyInstrument", 1); alg->initialize(); + alg->setRethrows(true); alg->setPropertyValue("Filename", "SNAP_Definition.xml"); alg->setPropertyValue("OutputWorkspace", "SNAP_empty"); alg->setPropertyValue("MakeEventWorkspace", "1"); diff --git a/Framework/Beamline/inc/MantidBeamline/ComponentInfo.h b/Framework/Beamline/inc/MantidBeamline/ComponentInfo.h index f37243f8ae84054557fb1874a2090f666bfbb62a..b0296fd79ca72602f8b28b6ec93617b523b5723c 100644 --- a/Framework/Beamline/inc/MantidBeamline/ComponentInfo.h +++ b/Framework/Beamline/inc/MantidBeamline/ComponentInfo.h @@ -40,7 +40,7 @@ class MANTID_BEAMLINE_DLL ComponentInfo { private: boost::shared_ptr<std::vector<size_t>> m_assemblySortedDetectorIndices; boost::shared_ptr<const std::vector<std::pair<size_t, size_t>>> m_ranges; - const size_t m_size = 0; + size_t m_size = 0; public: ComponentInfo(); diff --git a/Framework/Geometry/inc/MantidGeometry/Instrument.h b/Framework/Geometry/inc/MantidGeometry/Instrument.h index 5297cd70c1024a5593966b3b0ab67858e96fc455..8d04eed3b585f73b542dc96002fc3299292401f1 100644 --- a/Framework/Geometry/inc/MantidGeometry/Instrument.h +++ b/Framework/Geometry/inc/MantidGeometry/Instrument.h @@ -19,6 +19,7 @@ namespace Mantid { typedef std::map<detid_t, Geometry::IDetector_const_sptr> detid2det_map; namespace Beamline { +class ComponentInfo; class DetectorInfo; } namespace Geometry { @@ -243,10 +244,16 @@ public: bool hasDetectorInfo() const; const Beamline::DetectorInfo &detectorInfo() const; + bool hasComponentInfo() const; + const Beamline::ComponentInfo &componentInfo() const; + size_t detectorIndex(const detid_t detID) const; void setDetectorInfo(boost::shared_ptr<const Beamline::DetectorInfo> detectorInfo); - + void setComponentInfo( + boost::shared_ptr<const Beamline::ComponentInfo> componentInfo, + std::vector<Geometry::ComponentID> componentIds); + const std::vector<Geometry::ComponentID> &componentIds() const; boost::shared_ptr<ParameterMap> makeLegacyParameterMap() const; private: @@ -327,6 +334,9 @@ private: /// Pointer to the DetectorInfo object. NULL unless the instrument is /// associated with an ExperimentInfo object. boost::shared_ptr<const Beamline::DetectorInfo> m_detectorInfo{nullptr}; + + boost::shared_ptr<const Beamline::ComponentInfo> m_componentInfo{nullptr}; + std::vector<Geometry::ComponentID> m_componentIds; }; namespace Conversion { diff --git a/Framework/Geometry/inc/MantidGeometry/Instrument/ParameterMap.h b/Framework/Geometry/inc/MantidGeometry/Instrument/ParameterMap.h index 87a8b77d562b7afe92d6469d0063829b1a44230d..e9d449b5db8a71941f65b22c54dd731b60f189bc 100644 --- a/Framework/Geometry/inc/MantidGeometry/Instrument/ParameterMap.h +++ b/Framework/Geometry/inc/MantidGeometry/Instrument/ParameterMap.h @@ -18,6 +18,7 @@ namespace Kernel { template <class KEYTYPE, class VALUETYPE> class Cache; } namespace Beamline { +class ComponentInfo; class DetectorInfo; } namespace Geometry { @@ -346,9 +347,15 @@ public: bool hasDetectorInfo() const; const Beamline::DetectorInfo &detectorInfo() const; + bool hasComponentInfo() const; + const Beamline::ComponentInfo &componentInfo() const; size_t detectorIndex(const detid_t detID) const; + const std::vector<Geometry::ComponentID> &componentIds() const; void setDetectorInfo(boost::shared_ptr<const Beamline::DetectorInfo> detectorInfo); + void setComponentInfo( + boost::shared_ptr<const Beamline::ComponentInfo> componentInfo, + std::vector<Geometry::ComponentID> componentIds); void setInstrument(const Instrument *instrument); private: @@ -381,8 +388,13 @@ private: /// Pointer to the DetectorInfo object. NULL unless the instrument is /// associated with an ExperimentInfo object. boost::shared_ptr<const Beamline::DetectorInfo> m_detectorInfo{nullptr}; + /// Pointer to the ComponentInfo object. NULL unless the instrument is + /// associated with an ExperimentInfo object. + boost::shared_ptr<const Beamline::ComponentInfo> m_componentInfo{nullptr}; + /// Component ids. + std::vector<Geometry::ComponentID> m_componentIds; /// Pointer to the owning instrument for translating detector IDs into - /// detector indices when accessing the DetectorInfo object. + /// detector indices when accessing the DetectorInfo object const Instrument *m_instrument{nullptr}; }; diff --git a/Framework/Geometry/src/Instrument.cpp b/Framework/Geometry/src/Instrument.cpp index caa2d371f591101b426fa05e9aaaebc0b6ebf260..f7309b4999b58081f400cb6eafad475229d44d14 100644 --- a/Framework/Geometry/src/Instrument.cpp +++ b/Framework/Geometry/src/Instrument.cpp @@ -5,6 +5,7 @@ #include "MantidGeometry/Instrument/RectangularDetector.h" #include "MantidGeometry/Instrument/RectangularDetectorPixel.h" #include "MantidBeamline/DetectorInfo.h" +#include "MantidBeamline/ComponentInfo.h" #include "MantidKernel/EigenConversionHelpers.h" #include "MantidKernel/Exception.h" #include "MantidKernel/Logger.h" @@ -50,7 +51,8 @@ Instrument::Instrument(const boost::shared_ptr<const Instrument> instr, m_defaultViewAxis(instr->m_defaultViewAxis), m_instr(instr), m_map_nonconst(map), m_ValidFrom(instr->m_ValidFrom), m_ValidTo(instr->m_ValidTo), m_referenceFrame(new ReferenceFrame), - m_detectorInfo(instr->m_detectorInfo) { + m_detectorInfo(instr->m_detectorInfo), + m_componentInfo(instr->m_componentInfo) { m_map_nonconst->setInstrument(m_instr.get()); } @@ -69,7 +71,10 @@ Instrument::Instrument(const Instrument &instr) m_map_nonconst(), /* Should not be parameterized */ m_ValidFrom(instr.m_ValidFrom), m_ValidTo(instr.m_ValidTo), m_referenceFrame(instr.m_referenceFrame), - m_detectorInfo(instr.m_detectorInfo) { + m_detectorInfo(instr.m_detectorInfo), + m_componentInfo(instr.m_componentInfo) + +{ // Now we need to fill the detector, source and sample caches with pointers // into the new instrument std::vector<IComponent_const_sptr> children; @@ -1233,12 +1238,57 @@ const Beamline::DetectorInfo &Instrument::detectorInfo() const { return *m_detectorInfo; } +/** + * @brief Instrument::hasComponentInfo + * @return True only if a ComponentInfo has been set + */ +bool Instrument::hasComponentInfo() const { + return static_cast<bool>(m_componentInfo); +} + +/** + * @brief Instrument::componentInfo + * @return const ref to a ComponentInfo. Throws a std::runtime_error if + * not set. + */ +const Beamline::ComponentInfo &Instrument::componentInfo() const { + if (!hasComponentInfo()) { + throw std::runtime_error("Cannot return reference to NULL ComponentInfo"); + } + return *m_componentInfo; +} + +/** + * @brief Instrument::componentIds + * @return const ref to a vector of ComponentIds. Throws a std::runtime_error if + * Component Info not set. + */ +const std::vector<Geometry::ComponentID> &Instrument::componentIds() const { + if (!hasComponentInfo()) { + throw std::runtime_error( + "Cannot return component ids with a NULL ComponentInfo"); + } + return m_componentIds; +} + /// Only for use by ExperimentInfo. Sets the pointer to the DetectorInfo. void Instrument::setDetectorInfo( boost::shared_ptr<const Beamline::DetectorInfo> detectorInfo) { m_detectorInfo = std::move(detectorInfo); } +/** + * @brief Instrument::setComponentInfo + * @param componentInfo : ComponentInfo to store + * @param componentIds : ComponentIds to store + */ +void Instrument::setComponentInfo( + boost::shared_ptr<const Beamline::ComponentInfo> componentInfo, + std::vector<Geometry::ComponentID> componentIds) { + m_componentInfo = std::move(componentInfo); + m_componentIds = std::move(componentIds); +} + /// Returns the index for a detector ID. Used for accessing DetectorInfo. size_t Instrument::detectorIndex(const detid_t detID) const { const auto &baseInstr = m_map ? *m_instr : *this; diff --git a/Framework/Geometry/src/Instrument/ParameterMap.cpp b/Framework/Geometry/src/Instrument/ParameterMap.cpp index 7b157c7d3723d9ca4cb0ac7dc493f0546c6a9823..b8b820d02280a70de5b18771c5006273dc83b575 100644 --- a/Framework/Geometry/src/Instrument/ParameterMap.cpp +++ b/Framework/Geometry/src/Instrument/ParameterMap.cpp @@ -2,6 +2,8 @@ #include "MantidGeometry/Objects/BoundingBox.h" #include "MantidGeometry/IDetector.h" #include "MantidKernel/Cache.h" +#include "MantidBeamline/ComponentInfo.h" +#include "MantidBeamline/DetectorInfo.h" #include "MantidKernel/MultiThreaded.h" #include "MantidGeometry/Instrument.h" #include "MantidGeometry/Instrument/ParameterFactory.h" @@ -1162,6 +1164,41 @@ const Beamline::DetectorInfo &ParameterMap::detectorInfo() const { return *m_detectorInfo; } +/** + * @brief ParameterMap::hasComponentInfo + * @return True if a ComponentInfo is stored. + */ +bool ParameterMap::hasComponentInfo() const { + return static_cast<bool>(m_componentInfo); +} + +/** + * @brief ParameterMap::componentInfo + * @return A const ref to the ComponentInfo if stored. Throws a + * std::runtime_error + * exception otherwise. + */ +const Beamline::ComponentInfo &ParameterMap::componentInfo() const { + if (!hasComponentInfo()) { + throw std::runtime_error("Cannot return reference to NULL ComponentInfo"); + } + return *m_componentInfo; +} + +/** + * @brief ParameterMap::componentIds + * @return const ref to vector of component ids. Throws a std::runtime_error if + * the ComponentInfo has not been set. + */ +const std::vector<Geometry::ComponentID> &ParameterMap::componentIds() const { + // Component ids do not make sense without a ComponentInfo + if (!hasComponentInfo()) { + throw std::runtime_error( + "Cannot return component ids when ComponentInfo is NULL"); + } + return m_componentIds; +} + /// Only for use by Detector. Returns a detector index for a detector ID. size_t ParameterMap::detectorIndex(const detid_t detID) const { return m_instrument->detectorIndex(detID); @@ -1173,6 +1210,14 @@ void ParameterMap::setDetectorInfo( m_detectorInfo = std::move(detectorInfo); } +/// Only for use by ExperimentInfo. Sets the pointer to the ComponentInfo. +void ParameterMap::setComponentInfo( + boost::shared_ptr<const Beamline::ComponentInfo> componentInfo, + std::vector<Geometry::ComponentID> componentIds) { + m_componentInfo = std::move(componentInfo); + m_componentIds = std::move(componentIds); +} + /// Only for use by Instrument. Sets the pointer to the owning instrument. void ParameterMap::setInstrument(const Instrument *instrument) { m_instrument = instrument;