Skip to content

Commit

Permalink
38254 Introducing PeakShapeDetectorBin peak shape (#38433)
Browse files Browse the repository at this point in the history
* PeakShapeDetectorBin added with boost::python bindings

* cpp check fixed

* fixed comp warnings

* Unit tests added for equal opeartor in python and c++

* early return added and cppcheck fix

* reverted exposing opearator== into python for consistency
  • Loading branch information
warunawickramasingha authored Dec 11, 2024
1 parent 9b7db52 commit 32bc656
Show file tree
Hide file tree
Showing 13 changed files with 495 additions and 4 deletions.
9 changes: 7 additions & 2 deletions Framework/DataHandling/src/LoadNexusProcessed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -1164,10 +1165,12 @@ API::Workspace_sptr LoadNexusProcessed::loadLeanElasticPeaksEntry(const NXEntry

PeakShapeFactory_sptr peakFactoryEllipsoid = std::make_shared<PeakShapeEllipsoidFactory>();
PeakShapeFactory_sptr peakFactorySphere = std::make_shared<PeakShapeSphericalFactory>();
PeakShapeFactory_sptr peakFactoryDetectorBin = std::make_shared<PeakShapeDetectorBinFactory>();
PeakShapeFactory_sptr peakFactoryNone = std::make_shared<PeakNoShapeFactory>();

peakFactoryEllipsoid->setSuccessor(peakFactorySphere);
peakFactorySphere->setSuccessor(peakFactoryNone);
peakFactorySphere->setSuccessor(peakFactoryDetectorBin);
peakFactoryDetectorBin->setSuccessor(peakFactoryNone);

NXInfo info = nx_tw.getDataSetInfo(str);
NXChar data = nx_tw.openNXChar(str);
Expand Down Expand Up @@ -1456,10 +1459,12 @@ API::Workspace_sptr LoadNexusProcessed::loadPeaksEntry(const NXEntry &entry) {

PeakShapeFactory_sptr peakFactoryEllipsoid = std::make_shared<PeakShapeEllipsoidFactory>();
PeakShapeFactory_sptr peakFactorySphere = std::make_shared<PeakShapeSphericalFactory>();
PeakShapeFactory_sptr peakFactoryDetectorBin = std::make_shared<PeakShapeDetectorBinFactory>();
PeakShapeFactory_sptr peakFactoryNone = std::make_shared<PeakNoShapeFactory>();

peakFactoryEllipsoid->setSuccessor(peakFactorySphere);
peakFactorySphere->setSuccessor(peakFactoryNone);
peakFactorySphere->setSuccessor(peakFactoryDetectorBin);
peakFactoryDetectorBin->setSuccessor(peakFactoryNone);

NXInfo info = nx_tw.getDataSetInfo(str);
NXChar data = nx_tw.openNXChar(str);
Expand Down
6 changes: 6 additions & 0 deletions Framework/DataObjects/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -205,6 +209,8 @@ set(TEST_FILES
WorkspaceSingleValueTest.h
WorkspaceValidatorsTest.h
MortonIndex/BitInterleavingTest.h
PeakShapeDetectorBinTest.h
PeakShapeDetectorBinFactoryTest.h
)

if(COVERAGE)
Expand Down
47 changes: 47 additions & 0 deletions Framework/DataObjects/inc/MantidDataObjects/PeakShapeDetectorBin.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright &copy; 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 <vector>

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<std::tuple<int32_t, double, double>> &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<double> radius(RadiusType) const override { return std::nullopt; }

static const std::string detectorBinShapeName();

const std::vector<std::tuple<int32_t, double, double>> &getDetectorBinList() const { return m_detectorBinList; }

private:
std::vector<std::tuple<int32_t, double, double>> m_detectorBinList;
};

using PeakShapeDetectorTOF_sptr = std::shared_ptr<PeakShapeDetectorBin>;
using PeakShapeDetectorTOF_const_sptr = std::shared_ptr<const PeakShapeDetectorBin>;

} // namespace DataObjects
} // namespace Mantid
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright &copy; 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
60 changes: 60 additions & 0 deletions Framework/DataObjects/src/PeakShapeDetectorBin.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright &copy; 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 <json/json.h>

#include <utility>

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<std::tuple<int32_t, double, double>> &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
67 changes: 67 additions & 0 deletions Framework/DataObjects/src/PeakShapeDetectorBinFactory.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright &copy; 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 <json/json.h>
#include <stdexcept>

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<SpecialCoordinateSystem>(root["frame"].asInt()));

std::vector<std::tuple<int32_t, double, double>> 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<const PeakShapeFactory> successorFactory) {
this->m_successor = successorFactory;
}

} // namespace Mantid::DataObjects
76 changes: 76 additions & 0 deletions Framework/DataObjects/test/PeakShapeDetectorBinFactoryTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright &copy; 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 <cxxtest/TestSuite.h>
#include <gmock/gmock.h>
#include <json/json.h>

#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<Mantid::Geometry::PeakShape> productShape(factory.create(shape.toJSON()));

std::shared_ptr<PeakShapeDetectorBin> factoryShape = std::dynamic_pointer_cast<PeakShapeDetectorBin>(productShape);
TS_ASSERT(factoryShape);

TS_ASSERT_EQUALS(shape, *factoryShape);
TS_ASSERT_EQUALS(factoryShape->getDetectorBinList(), shape.getDetectorBinList())
}
};
Loading

0 comments on commit 32bc656

Please sign in to comment.