diff --git a/Framework/DataHandling/src/LoadNexusProcessed.cpp b/Framework/DataHandling/src/LoadNexusProcessed.cpp index 66a19bf1afd6..ae315d025168 100644 --- a/Framework/DataHandling/src/LoadNexusProcessed.cpp +++ b/Framework/DataHandling/src/LoadNexusProcessed.cpp @@ -21,6 +21,7 @@ #include "MantidDataObjects/LeanElasticPeaksWorkspace.h" #include "MantidDataObjects/Peak.h" #include "MantidDataObjects/PeakNoShapeFactory.h" +#include "MantidDataObjects/PeakShapeDetectorBinFactory.h" #include "MantidDataObjects/PeakShapeEllipsoidFactory.h" #include "MantidDataObjects/PeakShapeSphericalFactory.h" #include "MantidDataObjects/PeaksWorkspace.h" @@ -1164,10 +1165,12 @@ API::Workspace_sptr LoadNexusProcessed::loadLeanElasticPeaksEntry(const NXEntry PeakShapeFactory_sptr peakFactoryEllipsoid = std::make_shared(); PeakShapeFactory_sptr peakFactorySphere = std::make_shared(); + PeakShapeFactory_sptr peakFactoryDetectorBin = std::make_shared(); PeakShapeFactory_sptr peakFactoryNone = std::make_shared(); peakFactoryEllipsoid->setSuccessor(peakFactorySphere); - peakFactorySphere->setSuccessor(peakFactoryNone); + peakFactorySphere->setSuccessor(peakFactoryDetectorBin); + peakFactoryDetectorBin->setSuccessor(peakFactoryNone); NXInfo info = nx_tw.getDataSetInfo(str); NXChar data = nx_tw.openNXChar(str); @@ -1456,10 +1459,12 @@ API::Workspace_sptr LoadNexusProcessed::loadPeaksEntry(const NXEntry &entry) { PeakShapeFactory_sptr peakFactoryEllipsoid = std::make_shared(); PeakShapeFactory_sptr peakFactorySphere = std::make_shared(); + PeakShapeFactory_sptr peakFactoryDetectorBin = std::make_shared(); PeakShapeFactory_sptr peakFactoryNone = std::make_shared(); peakFactoryEllipsoid->setSuccessor(peakFactorySphere); - peakFactorySphere->setSuccessor(peakFactoryNone); + peakFactorySphere->setSuccessor(peakFactoryDetectorBin); + peakFactoryDetectorBin->setSuccessor(peakFactoryNone); NXInfo info = nx_tw.getDataSetInfo(str); NXChar data = nx_tw.openNXChar(str); diff --git a/Framework/DataObjects/CMakeLists.txt b/Framework/DataObjects/CMakeLists.txt index 0b3e0556fcc7..45ca6cce2eaa 100644 --- a/Framework/DataObjects/CMakeLists.txt +++ b/Framework/DataObjects/CMakeLists.txt @@ -54,6 +54,8 @@ set(SRC_FILES src/WorkspaceCreation.cpp src/WorkspaceProperty.cpp src/WorkspaceSingleValue.cpp + src/PeakShapeDetectorBin.cpp + src/PeakShapeDetectorBinFactory.cpp ) set(INC_FILES @@ -138,6 +140,8 @@ set(INC_FILES inc/MantidDataObjects/Workspace2D_fwd.h inc/MantidDataObjects/WorkspaceCreation.h inc/MantidDataObjects/WorkspaceSingleValue.h + inc/MantidDataObjects/PeakShapeDetectorBin.h + inc/MantidDataObjects/PeakShapeDetectorBinFactory.h ) set(TEST_FILES @@ -205,6 +209,8 @@ set(TEST_FILES WorkspaceSingleValueTest.h WorkspaceValidatorsTest.h MortonIndex/BitInterleavingTest.h + PeakShapeDetectorBinTest.h + PeakShapeDetectorBinFactoryTest.h ) if(COVERAGE) diff --git a/Framework/DataObjects/inc/MantidDataObjects/PeakShapeDetectorBin.h b/Framework/DataObjects/inc/MantidDataObjects/PeakShapeDetectorBin.h new file mode 100644 index 000000000000..23440b8ce88d --- /dev/null +++ b/Framework/DataObjects/inc/MantidDataObjects/PeakShapeDetectorBin.h @@ -0,0 +1,47 @@ +// Mantid Repository : https://github.com/mantidproject/mantid +// +// Copyright © 2024 ISIS Rutherford Appleton Laboratory UKRI, +// NScD Oak Ridge National Laboratory, European Spallation Source, +// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS +// SPDX - License - Identifier: GPL - 3.0 + +#pragma once + +#include "MantidDataObjects/PeakShapeBase.h" +#include + +namespace Mantid { +namespace DataObjects { + +/** PeakShapeDetectorBin : PeakShape representing detector ids and integration limits of a peak + */ +class MANTID_DATAOBJECTS_DLL PeakShapeDetectorBin : public PeakShapeBase { +public: + PeakShapeDetectorBin(const std::vector> &detectorBinList, + Kernel::SpecialCoordinateSystem frame, std::string algorithmName = std::string(), + int algorithmVersion = -1); + /// Equals operator + bool operator==(const PeakShapeDetectorBin &other) const; + + /// PeakShape interface + std::string toJSON() const override; + /// Clone PeakShapeDetectorBin + Mantid::Geometry::PeakShape *clone() const override; + /// Get the peak shape + std::string shapeName() const override; + + /// PeakBase interface + std::optional radius(RadiusType) const override { return std::nullopt; } + + static const std::string detectorBinShapeName(); + + const std::vector> &getDetectorBinList() const { return m_detectorBinList; } + +private: + std::vector> m_detectorBinList; +}; + +using PeakShapeDetectorTOF_sptr = std::shared_ptr; +using PeakShapeDetectorTOF_const_sptr = std::shared_ptr; + +} // namespace DataObjects +} // namespace Mantid diff --git a/Framework/DataObjects/inc/MantidDataObjects/PeakShapeDetectorBinFactory.h b/Framework/DataObjects/inc/MantidDataObjects/PeakShapeDetectorBinFactory.h new file mode 100644 index 000000000000..cef19d1d9587 --- /dev/null +++ b/Framework/DataObjects/inc/MantidDataObjects/PeakShapeDetectorBinFactory.h @@ -0,0 +1,35 @@ +// Mantid Repository : https://github.com/mantidproject/mantid +// +// Copyright © 2024 ISIS Rutherford Appleton Laboratory UKRI, +// NScD Oak Ridge National Laboratory, European Spallation Source, +// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS +// SPDX - License - Identifier: GPL - 3.0 + +#pragma once + +#include "MantidDataObjects/PeakShapeFactory.h" + +namespace Mantid { +namespace Geometry { +// Forward declare +class PeakShape; +} // namespace Geometry +namespace DataObjects { + +/** PeakShapeDetectorBinFactory : Factory for DetectorBin peak shapes for + de-serializing from JSON. + * +*/ +class MANTID_DATAOBJECTS_DLL PeakShapeDetectorBinFactory : public PeakShapeFactory { +public: + /// Make product + Mantid::Geometry::PeakShape *create(const std::string &source) const override; + /// Set a successor should this factory be unsuitable + void setSuccessor(PeakShapeFactory_const_sptr successorFactory) override; + +private: + /// Successor factory + PeakShapeFactory_const_sptr m_successor; +}; + +} // namespace DataObjects +} // namespace Mantid diff --git a/Framework/DataObjects/src/PeakShapeDetectorBin.cpp b/Framework/DataObjects/src/PeakShapeDetectorBin.cpp new file mode 100644 index 000000000000..b8c8d8060577 --- /dev/null +++ b/Framework/DataObjects/src/PeakShapeDetectorBin.cpp @@ -0,0 +1,60 @@ +// Mantid Repository : https://github.com/mantidproject/mantid +// +// Copyright © 2024 ISIS Rutherford Appleton Laboratory UKRI, +// NScD Oak Ridge National Laboratory, European Spallation Source, +// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS +// SPDX - License - Identifier: GPL - 3.0 + +#include "MantidDataObjects/PeakShapeDetectorBin.h" +#include "MantidJson/Json.h" +#include "MantidKernel/cow_ptr.h" +#include + +#include + +namespace Mantid::DataObjects { + +/** + * Create PeakShapeDetectorBin + * @param detectorBinList The list containing each detector Ids associated with its start and end points in TOF or + * dSpacing domains + * @param frame SpecialCoordinateSystem frame, default is None + * @param algorithmName Name of the algorithm using this shape + * @param algorithmVersion Version of the above algorithm + */ +PeakShapeDetectorBin::PeakShapeDetectorBin(const std::vector> &detectorBinList, + Kernel::SpecialCoordinateSystem frame, std::string algorithmName, + int algorithmVersion) + : PeakShapeBase(frame, std::move(algorithmName), algorithmVersion), m_detectorBinList(detectorBinList) { + + if (detectorBinList.size() == 0) { + throw std::invalid_argument("No data provided for detector data"); + } +} + +bool PeakShapeDetectorBin::operator==(const PeakShapeDetectorBin &other) const { + return PeakShapeBase::operator==(other) && (this->m_detectorBinList == other.m_detectorBinList); +} + +std::string PeakShapeDetectorBin::toJSON() const { + Json::Value root; + PeakShapeBase::buildCommon(root); + Json::Value detBinList; + for (auto const &[detectorId, startX, endX] : m_detectorBinList) { + Json::Value detBinVal; + detBinVal["detId"] = Json::Value(detectorId); + detBinVal["startX"] = Json::Value(startX); + detBinVal["endX"] = Json::Value(endX); + detBinList.append(detBinVal); + } + + root["detectors"] = detBinList; + return Mantid::JsonHelpers::jsonToString(root); +} + +Mantid::Geometry::PeakShape *PeakShapeDetectorBin::clone() const { return new PeakShapeDetectorBin(*this); } + +std::string PeakShapeDetectorBin::shapeName() const { return PeakShapeDetectorBin::detectorBinShapeName(); } + +const std::string PeakShapeDetectorBin::detectorBinShapeName() { return "PeakShapeDetectorBin"; } + +} // namespace Mantid::DataObjects diff --git a/Framework/DataObjects/src/PeakShapeDetectorBinFactory.cpp b/Framework/DataObjects/src/PeakShapeDetectorBinFactory.cpp new file mode 100644 index 000000000000..4f531c507422 --- /dev/null +++ b/Framework/DataObjects/src/PeakShapeDetectorBinFactory.cpp @@ -0,0 +1,67 @@ +// Mantid Repository : https://github.com/mantidproject/mantid +// +// Copyright © 2024 ISIS Rutherford Appleton Laboratory UKRI, +// NScD Oak Ridge National Laboratory, European Spallation Source, +// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS +// SPDX - License - Identifier: GPL - 3.0 + +#include "MantidDataObjects/PeakShapeDetectorBinFactory.h" +#include "MantidDataObjects/PeakShapeDetectorBin.h" +#include "MantidJson/Json.h" +#include "MantidKernel/SpecialCoordinateSystem.h" + +#include +#include + +using namespace Mantid::Kernel; + +namespace Mantid::DataObjects { + +/** + * @brief Create the PeakShapeDetectorBin + * @param source : source JSON + * @return PeakShape via this factory or it's successors + */ +Mantid::Geometry::PeakShape *PeakShapeDetectorBinFactory::create(const std::string &source) const { + Json::Value root; + Mantid::Geometry::PeakShape *peakShape = nullptr; + if (!Mantid::JsonHelpers::parse(source, &root)) { + throw std::invalid_argument("PeakShapeDetectorBinFactory:: Source JSON for " + "the peak shape is not valid: " + + source); + } + + const std::string shape = root["shape"].asString(); + if (shape == PeakShapeDetectorBin::detectorBinShapeName()) { + const std::string algorithmName(root["algorithm_name"].asString()); + const int algorithmVersion(root["algorithm_version"].asInt()); + const auto frame(static_cast(root["frame"].asInt())); + + std::vector> detectorBinList; + const Json::Value detectorList = root["detectors"]; + for (uint32_t index = 0; index < detectorList.size(); index++) { + const Json::Value detBinVal = detectorList[index]; + detectorBinList.emplace_back(detBinVal["detId"].asInt(), detBinVal["startX"].asDouble(), + detBinVal["endX"].asDouble()); + } + peakShape = new PeakShapeDetectorBin(detectorBinList, frame, algorithmName, algorithmVersion); + } else { + if (m_successor) { + peakShape = m_successor->create(source); + } else { + throw std::invalid_argument("PeakShapeDetectorBinFactory:: No successor " + "factory able to process : " + + source); + } + } + return peakShape; +} + +/** + * @brief Set successor + * @param successorFactory : successor + */ +void PeakShapeDetectorBinFactory::setSuccessor(std::shared_ptr successorFactory) { + this->m_successor = successorFactory; +} + +} // namespace Mantid::DataObjects diff --git a/Framework/DataObjects/test/PeakShapeDetectorBinFactoryTest.h b/Framework/DataObjects/test/PeakShapeDetectorBinFactoryTest.h new file mode 100644 index 000000000000..b6989726f437 --- /dev/null +++ b/Framework/DataObjects/test/PeakShapeDetectorBinFactoryTest.h @@ -0,0 +1,76 @@ +// Mantid Repository : https://github.com/mantidproject/mantid +// +// Copyright © 2024 ISIS Rutherford Appleton Laboratory UKRI, +// NScD Oak Ridge National Laboratory, European Spallation Source, +// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS +// SPDX - License - Identifier: GPL - 3.0 + +#pragma once + +#include +#include +#include + +#include "MantidDataObjects/PeakShapeDetectorBin.h" +#include "MantidDataObjects/PeakShapeDetectorBinFactory.h" +#include "MantidJson/Json.h" +#include "MantidKernel/SpecialCoordinateSystem.h" +#include "MantidKernel/cow_ptr.h" +#include "MockObjects.h" + +using namespace Mantid; +using namespace Mantid::DataObjects; +using namespace Mantid::Kernel; +using Mantid::DataObjects::PeakShapeDetectorBin; +using Mantid::Kernel::SpecialCoordinateSystem; + +class PeakShapeDetectorBinFactoryTest : public CxxTest::TestSuite { +public: + static PeakShapeDetectorBinFactoryTest *createSuite() { return new PeakShapeDetectorBinFactoryTest(); } + static void destroySuite(PeakShapeDetectorBinFactoryTest *suite) { delete suite; } + + void test_invalid_json_with_no_successor() { + PeakShapeDetectorBinFactory factory; + TS_ASSERT_THROWS(factory.create(""), std::invalid_argument &); + } + + void test_successor_calling_when_shape_is_unhandled() { + using namespace testing; + MockPeakShapeFactory *delegate = new MockPeakShapeFactory; + EXPECT_CALL(*delegate, create(_)).Times(1); + + PeakShapeDetectorBinFactory factory; + factory.setSuccessor(PeakShapeFactory_const_sptr(delegate)); + + // Minimal valid JSON for describing the shape. + Json::Value root; + root["shape"] = "NotHandled"; + const std::string str_json = Mantid::JsonHelpers::jsonToString(root); + + TS_ASSERT_THROWS_NOTHING(factory.create(str_json)); + TS_ASSERT(Mock::VerifyAndClearExpectations(delegate)); + } + + void test_when_no_successor() { + PeakShapeDetectorBinFactory factory; + + // Minimal valid JSON for describing the shape. + Json::Value root; + root["shape"] = "NotHandled"; + const std::string str_json = Mantid::JsonHelpers::jsonToString(root); + + TS_ASSERT_THROWS(factory.create(str_json), std::invalid_argument &); + } + + void test_factory_create() { + PeakShapeDetectorBin shape({{100, 10, 50}, {200, 34, 55}}, SpecialCoordinateSystem::None, "test", 1); + + PeakShapeDetectorBinFactory factory; + std::shared_ptr productShape(factory.create(shape.toJSON())); + + std::shared_ptr factoryShape = std::dynamic_pointer_cast(productShape); + TS_ASSERT(factoryShape); + + TS_ASSERT_EQUALS(shape, *factoryShape); + TS_ASSERT_EQUALS(factoryShape->getDetectorBinList(), shape.getDetectorBinList()) + } +}; diff --git a/Framework/DataObjects/test/PeakShapeDetectorBinTest.h b/Framework/DataObjects/test/PeakShapeDetectorBinTest.h new file mode 100644 index 000000000000..825379e9a4da --- /dev/null +++ b/Framework/DataObjects/test/PeakShapeDetectorBinTest.h @@ -0,0 +1,124 @@ +// Mantid Repository : https://github.com/mantidproject/mantid +// +// Copyright © 2024 ISIS Rutherford Appleton Laboratory UKRI, +// NScD Oak Ridge National Laboratory, European Spallation Source, +// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS +// SPDX - License - Identifier: GPL - 3.0 + +#pragma once + +#include + +#include "MantidDataObjects/PeakShapeDetectorBin.h" +#include "MantidJson/Json.h" +#include "MantidKernel/cow_ptr.h" +#include +#include + +using Mantid::DataObjects::PeakShapeDetectorBin; +using Mantid::Kernel::SpecialCoordinateSystem; +using namespace Mantid; +using namespace Mantid::Kernel; + +class PeakShapeDetectorBinTest : 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 PeakShapeDetectorBinTest *createSuite() { return new PeakShapeDetectorBinTest(); } + static void destroySuite(PeakShapeDetectorBinTest *suite) { delete suite; } + + void test_constructor() { + std::vector> detPeakBinList = { + {100, 20.55, 40.52}, {102, 33.0, 55.67}, {104, 50.9, 70.5}}; + std::string algorithmName = "TestSuite"; + int version = 1; + auto coordinateSys = SpecialCoordinateSystem::None; + + std::shared_ptr peakShape = + std::make_shared(detPeakBinList, coordinateSys, algorithmName, version); + + TS_ASSERT_EQUALS(algorithmName, peakShape->algorithmName()); + TS_ASSERT_EQUALS(version, peakShape->algorithmVersion()); + TS_ASSERT_EQUALS(coordinateSys, peakShape->frame()); + TS_ASSERT_EQUALS("PeakShapeDetectorBin", peakShape->shapeName()); + TS_ASSERT_EQUALS(std::nullopt, peakShape->radius(Mantid::Geometry::PeakShape::RadiusType::Radius)); + TS_ASSERT_EQUALS(std::dynamic_pointer_cast(peakShape)->getDetectorBinList(), detPeakBinList); + + std::shared_ptr cloneShape(peakShape->clone()); + + TS_ASSERT_EQUALS(algorithmName, cloneShape->algorithmName()); + TS_ASSERT_EQUALS(version, cloneShape->algorithmVersion()); + TS_ASSERT_EQUALS(coordinateSys, cloneShape->frame()); + TS_ASSERT_EQUALS("PeakShapeDetectorBin", cloneShape->shapeName()); + TS_ASSERT_EQUALS(std::nullopt, cloneShape->radius(Mantid::Geometry::PeakShape::RadiusType::Radius)); + TS_ASSERT_EQUALS(std::dynamic_pointer_cast(cloneShape)->getDetectorBinList(), detPeakBinList); + } + + void test_json_serialization() { + std::vector> detPeakBinList = { + {100, 20.55, 40.52}, {102, 33.0, 55.67}, {104, 50.9, 70.5}}; + std::shared_ptr peakShape = + std::make_shared(detPeakBinList, SpecialCoordinateSystem::None, "TestSuite", 1); + + std::string jsonStr = peakShape->toJSON(); + Json::Value output; + TSM_ASSERT("Should parse as JSON", Mantid::JsonHelpers::parse(jsonStr, &output)); + TS_ASSERT_EQUALS("PeakShapeDetectorBin", output["shape"].asString()); + TS_ASSERT_EQUALS("TestSuite", output["algorithm_name"].asString()); + TS_ASSERT_EQUALS(1, output["algorithm_version"].asInt()); + TS_ASSERT_EQUALS(0, output["frame"].asInt()); + + Json::Value detectorBinList = output["detectors"]; + TS_ASSERT_EQUALS(detectorBinList[0]["detId"].asInt(), 100); + TS_ASSERT_EQUALS(detectorBinList[0]["startX"].asDouble(), 20.55); + TS_ASSERT_EQUALS(detectorBinList[0]["endX"].asDouble(), 40.52); + + TS_ASSERT_EQUALS(detectorBinList[1]["detId"].asInt(), 102); + TS_ASSERT_EQUALS(detectorBinList[1]["startX"].asDouble(), 33.0); + TS_ASSERT_EQUALS(detectorBinList[1]["endX"].asDouble(), 55.67); + + TS_ASSERT_EQUALS(detectorBinList[2]["detId"].asInt(), 104); + TS_ASSERT_EQUALS(detectorBinList[2]["startX"].asDouble(), 50.9); + TS_ASSERT_EQUALS(detectorBinList[2]["endX"].asDouble(), 70.5); + } + + void test_constructor_throws() { + std::vector> detPeakBinList = {}; + + TSM_ASSERT_THROWS("Should throw, bad directions", + PeakShapeDetectorBin(detPeakBinList, SpecialCoordinateSystem::None, "test", 1); + , std::invalid_argument &); + } + + void test_copy_constructor() { + std::vector> detPeakBinList = {{100, 10, 50}, {200, 34, 55}}; + PeakShapeDetectorBin shape1(detPeakBinList, SpecialCoordinateSystem::None, "test", 1); + PeakShapeDetectorBin shape2(shape1); + + TS_ASSERT_EQUALS(shape1.getDetectorBinList(), detPeakBinList); + TS_ASSERT_EQUALS(shape2.getDetectorBinList(), detPeakBinList); + TS_ASSERT_EQUALS(shape1, shape2); + } + + void test_assignment() { + std::vector> detPeakBinList1 = {{100, 10, 50}, {200, 34, 55}}; + PeakShapeDetectorBin shape1(detPeakBinList1, SpecialCoordinateSystem::None, "test", 1); + + std::vector> detPeakBinList2 = {{500, 68, 77}}; + PeakShapeDetectorBin shape2(detPeakBinList2, SpecialCoordinateSystem::None, "test", 1); + + shape2 = shape1; + + TS_ASSERT_EQUALS(shape2.getDetectorBinList(), shape1.getDetectorBinList()); + TS_ASSERT_EQUALS(shape2.toJSON(), shape1.toJSON()); + } + + void test_equal_operator() { + std::vector> detPeakBinList1 = {{100, 10, 50}, {200, 34, 55}}; + PeakShapeDetectorBin shape1(detPeakBinList1, SpecialCoordinateSystem::None, "algo1", 1); + + std::vector> detPeakBinList2 = {{100, 10, 50}, {200, 34, 55}}; + PeakShapeDetectorBin shape2(detPeakBinList2, SpecialCoordinateSystem::None, "algo2", 2); + + TS_ASSERT_EQUALS(shape1, shape2); + } +}; diff --git a/Framework/PythonInterface/mantid/dataobjects/CMakeLists.txt b/Framework/PythonInterface/mantid/dataobjects/CMakeLists.txt index 5a9a4324b76a..fdd096452d90 100644 --- a/Framework/PythonInterface/mantid/dataobjects/CMakeLists.txt +++ b/Framework/PythonInterface/mantid/dataobjects/CMakeLists.txt @@ -34,6 +34,7 @@ set(EXPORT_FILES src/Exports/PeakShapeSpherical.cpp src/Exports/PeakShapeEllipsoid.cpp src/Exports/WorkspaceValidators.cpp + src/Exports/PeakShapeDetectorBin.cpp ) set(MODULE_DEFINITION ${CMAKE_CURRENT_BINARY_DIR}/dataobjects.cpp) diff --git a/Framework/PythonInterface/mantid/dataobjects/src/Exports/PeakShapeDetectorBin.cpp b/Framework/PythonInterface/mantid/dataobjects/src/Exports/PeakShapeDetectorBin.cpp new file mode 100644 index 000000000000..55a94d58a4d4 --- /dev/null +++ b/Framework/PythonInterface/mantid/dataobjects/src/Exports/PeakShapeDetectorBin.cpp @@ -0,0 +1,42 @@ +// Mantid Repository : https://github.com/mantidproject/mantid +// +// Copyright © 2024 ISIS Rutherford Appleton Laboratory UKRI, +// NScD Oak Ridge National Laboratory, European Spallation Source, +// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS +// SPDX - License - Identifier: GPL - 3.0 + +#include "MantidDataObjects/PeakShapeDetectorBin.h" +#include "MantidPythonInterface/core/Converters/PySequenceToVector.h" +#include +#include +#include +#include +#include + +using namespace boost::python; +using namespace Mantid::DataObjects; +using Mantid::Kernel::SpecialCoordinateSystem; +using Mantid::PythonInterface::Converters::PySequenceToVector; + +PeakShapeDetectorBin *createPeakShapeDetectorBin(const boost::python::list &pyList, SpecialCoordinateSystem frame, + const std::string &algorithmName = std::string(), + int algorithmVersion = -1) { + // Convert Python list of tuples to std::vector> + std::vector> detectorBinList; + + for (int i = 0; i < boost::python::len(pyList); ++i) { + boost::python::tuple pyTuple = boost::python::extract(pyList[i]); + int32_t detectorID = boost::python::extract(pyTuple[0]); + double startX = boost::python::extract(pyTuple[1]); + double endX = boost::python::extract(pyTuple[2]); + detectorBinList.emplace_back(detectorID, startX, endX); + } + + return new PeakShapeDetectorBin(detectorBinList, frame, algorithmName, algorithmVersion); +} + +void export_PeakShapeDetectorBin() { + class_, boost::noncopyable>("PeakShapeDetectorBin", no_init) + .def("__init__", make_constructor(&createPeakShapeDetectorBin, default_call_policies(), + (arg("detectorBinList"), arg("frame") = SpecialCoordinateSystem::None, + arg("algorithmName") = "", arg("algorithmVersion") = -1))); +} diff --git a/Framework/PythonInterface/test/python/mantid/geometry/IPeakTest.py b/Framework/PythonInterface/test/python/mantid/geometry/IPeakTest.py index 866bc51f8b58..4b1b515047bc 100644 --- a/Framework/PythonInterface/test/python/mantid/geometry/IPeakTest.py +++ b/Framework/PythonInterface/test/python/mantid/geometry/IPeakTest.py @@ -5,11 +5,12 @@ # Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS # SPDX - License - Identifier: GPL - 3.0 + import unittest -from mantid.kernel import V3D -from mantid.dataobjects import NoShape, PeakShapeSpherical, PeakShapeEllipsoid +from mantid.kernel import V3D, SpecialCoordinateSystem +from mantid.dataobjects import NoShape, PeakShapeSpherical, PeakShapeEllipsoid, PeakShapeDetectorBin from mantid.simpleapi import CreateSimulationWorkspace, CreatePeaksWorkspace, LoadInstrument import numpy as np import numpy.testing as npt +import json class IPeakTest(unittest.TestCase): @@ -173,6 +174,8 @@ def test_set_peak_shape(self): no_shape = NoShape() sphere = PeakShapeSpherical(1) ellipse = PeakShapeEllipsoid([V3D(1, 0, 0), V3D(0, 1, 0), V3D(0, 0, 1)], [0.1, 0.2, 0.3], [0.4, 0.5, 0.6], [0.7, 0.8, 0.9]) + detector_x_list = [(14500, 20.45, 50.89), (45670, 109.88, 409.56), (60995, 56009.89, 70988.89)] + detector_bin = PeakShapeDetectorBin(detector_x_list, SpecialCoordinateSystem.NONE, "test", 1) self.assertEqual(self._peak.getPeakShape().shapeName(), "none") @@ -185,6 +188,16 @@ def test_set_peak_shape(self): self._peak.setPeakShape(no_shape) self.assertEqual(self._peak.getPeakShape().shapeName(), "none") + self._peak.setPeakShape(detector_bin) + self.assertEqual(self._peak.getPeakShape().shapeName(), "PeakShapeDetectorBin") + self.assertEqual(self._peak.getPeakShape().algorithmVersion(), 1) + self.assertEqual(self._peak.getPeakShape().algorithmName(), "test") + det_bin_dict = json.loads(self._peak.getPeakShape().toJSON()) + for i in range(3): + self.assertEqual(det_bin_dict["detectors"][i]["detId"], detector_x_list[i][0]) + self.assertEqual(det_bin_dict["detectors"][i]["startX"], detector_x_list[i][1]) + self.assertEqual(det_bin_dict["detectors"][i]["endX"], detector_x_list[i][2]) + if __name__ == "__main__": unittest.main() diff --git a/docs/source/api/python/mantid/dataobjects/PeakShapeDetectorBin.rst b/docs/source/api/python/mantid/dataobjects/PeakShapeDetectorBin.rst new file mode 100644 index 000000000000..e53b45926b4d --- /dev/null +++ b/docs/source/api/python/mantid/dataobjects/PeakShapeDetectorBin.rst @@ -0,0 +1,14 @@ +====================== + PeakShapeDetectorBin +====================== + +This is a Python binding to the C++ class Mantid::DataObjects::PeakShapeDetectorBin. + +*bases:* :py:obj:`mantid.geometry.PeakShape` + +.. module:`mantid.dataobjects` + +.. autoclass:: mantid.dataobjects.PeakShapeDetectorBin + :members: + :undoc-members: + :inherited-members: diff --git a/docs/source/release/v6.12.0/Diffraction/Single_Crystal/New_features/38254.rst b/docs/source/release/v6.12.0/Diffraction/Single_Crystal/New_features/38254.rst new file mode 100644 index 000000000000..3205cd4e6548 --- /dev/null +++ b/docs/source/release/v6.12.0/Diffraction/Single_Crystal/New_features/38254.rst @@ -0,0 +1 @@ +- A new peak shape named PeakShapeDetectorBin was introduced to save the detector IDs and bin indices of either TOF or dSpacing domains. This peak shape could be used for Overlap detection, Two-step integration and Eventual visualisation on instrument view.