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/inc/MantidDataObjects/PeakShapeDetectorBin.h b/Framework/DataObjects/inc/MantidDataObjects/PeakShapeDetectorBin.h index deae571171c2..beb83d811c2b 100644 --- a/Framework/DataObjects/inc/MantidDataObjects/PeakShapeDetectorBin.h +++ b/Framework/DataObjects/inc/MantidDataObjects/PeakShapeDetectorBin.h @@ -7,6 +7,7 @@ #pragma once #include "MantidDataObjects/PeakShapeBase.h" +#include namespace Mantid { namespace DataObjects { @@ -15,8 +16,7 @@ namespace DataObjects { */ class MANTID_DATAOBJECTS_DLL PeakShapeDetectorBin : public PeakShapeBase { public: - /// Constructor - PeakShapeDetectorBin(std::vector> detectorXList, + PeakShapeDetectorBin(std::vector> detectorBinList, Kernel::SpecialCoordinateSystem frame, std::string algorithmName = std::string(), int algorithmVersion = -1); /// Equals operator @@ -34,10 +34,10 @@ class MANTID_DATAOBJECTS_DLL PeakShapeDetectorBin : public PeakShapeBase { static const std::string detectorBinShapeName(); - const std::vector> &getDetectorXList() const { return m_detectorXList; } + const std::vector> &getDetectorBinList() const { return m_detectorBinList; } private: - std::vector> m_detectorXList; + std::vector> m_detectorBinList; }; using PeakShapeDetectorTOF_sptr = std::shared_ptr; diff --git a/Framework/DataObjects/src/PeakShapeDetectorBin.cpp b/Framework/DataObjects/src/PeakShapeDetectorBin.cpp index 538008421362..c142d4a889c6 100644 --- a/Framework/DataObjects/src/PeakShapeDetectorBin.cpp +++ b/Framework/DataObjects/src/PeakShapeDetectorBin.cpp @@ -13,33 +13,41 @@ namespace Mantid::DataObjects { -PeakShapeDetectorBin::PeakShapeDetectorBin(std::vector> detectorXList, +/** + * 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(std::vector> detectorBinList, Kernel::SpecialCoordinateSystem frame, std::string algorithmName, int algorithmVersion) - : PeakShapeBase(frame, std::move(algorithmName), algorithmVersion), m_detectorXList(detectorXList) { + : PeakShapeBase(frame, std::move(algorithmName), algorithmVersion), m_detectorBinList(detectorBinList) { - if (detectorXList.size() == 0) { + 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_detectorXList == other.m_detectorXList); + return PeakShapeBase::operator==(other) && (this->m_detectorBinList == other.m_detectorBinList); } std::string PeakShapeDetectorBin::toJSON() const { Json::Value root; PeakShapeBase::buildCommon(root); - Json::Value detXList; - for (auto const &[detectorId, startX, endX] : m_detectorXList) { - Json::Value detXVal; - detXVal["detId"] = Json::Value(detectorId); - detXVal["startX"] = Json::Value(startX); - detXVal["endX"] = Json::Value(endX); - detXList.append(detXVal); + 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"] = detXList; + root["detectors"] = detBinList; return Mantid::JsonHelpers::jsonToString(root); } diff --git a/Framework/DataObjects/src/PeakShapeDetectorBinFactory.cpp b/Framework/DataObjects/src/PeakShapeDetectorBinFactory.cpp index c2979fb62d87..01566ca6de52 100644 --- a/Framework/DataObjects/src/PeakShapeDetectorBinFactory.cpp +++ b/Framework/DataObjects/src/PeakShapeDetectorBinFactory.cpp @@ -31,13 +31,14 @@ Mantid::Geometry::PeakShape *PeakShapeDetectorBinFactory::create(const std::stri const int algorithmVersion(root["algorithm_version"].asInt()); const auto frame(static_cast(root["frame"].asInt())); - std::vector> detectorXList; + std::vector> detectorBinList; const Json::Value detectorList = root["detectors"]; for (int index = 0; index < detectorList.size(); index++) { - const Json::Value detXVal = detectorList[index]; - detectorXList.emplace_back(detXVal["detId"].asInt(), detXVal["startX"].asDouble(), detXVal["endX"].asDouble()); + const Json::Value detBinVal = detectorList[index]; + detectorBinList.emplace_back(detBinVal["detId"].asInt(), detBinVal["startX"].asDouble(), + detBinVal["endX"].asDouble()); } - peakShape = new PeakShapeDetectorBin(detectorXList, frame, algorithmName, algorithmVersion); + peakShape = new PeakShapeDetectorBin(detectorBinList, frame, algorithmName, algorithmVersion); } else { if (m_successor) { peakShape = m_successor->create(source); diff --git a/Framework/DataObjects/test/PeakShapeDetectorBinFactoryTest.h b/Framework/DataObjects/test/PeakShapeDetectorBinFactoryTest.h index 0d996be1d5cd..b6989726f437 100644 --- a/Framework/DataObjects/test/PeakShapeDetectorBinFactoryTest.h +++ b/Framework/DataObjects/test/PeakShapeDetectorBinFactoryTest.h @@ -71,6 +71,6 @@ class PeakShapeDetectorBinFactoryTest : public CxxTest::TestSuite { TS_ASSERT(factoryShape); TS_ASSERT_EQUALS(shape, *factoryShape); - TS_ASSERT_EQUALS(factoryShape->getDetectorXList(), shape.getDetectorXList()) + TS_ASSERT_EQUALS(factoryShape->getDetectorBinList(), shape.getDetectorBinList()) } }; diff --git a/Framework/DataObjects/test/PeakShapeDetectorBinTest.h b/Framework/DataObjects/test/PeakShapeDetectorBinTest.h index 65580b78a3de..270f64dc3185 100644 --- a/Framework/DataObjects/test/PeakShapeDetectorBinTest.h +++ b/Framework/DataObjects/test/PeakShapeDetectorBinTest.h @@ -27,21 +27,21 @@ class PeakShapeDetectorBinTest : public CxxTest::TestSuite { static void destroySuite(PeakShapeDetectorBinTest *suite) { delete suite; } void test_constructor() { - std::vector> detPeakXList = { + 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(detPeakXList, coordinateSys, algorithmName, version); + 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)->getDetectorXList(), detPeakXList); + TS_ASSERT_EQUALS(std::dynamic_pointer_cast(peakShape)->getDetectorBinList(), detPeakBinList); std::shared_ptr cloneShape(peakShape->clone()); @@ -50,14 +50,14 @@ class PeakShapeDetectorBinTest : public CxxTest::TestSuite { 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)->getDetectorXList(), detPeakXList); + TS_ASSERT_EQUALS(std::dynamic_pointer_cast(cloneShape)->getDetectorBinList(), detPeakBinList); } void test_json_serialization() { - std::vector> detPeakXList = { + 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(detPeakXList, SpecialCoordinateSystem::None, "TestSuite", 1); + std::make_shared(detPeakBinList, SpecialCoordinateSystem::None, "TestSuite", 1); std::string jsonStr = peakShape->toJSON(); Json::Value output; @@ -67,48 +67,48 @@ class PeakShapeDetectorBinTest : public CxxTest::TestSuite { TS_ASSERT_EQUALS(1, output["algorithm_version"].asInt()); TS_ASSERT_EQUALS(0, output["frame"].asInt()); - Json::Value detectorXList = output["detectors"]; - TS_ASSERT_EQUALS(detectorXList[0]["detId"].asInt(), 100); - TS_ASSERT_EQUALS(detectorXList[0]["startX"].asDouble(), 20.55); - TS_ASSERT_EQUALS(detectorXList[0]["endX"].asDouble(), 40.52); + 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(detectorXList[1]["detId"].asInt(), 102); - TS_ASSERT_EQUALS(detectorXList[1]["startX"].asDouble(), 33.0); - TS_ASSERT_EQUALS(detectorXList[1]["endX"].asDouble(), 55.67); + 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(detectorXList[2]["detId"].asInt(), 104); - TS_ASSERT_EQUALS(detectorXList[2]["startX"].asDouble(), 50.9); - TS_ASSERT_EQUALS(detectorXList[2]["endX"].asDouble(), 70.5); + 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> detPeakXList = {}; + std::vector> detPeakBinList = {}; TSM_ASSERT_THROWS("Should throw, bad directions", - PeakShapeDetectorBin(detPeakXList, SpecialCoordinateSystem::None, "test", 1); + PeakShapeDetectorBin(detPeakBinList, SpecialCoordinateSystem::None, "test", 1); , std::invalid_argument &); } void test_copy_constructor() { - std::vector> detPeakXList = {{100, 10, 50}, {200, 34, 55}}; - PeakShapeDetectorBin shape1(detPeakXList, SpecialCoordinateSystem::None, "test", 1); + std::vector> detPeakBinList = {{100, 10, 50}, {200, 34, 55}}; + PeakShapeDetectorBin shape1(detPeakBinList, SpecialCoordinateSystem::None, "test", 1); PeakShapeDetectorBin shape2(shape1); - TS_ASSERT_EQUALS(shape1.getDetectorXList(), detPeakXList); - TS_ASSERT_EQUALS(shape2.getDetectorXList(), detPeakXList); + TS_ASSERT_EQUALS(shape1.getDetectorBinList(), detPeakBinList); + TS_ASSERT_EQUALS(shape2.getDetectorBinList(), detPeakBinList); TS_ASSERT_EQUALS(shape1, shape2); } void test_assignment() { - std::vector> detPeakXList1 = {{100, 10, 50}, {200, 34, 55}}; - PeakShapeDetectorBin shape1(detPeakXList1, SpecialCoordinateSystem::None, "test", 1); + std::vector> detPeakBinList1 = {{100, 10, 50}, {200, 34, 55}}; + PeakShapeDetectorBin shape1(detPeakBinList1, SpecialCoordinateSystem::None, "test", 1); - std::vector> detPeakXList2 = {{500, 68, 77}}; - PeakShapeDetectorBin shape2(detPeakXList2, SpecialCoordinateSystem::None, "test", 1); + std::vector> detPeakBinList2 = {{500, 68, 77}}; + PeakShapeDetectorBin shape2(detPeakBinList2, SpecialCoordinateSystem::None, "test", 1); shape2 = shape1; - TS_ASSERT_EQUALS(shape2.getDetectorXList(), shape1.getDetectorXList()); + TS_ASSERT_EQUALS(shape2.getDetectorBinList(), shape1.getDetectorBinList()); TS_ASSERT_EQUALS(shape2.toJSON(), shape1.toJSON()); } }; 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..a891485a8997 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]) + detectorXList = [(14500, 20.45, 50.89), (45670, 109.88, 409.56), (60995, 56009.89, 70988.89)] + detectorBin = PeakShapeDetectorBin(detectorXList, 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(detectorBin) + 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"], detectorXList[i][0]) + self.assertEqual(det_bin_dict["detectors"][i]["startX"], detectorXList[i][1]) + self.assertEqual(det_bin_dict["detectors"][i]["endX"], detectorXList[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.