diff --git a/Framework/Beamline/inc/MantidBeamline/ComponentInfo.h b/Framework/Beamline/inc/MantidBeamline/ComponentInfo.h index 8405138254935c2a04fa3557d21661b8b09a7e74..b824292889070d21f007d2a98f585ed9260b9b21 100644 --- a/Framework/Beamline/inc/MantidBeamline/ComponentInfo.h +++ b/Framework/Beamline/inc/MantidBeamline/ComponentInfo.h @@ -9,6 +9,7 @@ #include <utility> #include <cstddef> #include <Eigen/Geometry> +#include <string> namespace Mantid { namespace Beamline { @@ -54,6 +55,7 @@ private: Mantid::Kernel::cow_ptr<std::vector<Eigen::Quaterniond>> m_rotations; Mantid::Kernel::cow_ptr<std::vector<Eigen::Vector3d>> m_scaleFactors; Mantid::Kernel::cow_ptr<std::vector<bool>> m_isStructuredBank; + boost::shared_ptr<const std::vector<std::string>> m_names; const size_t m_size = 0; const int64_t m_sourceIndex = -1; @@ -96,6 +98,7 @@ public: boost::shared_ptr<std::vector<Eigen::Quaterniond>> rotations, boost::shared_ptr<std::vector<Eigen::Vector3d>> scaleFactors, boost::shared_ptr<std::vector<bool>> isStructuredBank, + boost::shared_ptr<const std::vector<std::string>> names, int64_t sourceIndex, int64_t sampleIndex); /// Copy assignment not permitted because of the way DetectorInfo stored ComponentInfo &operator=(const ComponentInfo &other) = delete; @@ -138,6 +141,8 @@ public: size_t sample() const; size_t root() const; double l1() const; + std::string name(const size_t componentIndex) const; + size_t indexOf(const std::string &name) const; Eigen::Vector3d scaleFactor(const size_t componentIndex) const; void setScaleFactor(const size_t componentIndex, const Eigen::Vector3d &scaleFactor); diff --git a/Framework/Beamline/src/ComponentInfo.cpp b/Framework/Beamline/src/ComponentInfo.cpp index baea0884a8819cf536252233dea8347aa4eeb7ca..c6c71b9fa7868deca4f29a10b57626d419d66552 100644 --- a/Framework/Beamline/src/ComponentInfo.cpp +++ b/Framework/Beamline/src/ComponentInfo.cpp @@ -3,8 +3,11 @@ #include "MantidKernel/make_cow.h" #include <boost/make_shared.hpp> #include <numeric> +#include <algorithm> #include <utility> #include <vector> +#include <sstream> +#include <iterator> namespace Mantid { namespace Beamline { @@ -39,8 +42,9 @@ ComponentInfo::ComponentInfo( boost::shared_ptr<std::vector<Eigen::Vector3d>> positions, boost::shared_ptr<std::vector<Eigen::Quaterniond>> rotations, boost::shared_ptr<std::vector<Eigen::Vector3d>> scaleFactors, - boost::shared_ptr<std::vector<bool>> isStructuredBank, int64_t sourceIndex, - int64_t sampleIndex) + boost::shared_ptr<std::vector<bool>> isStructuredBank, + boost::shared_ptr<const std::vector<std::string>> names, + int64_t sourceIndex, int64_t sampleIndex) : m_assemblySortedDetectorIndices(std::move(assemblySortedDetectorIndices)), m_assemblySortedComponentIndices( std::move(assemblySortedComponentIndices)), @@ -50,6 +54,7 @@ ComponentInfo::ComponentInfo( m_positions(std::move(positions)), m_rotations(std::move(rotations)), m_scaleFactors(std::move(scaleFactors)), m_isStructuredBank(std::move(isStructuredBank)), + m_names(std::move(names)), m_size(m_assemblySortedDetectorIndices->size() + m_detectorRanges->size()), m_sourceIndex(sourceIndex), m_sampleIndex(sampleIndex), @@ -83,6 +88,10 @@ ComponentInfo::ComponentInfo( "of rectangular bank flags as number of " "non-detector components"); } + if (m_names->size() != m_size) { + throw std::invalid_argument("ComponentInfo should be provided same number " + "of names as number of components"); + } } std::unique_ptr<ComponentInfo> ComponentInfo::cloneWithoutDetectorInfo() const { @@ -494,6 +503,20 @@ Eigen::Vector3d ComponentInfo::scaleFactor(const size_t componentIndex) const { return (*m_scaleFactors)[componentIndex]; } +std::string ComponentInfo::name(const size_t componentIndex) const { + return (*m_names)[componentIndex]; +} + +size_t ComponentInfo::indexOf(const std::string &name) const { + auto it = std::find(m_names->begin(), m_names->end(), name); + if (it == m_names->end()) { + std::stringstream buffer; + buffer << name << " does not exist"; + throw std::invalid_argument(buffer.str()); + } + return std::distance(m_names->begin(), it); +} + void ComponentInfo::setScaleFactor(const size_t componentIndex, const Eigen::Vector3d &scaleFactor) { m_scaleFactors.access()[componentIndex] = scaleFactor; diff --git a/Framework/Beamline/test/ComponentInfoTest.h b/Framework/Beamline/test/ComponentInfoTest.h index 7ef75e03362f1d25e0ca1f0436fe56e8134e5e1a..44187c9aa69d9bd17619355f3df354d569da2a71 100644 --- a/Framework/Beamline/test/ComponentInfoTest.h +++ b/Framework/Beamline/test/ComponentInfoTest.h @@ -9,6 +9,7 @@ #include <boost/make_shared.hpp> #include <numeric> #include <tuple> +#include <string> using namespace Mantid::Beamline; @@ -16,6 +17,7 @@ namespace { using PosVec = std::vector<Eigen::Vector3d>; using RotVec = std::vector<Eigen::Quaterniond>; +using StrVec = std::vector<std::string>; /* * Makes a tree which in which all detectors are arranged in a single flat @@ -50,6 +52,12 @@ makeFlatTree(PosVec detPositions, RotVec detRotations) { // Component scale factors auto scaleFactors = boost::make_shared<PosVec>( PosVec(detPositions.size() + 1, Eigen::Vector3d{1, 1, 1})); + // Component names + auto names = boost::make_shared<StrVec>(); + for (size_t detIndex = 0; detIndex < detPositions.size(); ++detIndex) { + names->emplace_back("det" + std::to_string(detIndex)); + } + names->emplace_back("root"); auto detectorInfo = boost::make_shared<DetectorInfo>(detPositions, detRotations); // Rectangular bank flag @@ -62,8 +70,8 @@ makeFlatTree(PosVec detPositions, RotVec detRotations) { bankSortedComponentIndices, boost::make_shared<const std::vector<std::pair<size_t, size_t>>>( componentRanges), - parentIndices, positions, rotations, scaleFactors, isRectangularBank, -1, - -1); + parentIndices, positions, rotations, scaleFactors, isRectangularBank, + names, -1, -1); componentInfo->setDetectorInfo(detectorInfo.get()); @@ -125,7 +133,8 @@ makeTreeExampleAndReturnGeometricArguments() { // Component scale factors auto scaleFactors = boost::make_shared<PosVec>(PosVec(5, Eigen::Vector3d{1, 1, 1})); - + // Component names + auto names = boost::make_shared<StrVec>(5); // Rectangular bank flag auto isRectangularBank = boost::make_shared<std::vector<bool>>(2, false); @@ -137,7 +146,7 @@ makeTreeExampleAndReturnGeometricArguments() { boost::make_shared<const std::vector<std::pair<size_t, size_t>>>( componentRanges), parentIndices, compPositions, compRotations, scaleFactors, - isRectangularBank, -1, -1); + isRectangularBank, names, -1, -1); compInfo->setDetectorInfo(detectorInfo.get()); @@ -187,6 +196,8 @@ makeTreeExample() { // Component scale factors auto scaleFactors = boost::make_shared<PosVec>(PosVec(5, Eigen::Vector3d{1, 1, 1})); + // Component names + auto names = boost::make_shared<StrVec>(5); auto detectorInfo = boost::make_shared<DetectorInfo>(detPositions, detRotations); // Rectangular bank flag @@ -199,8 +210,8 @@ makeTreeExample() { bankSortedComponentIndices, boost::make_shared<const std::vector<std::pair<size_t, size_t>>>( componentRanges), - parentIndices, positions, rotations, scaleFactors, isRectangularBank, -1, - -1); + parentIndices, positions, rotations, scaleFactors, isRectangularBank, + names, -1, -1); componentInfo->setDetectorInfo(detectorInfo.get()); @@ -269,11 +280,12 @@ public: auto positions = boost::make_shared<PosVec>(); auto rotations = boost::make_shared<RotVec>(); auto scaleFactors = boost::make_shared<PosVec>(3); + auto names = boost::make_shared<StrVec>(3); auto isRectangularBank = boost::make_shared<std::vector<bool>>(); ComponentInfo componentInfo(bankSortedDetectorIndices, detectorRanges, bankSortedComponentIndices, componentRanges, parentIndices, positions, rotations, - scaleFactors, isRectangularBank, -1, -1); + scaleFactors, isRectangularBank, names, -1, -1); DetectorInfo detectorInfo; // Detector info size 0 TS_ASSERT_THROWS(componentInfo.setDetectorInfo(&detectorInfo), @@ -305,11 +317,13 @@ public: auto rotations = boost::make_shared<RotVec>(0); // 0 rotations provided auto scaleFactors = boost::make_shared<PosVec>(); + auto names = boost::make_shared<StrVec>(); auto isRectangularBank = boost::make_shared<std::vector<bool>>(2, false); TS_ASSERT_THROWS(ComponentInfo(detectorsInSubtree, detectorRanges, bankSortedComponentIndices, componentRanges, parentIndices, positions, rotations, - scaleFactors, isRectangularBank, -1, -1), + scaleFactors, isRectangularBank, names, -1, + -1), std::invalid_argument &); } @@ -338,17 +352,18 @@ public: auto rotations = boost::make_shared<RotVec>(1); // 1 rotation provided auto scaleFactors = boost::make_shared<PosVec>(); + auto names = boost::make_shared<StrVec>(); // Only one component. So single empty component range. auto componentRanges = boost::make_shared<const std::vector<std::pair<size_t, size_t>>>( std::vector<std::pair<size_t, size_t>>{{0, 0}}); auto isRectangularBank = boost::make_shared<std::vector<bool>>(2, false); - TS_ASSERT_THROWS(ComponentInfo(detectorsInSubtree, detectorRanges, - componentsInSubtree, componentRanges, - parentIndices, positions, rotations, - scaleFactors, isRectangularBank, -1, -1), - std::invalid_argument &); + TS_ASSERT_THROWS( + ComponentInfo(detectorsInSubtree, detectorRanges, componentsInSubtree, + componentRanges, parentIndices, positions, rotations, + scaleFactors, isRectangularBank, names, -1, -1), + std::invalid_argument &); } void test_read_positions_rotations() { @@ -733,6 +748,30 @@ public: TS_ASSERT_EQUALS(compInfo.scaleFactor(0), newFactor); } + void test_name() { + auto infos = makeFlat(PosVec(1), RotVec(1)); + ComponentInfo &compInfo = *std::get<0>(infos); + TS_ASSERT_EQUALS(compInfo.name(compInfo.root()), "root"); + TS_ASSERT_EQUALS(compInfo.name(0), "det0"); + } + + void test_indexOf_name_throws_when_name_invalid() { + auto infos = makeFlat(PosVec(1), RotVec(1)); + ComponentInfo &compInfo = *std::get<0>(infos); + TSM_ASSERT_THROWS("Should throw, this name does not exist", + compInfo.indexOf("phantom"), std::invalid_argument &) + // Sanity check. + TSM_ASSERT_THROWS_NOTHING("Should NOT throw if provided with a valid name", + compInfo.indexOf(compInfo.name(0))); + } + + void test_indexOf() { + auto infos = makeFlat(PosVec(1), RotVec(1)); + ComponentInfo &compInfo = *std::get<0>(infos); + TS_ASSERT_EQUALS(compInfo.indexOf("det0"), 0); + TS_ASSERT_EQUALS(compInfo.indexOf("root"), compInfo.root()); + } + void test_scan_count_no_scanning() { ComponentInfo info; TS_ASSERT_EQUALS(info.scanCount(0), 1); diff --git a/Framework/Geometry/inc/MantidGeometry/Instrument/ComponentInfo.h b/Framework/Geometry/inc/MantidGeometry/Instrument/ComponentInfo.h index b2d9c5b3b7ceb199552497083ebde26e0b2f1a2b..c6d709f784f962c078a57baf79b35971dad468b3 100644 --- a/Framework/Geometry/inc/MantidGeometry/Instrument/ComponentInfo.h +++ b/Framework/Geometry/inc/MantidGeometry/Instrument/ComponentInfo.h @@ -87,6 +87,7 @@ public: std::vector<size_t> componentsInSubtree(size_t componentIndex) const; size_t size() const; size_t indexOf(Geometry::IComponent *id) const; + size_t indexOf(const std::string &name) const; bool isDetector(const size_t componentIndex) const; Kernel::V3D position(const size_t componentIndex) const; Kernel::V3D position(const std::pair<size_t, size_t> index) const; @@ -111,6 +112,7 @@ public: size_t sample() const; double l1() const; Kernel::V3D scaleFactor(const size_t componentIndex) const; + std::string name(const size_t componentIndex) const; void setScaleFactor(const size_t componentIndex, const Kernel::V3D &scaleFactor); size_t root(); diff --git a/Framework/Geometry/inc/MantidGeometry/Instrument/InstrumentVisitor.h b/Framework/Geometry/inc/MantidGeometry/Instrument/InstrumentVisitor.h index d44302c5ba18422fc5a9a3326876fc280ad3bdb7..e8e13363c2e5304624516d571a9da0bc909c0cc0 100644 --- a/Framework/Geometry/inc/MantidGeometry/Instrument/InstrumentVisitor.h +++ b/Framework/Geometry/inc/MantidGeometry/Instrument/InstrumentVisitor.h @@ -136,6 +136,9 @@ private: /// Structured bank flag boost::shared_ptr<std::vector<bool>> m_isStructuredBank; + /// Component names + boost::shared_ptr<std::vector<std::string>> m_names; + void markAsSourceOrSample(Mantid::Geometry::IComponent *componentId, const size_t componentIndex); diff --git a/Framework/Geometry/src/Instrument/ComponentInfo.cpp b/Framework/Geometry/src/Instrument/ComponentInfo.cpp index 4a7d5b38debcd36308b7f608d00a1af4435c456e..08a9ab755b73cd0d5b8ab5df9c612969e690bf15 100644 --- a/Framework/Geometry/src/Instrument/ComponentInfo.cpp +++ b/Framework/Geometry/src/Instrument/ComponentInfo.cpp @@ -111,6 +111,10 @@ size_t ComponentInfo::indexOf(Geometry::IComponent *id) const { return m_compIDToIndex->at(id); } +size_t ComponentInfo::indexOf(const std::string &name) const { + return m_componentInfo->indexOf(name); +} + bool ComponentInfo::isDetector(const size_t componentIndex) const { return m_componentInfo->isDetector(componentIndex); } @@ -207,6 +211,10 @@ Kernel::V3D ComponentInfo::scaleFactor(const size_t componentIndex) const { return Kernel::toV3D(m_componentInfo->scaleFactor(componentIndex)); } +std::string ComponentInfo::name(const size_t componentIndex) const { + return m_componentInfo->name(componentIndex); +} + void ComponentInfo::setScaleFactor(const size_t componentIndex, const Kernel::V3D &scaleFactor) { m_componentInfo->setScaleFactor(componentIndex, diff --git a/Framework/Geometry/src/Instrument/InstrumentVisitor.cpp b/Framework/Geometry/src/Instrument/InstrumentVisitor.cpp index 13adc7e538800b24e92c5da9b3489683ff17ad1a..a95dddac502ecdc85ee2b71ab02b321841e039d9 100644 --- a/Framework/Geometry/src/Instrument/InstrumentVisitor.cpp +++ b/Framework/Geometry/src/Instrument/InstrumentVisitor.cpp @@ -85,8 +85,9 @@ InstrumentVisitor::InstrumentVisitor( m_orderedDetectorIds->size(), m_nullShape)), m_scaleFactors(boost::make_shared<std::vector<Eigen::Vector3d>>( m_orderedDetectorIds->size(), Eigen::Vector3d{1, 1, 1})), - m_isStructuredBank(boost::make_shared<std::vector<bool>>()) { - + m_isStructuredBank(boost::make_shared<std::vector<bool>>()), + m_names(boost::make_shared<std::vector<std::string>>( + m_orderedDetectorIds->size())) { if (m_instrument->isParametrized()) { m_pmap = m_instrument->getParameterMap().get(); } @@ -109,7 +110,6 @@ InstrumentVisitor::InstrumentVisitor( const auto nDetectors = m_orderedDetectorIds->size(); m_assemblySortedDetectorIndices->reserve(nDetectors); // Exact m_componentIdToIndexMap->reserve(nDetectors); // Approximation - m_shapes->reserve(nDetectors); // Approximation } void InstrumentVisitor::walkInstrument() { @@ -160,6 +160,7 @@ InstrumentVisitor::registerComponentAssembly(const ICompAssembly &assembly) { m_shapes->emplace_back(m_nullShape); m_isStructuredBank->push_back(false); m_scaleFactors->emplace_back(Kernel::toVector3d(assembly.getScaleFactor())); + m_names->emplace_back(assembly.getName()); clearLegacyParameters(m_pmap, assembly); return componentIndex; } @@ -194,6 +195,7 @@ InstrumentVisitor::registerGenericComponent(const IComponent &component) { m_shapes->emplace_back(m_nullShape); m_isStructuredBank->push_back(false); m_scaleFactors->emplace_back(Kernel::toVector3d(component.getScaleFactor())); + m_names->emplace_back(component.getName()); clearLegacyParameters(m_pmap, component); return componentIndex; } @@ -261,6 +263,7 @@ size_t InstrumentVisitor::registerDetector(const IDetector &detector) { if (m_instrument->isMonitorViaIndex(detectorIndex)) { m_monitorIndices->push_back(detectorIndex); } + (*m_names)[detectorIndex] = detector.getName(); clearLegacyParameters(m_pmap, detector); /* Note that positions and rotations for detectors are currently @@ -314,7 +317,7 @@ InstrumentVisitor::componentInfo() const { m_assemblySortedDetectorIndices, m_detectorRanges, m_assemblySortedComponentIndices, m_componentRanges, m_parentComponentIndices, m_positions, m_rotations, m_scaleFactors, - m_isStructuredBank, m_sourceIndex, m_sampleIndex); + m_isStructuredBank, m_names, m_sourceIndex, m_sampleIndex); } std::unique_ptr<Beamline::DetectorInfo> diff --git a/Framework/Geometry/test/ComponentInfoTest.h b/Framework/Geometry/test/ComponentInfoTest.h index ae8a2baea24a14f673dae8273a5611a4594050a4..543b1c56b0394d3650886985ab7dd0dce32dc528 100644 --- a/Framework/Geometry/test/ComponentInfoTest.h +++ b/Framework/Geometry/test/ComponentInfoTest.h @@ -104,11 +104,12 @@ std::unique_ptr<Beamline::ComponentInfo> makeSingleBeamlineComponentInfo( boost::make_shared<std::vector<Eigen::Quaterniond>>(1, rotation); auto scaleFactors = boost::make_shared<std::vector<Eigen::Vector3d>>(1, scaleFactor); + auto names = boost::make_shared<std::vector<std::string>>(1); auto isStructuredBank = boost::make_shared<std::vector<bool>>(1, false); return Kernel::make_unique<Beamline::ComponentInfo>( detectorIndices, detectorRanges, componentIndices, componentRanges, - parentIndices, positions, rotations, scaleFactors, isStructuredBank, -1, - -1); + parentIndices, positions, rotations, scaleFactors, isStructuredBank, + names, -1, -1); } } @@ -146,10 +147,12 @@ public: auto positions = boost::make_shared<std::vector<Eigen::Vector3d>>(2); auto rotations = boost::make_shared<std::vector<Eigen::Quaterniond>>(2); auto scaleFactors = boost::make_shared<std::vector<Eigen::Vector3d>>(2); + auto names = boost::make_shared<std::vector<std::string>>(2); auto isRectBank = boost::make_shared<std::vector<bool>>(2); auto internalInfo = Kernel::make_unique<Beamline::ComponentInfo>( detectorIndices, detectorRanges, componentIndices, componentRanges, - parentIndices, positions, rotations, scaleFactors, isRectBank, -1, -1); + parentIndices, positions, rotations, scaleFactors, isRectBank, names, + -1, -1); Mantid::Geometry::ObjComponent comp1("component1"); Mantid::Geometry::ObjComponent comp2("component2"); diff --git a/Framework/Geometry/test/InstrumentVisitorTest.h b/Framework/Geometry/test/InstrumentVisitorTest.h index 352c57dbd6658b452a226317ce047ef7adbb32c6..cdc74a72501fd7a01a26a058d457ce4c6124ad6f 100644 --- a/Framework/Geometry/test/InstrumentVisitorTest.h +++ b/Framework/Geometry/test/InstrumentVisitorTest.h @@ -384,6 +384,30 @@ public: &componentInfo->shape(1 /*another detector*/)); } + void test_names() { + + const int nPixelsWide = 10; // Gives 10*10 detectors in total + auto instrument = ComponentCreationHelper::createTestInstrumentRectangular( + 1 /*n banks*/, nPixelsWide, 1 /*sample-bank distance*/); + + // Visit everything + auto wrappers = + InstrumentVisitor::makeWrappers(*instrument, nullptr /*parameter map*/); + auto componentInfo = std::move(std::get<0>(wrappers)); + + // Check root name + TS_ASSERT_EQUALS("basic_rect", componentInfo->name(componentInfo->root())); + // Backward check that we get the right index + TS_ASSERT_EQUALS(componentInfo->indexOf("basic_rect"), + componentInfo->root()); + + // Check all names are the same in old instrument and component info + for (size_t index = 0; index < componentInfo->size(); ++index) { + TS_ASSERT_EQUALS(componentInfo->componentID(index)->getName(), + componentInfo->name(index)); + } + } + void test_purge_scale_factors() { // Create a very basic instrument to visit