diff --git a/Framework/NexusGeometry/inc/MantidNexusGeometry/JSONGeometryParser.h b/Framework/NexusGeometry/inc/MantidNexusGeometry/JSONGeometryParser.h index d4d05aa59ef6bbe20f2c91ee15cf23917d9b3b42..0a86afa45e4149d979f1717997cc52e93608db47 100644 --- a/Framework/NexusGeometry/inc/MantidNexusGeometry/JSONGeometryParser.h +++ b/Framework/NexusGeometry/inc/MantidNexusGeometry/JSONGeometryParser.h @@ -10,10 +10,13 @@ #include "MantidGeometry/IDTypes.h" #include "MantidNexusGeometry/DllConfig.h" #include <Eigen/Geometry> -#include <json/json.h> #include <memory> #include <vector> +namespace Json { +class Value; +} + namespace Mantid { namespace NexusGeometry { @@ -78,7 +81,7 @@ public: const Eigen::Quaterniond &sourceOrientation() const noexcept { return m_sourceOrientation; } - size_t numberOfBanks() const noexcept { return m_jsonDetectorBanks.size(); } + size_t numberOfBanks() const noexcept { return m_detIDs.size(); } const std::vector<detid_t> &detectorIDs(const size_t index) const noexcept { return m_detIDs[index]; } @@ -149,10 +152,10 @@ private: private: std::string m_name; - Json::Value m_root; - Json::Value m_instrument; - Json::Value m_sample; - Json::Value m_source; + std::unique_ptr<Json::Value> m_root; + std::unique_ptr<Json::Value> m_instrument; + std::unique_ptr<Json::Value> m_sample; + std::unique_ptr<Json::Value> m_source; std::string m_sampleName; std::string m_sourceName; Eigen::Vector3d m_samplePosition; @@ -160,13 +163,13 @@ private: Eigen::Vector3d m_sourcePosition; Eigen::Quaterniond m_sourceOrientation; // monitor information - std::vector<Json::Value> m_jsonMonitors; + std::vector<std::unique_ptr<Json::Value>> m_jsonMonitors; std::vector<Monitor> m_monitors; // chopper information - std::vector<Json::Value> m_jsonChoppers; + std::vector<std::unique_ptr<Json::Value>> m_jsonChoppers; std::vector<Chopper> m_choppers; // detector information - std::vector<Json::Value> m_jsonDetectorBanks; + std::vector<std::unique_ptr<Json::Value>> m_jsonDetectorBanks; std::vector<std::string> m_detectorBankNames; std::vector<std::vector<detid_t>> m_detIDs; std::vector<std::vector<double>> m_x; diff --git a/Framework/NexusGeometry/inc/MantidNexusGeometry/JSONInstrumentBuilder.h b/Framework/NexusGeometry/inc/MantidNexusGeometry/JSONInstrumentBuilder.h index fe7698aa61990c8baeddac1bded2db30eff31e87..43b3adbc08fe006eaeeaff3c2e59ffd512c461bb 100644 --- a/Framework/NexusGeometry/inc/MantidNexusGeometry/JSONInstrumentBuilder.h +++ b/Framework/NexusGeometry/inc/MantidNexusGeometry/JSONInstrumentBuilder.h @@ -9,12 +9,14 @@ #include "MantidGeometry/Instrument_fwd.h" #include "MantidNexusGeometry/DllConfig.h" -#include "MantidNexusGeometry/JSONGeometryParser.h" +#include <memory> #include <string> #include <vector> namespace Mantid { namespace NexusGeometry { +class JSONGeometryParser; +struct Chopper; /** JSONInstrumentBuilder : Builds in-memory instrument from json string * representing Nexus instrument geometry. */ @@ -29,7 +31,7 @@ public: Geometry::Instrument_const_uptr buildGeometry() const; private: - JSONGeometryParser m_parser; + std::unique_ptr<JSONGeometryParser> m_parser; }; } // namespace NexusGeometry diff --git a/Framework/NexusGeometry/src/JSONGeometryParser.cpp b/Framework/NexusGeometry/src/JSONGeometryParser.cpp index 655279f41d96f5324ed9d8a68a311ad77a33beda..a45245e8ac6db8470a8ce25a2789bf43c7c46269 100644 --- a/Framework/NexusGeometry/src/JSONGeometryParser.cpp +++ b/Framework/NexusGeometry/src/JSONGeometryParser.cpp @@ -10,6 +10,9 @@ #include "MantidNexusGeometry/NexusGeometryDefinitions.h" #include <boost/algorithm/string/classification.hpp> #include <boost/algorithm/string/split.hpp> +#include <json/json.h> + +using Json::Value; namespace { using namespace Mantid::NexusGeometry; @@ -296,6 +299,15 @@ std::string extractInstrumentName(const Json::Value &instrument) { return name; } +std::vector<std::unique_ptr<Json::Value>> +moveToUniquePtrVec(std::vector<Json::Value> &jsonVector) { + std::vector<std::unique_ptr<Json::Value>> ret; + for (auto &val : jsonVector) + ret.push_back(std::make_unique<Json::Value>(std::move(val))); + + return ret; +} + } // namespace namespace Mantid { @@ -325,8 +337,8 @@ void JSONGeometryParser::validateAndRetrieveGeometry( if (sample.isNull()) throw std::invalid_argument("No sample found in json."); - m_source = get(entryChildren, NX_SOURCE); - if (m_source.isNull()) + auto source = get(entryChildren, NX_SOURCE); + if (source.isNull()) g_log.notice() << "No source information found in json instrument." << std::endl; @@ -336,25 +348,30 @@ void JSONGeometryParser::validateAndRetrieveGeometry( m_name = extractInstrumentName(instrument); - m_jsonDetectorBanks = getAllDetectors(instrument); - if (m_jsonDetectorBanks.empty()) + auto jsonDetectorBanks = getAllDetectors(instrument); + if (jsonDetectorBanks.empty()) throw std::invalid_argument("No detectors found in json."); + ; + m_jsonDetectorBanks = moveToUniquePtrVec(jsonDetectorBanks); - m_jsonMonitors = getAllMonitors(instrument); + auto jsonMonitors = getAllMonitors(instrument); + auto jsonChoppers = getAllChoppers(instrument); - m_jsonChoppers = getAllChoppers(instrument); + m_jsonMonitors = moveToUniquePtrVec(jsonMonitors); + m_jsonChoppers = moveToUniquePtrVec(jsonChoppers); - m_root = root; - m_sample = sample; - m_instrument = instrument; + m_root = std::make_unique<Json::Value>(std::move(root)); + m_source = std::make_unique<Json::Value>(std::move(source)); + m_sample = std::make_unique<Json::Value>(std::move(sample)); + m_instrument = std::make_unique<Json::Value>(std::move(instrument)); } void JSONGeometryParser::extractSampleContent() { - const auto &children = m_sample[CHILDREN]; + const auto &children = (*m_sample)[CHILDREN]; m_samplePosition = Eigen::Vector3d(0, 0, 0); m_sampleOrientation = Eigen::Quaterniond(Eigen::AngleAxisd(0, Eigen::Vector3d(1, 0, 0))); - m_sampleName = m_sample[NAME].asString(); + m_sampleName = (*m_sample)[NAME].asString(); for (const auto &child : children) { if (child[NAME] == TRANSFORMATIONS) extractTransformations(child, m_samplePosition, m_sampleOrientation); @@ -366,9 +383,9 @@ void JSONGeometryParser::extractSourceContent() { m_sourcePosition = Eigen::Vector3d(0, 0, 0); m_sourceOrientation = Eigen::Quaterniond(Eigen::AngleAxisd(0, Eigen::Vector3d(1, 0, 0))); - if (!m_source.isNull()) { - m_sourceName = m_source[NAME].asCString(); - const auto &children = m_source[CHILDREN]; + if (!m_source->isNull()) { + m_sourceName = (*m_source)[NAME].asCString(); + const auto &children = (*m_source)[CHILDREN]; for (const auto &child : children) { if (child[NAME] == TRANSFORMATIONS) extractTransformations(child, m_sourcePosition, m_sourceOrientation); @@ -382,7 +399,7 @@ void JSONGeometryParser::extractTransformationDataset( const Json::Value &transformation, double &value, Eigen::Vector3d &axis) { std::vector<double> values; extractDatasetValues(transformation, values); - axis = getTransformationAxis(m_root, transformation[ATTRIBUTES]); + axis = getTransformationAxis(*m_root, transformation[ATTRIBUTES]); value = values[0]; } @@ -429,7 +446,7 @@ void JSONGeometryParser::extractDetectorContent() { std::vector<uint32_t> windingOrder; bool isOffGeometry = false; - auto children = detector[CHILDREN]; + auto children = (*detector)[CHILDREN]; for (const auto &child : children) { if (child[NAME] == DETECTOR_IDS) @@ -444,7 +461,7 @@ void JSONGeometryParser::extractDetectorContent() { extractShapeInformation(child, cylinders, faces, vertices, windingOrder, isOffGeometry); else if (child[NAME] == DEPENDS_ON) - verifyDependency(m_root, child); + verifyDependency(*m_root, child); else if (validateNXAttribute(child[ATTRIBUTES], NX_TRANSFORMATIONS)) { m_translations.emplace_back(Eigen::Vector3d()); m_orientations.emplace_back(Eigen::Quaterniond()); @@ -452,7 +469,7 @@ void JSONGeometryParser::extractDetectorContent() { m_orientations.back()); } } - auto name = detector[NAME].asString(); + auto name = (*detector)[NAME].asString(); if (detIDs.empty()) throw std::invalid_argument("No detector ids found in " + name + "."); if (x.empty()) @@ -482,14 +499,14 @@ void JSONGeometryParser::extractMonitorContent() { return; for (const auto &monitor : m_jsonMonitors) { - const auto &children = monitor[CHILDREN]; + const auto &children = (*monitor)[CHILDREN]; if (children.empty()) throw std::invalid_argument( "Full monitor definition missing in json provided."); Monitor mon; - mon.componentName = monitor[NAME].asString(); + mon.componentName = (*monitor)[NAME].asString(); for (const auto &child : children) { const auto &val = child[VALUES]; if (child[NAME] == NAME) @@ -506,7 +523,7 @@ void JSONGeometryParser::extractMonitorContent() { extractShapeInformation(child, mon.cylinders, mon.faces, mon.vertices, mon.windingOrder, mon.isOffGeometry); else if (child[NAME] == DEPENDS_ON) - verifyDependency(m_root, child); + verifyDependency(*m_root, child); } if (validateShapeInformation(mon.isOffGeometry, mon.vertices, mon.cylinders, @@ -526,13 +543,13 @@ void JSONGeometryParser::extractChopperContent() { return; for (const auto &chopper : m_jsonChoppers) { - const auto &children = chopper[CHILDREN]; + const auto &children = (*chopper)[CHILDREN]; if (children.empty()) throw std::invalid_argument( "Full chopper definition missing in json provided."); Chopper chop; - chop.componentName = chopper[NAME].asString(); + chop.componentName = (*chopper)[NAME].asString(); for (const auto &child : children) { const auto &val = child[VALUES]; if (child[NAME] == "name") diff --git a/Framework/NexusGeometry/src/JSONInstrumentBuilder.cpp b/Framework/NexusGeometry/src/JSONInstrumentBuilder.cpp index 6e7803a8a9c57e5bfe6935e44ddc53dfd21c907c..617045bb806594559c8439cc7b6c4a07266ca2b0 100644 --- a/Framework/NexusGeometry/src/JSONInstrumentBuilder.cpp +++ b/Framework/NexusGeometry/src/JSONInstrumentBuilder.cpp @@ -12,6 +12,7 @@ #include "MantidNexusGeometry/JSONGeometryParser.h" #include "MantidNexusGeometry/NexusShapeFactory.h" #include "MantidNexusGeometry/TubeHelpers.h" +#include <json/json.h> namespace { using namespace Mantid::Geometry; @@ -95,29 +96,29 @@ void addMonitors(const JSONGeometryParser &parser, InstrumentBuilder &builder) { namespace Mantid { namespace NexusGeometry { JSONInstrumentBuilder::JSONInstrumentBuilder(const std::string &jsonGeometry) - : m_parser(jsonGeometry) {} + : m_parser(std::make_unique<JSONGeometryParser>(jsonGeometry)) {} const std::vector<Chopper> &JSONInstrumentBuilder::choppers() const { - return m_parser.choppers(); + return m_parser->choppers(); } Geometry::Instrument_const_uptr JSONInstrumentBuilder::buildGeometry() const { - InstrumentBuilder builder(m_parser.name()); - for (size_t bank = 0; bank < m_parser.numberOfBanks(); ++bank) { - auto bankName = m_parser.detectorName(bank); - builder.addBank(bankName, m_parser.translation(bank), - m_parser.orientation(bank)); - auto shape = createShape(m_parser, bank); - auto pixelOffsets = getOffsets(m_parser, bank); + InstrumentBuilder builder(m_parser->name()); + for (size_t bank = 0; bank < m_parser->numberOfBanks(); ++bank) { + auto bankName = m_parser->detectorName(bank); + builder.addBank(bankName, m_parser->translation(bank), + m_parser->orientation(bank)); + auto shape = createShape(*m_parser, bank); + auto pixelOffsets = getOffsets(*m_parser, bank); Eigen::Matrix<double, 3, Eigen::Dynamic> detectorPixels = Eigen::Affine3d::Identity() * pixelOffsets; - const auto &ids = m_parser.detectorIDs(bank); - if (m_parser.isOffGeometry(bank)) { - const auto &x = m_parser.xPixelOffsets(bank); - const auto &y = m_parser.yPixelOffsets(bank); - const auto &z = m_parser.zPixelOffsets(bank); + const auto &ids = m_parser->detectorIDs(bank); + if (m_parser->isOffGeometry(bank)) { + const auto &x = m_parser->xPixelOffsets(bank); + const auto &y = m_parser->yPixelOffsets(bank); + const auto &z = m_parser->zPixelOffsets(bank); - for (size_t i = 0; i < m_parser.detectorIDs(bank).size(); ++i) { + for (size_t i = 0; i < m_parser->detectorIDs(bank).size(); ++i) { builder.addDetectorToLastBank(bankName + "_" + std::to_string(i), ids[i], Eigen::Vector3d(x[i], y[i], z[i]), shape); @@ -129,12 +130,12 @@ Geometry::Instrument_const_uptr JSONInstrumentBuilder::buildGeometry() const { } builder.addSample( - m_parser.sampleName(), - applyRotation(m_parser.samplePosition(), m_parser.sampleOrientation())); + m_parser->sampleName(), + applyRotation(m_parser->samplePosition(), m_parser->sampleOrientation())); builder.addSource( - m_parser.sourceName(), - applyRotation(m_parser.sourcePosition(), m_parser.sourceOrientation())); - addMonitors(m_parser, builder); + m_parser->sourceName(), + applyRotation(m_parser->sourcePosition(), m_parser->sourceOrientation())); + addMonitors(*m_parser, builder); return builder.createInstrument(); } diff --git a/Framework/NexusGeometry/test/JSONGeometryParserTest.h b/Framework/NexusGeometry/test/JSONGeometryParserTest.h index be878a89a9ba445fe17ced99f10cac943e7e9418..9898537337870e5328af8d92ad833c3b48910926 100644 --- a/Framework/NexusGeometry/test/JSONGeometryParserTest.h +++ b/Framework/NexusGeometry/test/JSONGeometryParserTest.h @@ -14,11 +14,12 @@ #include <Poco/Glob.h> #include <cxxtest/TestSuite.h> #include <exception> +#include <json/json.h> #include <string> using namespace Mantid::Kernel; -using Mantid::NexusGeometry::JSONGeometryParser; using Mantid::detid_t; +using Mantid::NexusGeometry::JSONGeometryParser; class JSONGeometryParserTest : public CxxTest::TestSuite { public: diff --git a/Framework/NexusGeometry/test/JSONInstrumentBuilderTest.h b/Framework/NexusGeometry/test/JSONInstrumentBuilderTest.h index 99a2a443190715ea6be884431d18d21904180c1f..0019c8f74d3d9e710f9fc74f5211399510571694 100644 --- a/Framework/NexusGeometry/test/JSONInstrumentBuilderTest.h +++ b/Framework/NexusGeometry/test/JSONInstrumentBuilderTest.h @@ -8,9 +8,11 @@ #define MANTID_NEXUSGEOMETRY_JSONINSTRUMENTBUILDERTEST_H_ #include "MantidGeometry/Instrument.h" +#include "MantidNexusGeometry/JSONGeometryParser.h" #include "MantidNexusGeometry/JSONInstrumentBuilder.h" #include "MantidTestHelpers/JSONGeometryParserTestHelper.h" #include <cxxtest/TestSuite.h> +#include <json/json.h> using namespace Mantid; using Mantid::NexusGeometry::JSONInstrumentBuilder;