diff --git a/Code/Mantid/Framework/DataObjects/CMakeLists.txt b/Code/Mantid/Framework/DataObjects/CMakeLists.txt index 5ddf645329ed..0e165cd0107d 100644 --- a/Code/Mantid/Framework/DataObjects/CMakeLists.txt +++ b/Code/Mantid/Framework/DataObjects/CMakeLists.txt @@ -14,6 +14,7 @@ set ( SRC_FILES src/PeakColumn.cpp src/PeakNoShapeFactory.cpp src/PeakShapeBase.cpp + src/PeakShapeEllipsoid.cpp src/PeakShapeSpherical.cpp src/PeakShapeSphericalFactory.cpp src/PeaksWorkspace.cpp @@ -51,6 +52,7 @@ set ( INC_FILES inc/MantidDataObjects/PeakNoShapeFactory.h inc/MantidDataObjects/PeakShape.h inc/MantidDataObjects/PeakShapeBase.h + inc/MantidDataObjects/PeakShapeEllipsoid.h inc/MantidDataObjects/PeakShapeFactory.h inc/MantidDataObjects/PeakShapeSpherical.h inc/MantidDataObjects/PeakShapeSphericalFactory.h @@ -79,6 +81,7 @@ set ( TEST_FILES OffsetsWorkspaceTest.h PeakColumnTest.h PeakNoShapeFactoryTest.h + PeakShapeEllipsoidTest.h PeakShapeSphericalFactoryTest.h PeakShapeSphericalTest.h PeakTest.h diff --git a/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/PeakShapeEllipsoid.h b/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/PeakShapeEllipsoid.h new file mode 100644 index 000000000000..3c187ac2da62 --- /dev/null +++ b/Code/Mantid/Framework/DataObjects/inc/MantidDataObjects/PeakShapeEllipsoid.h @@ -0,0 +1,84 @@ +#ifndef MANTID_DATAOBJECTS_PEAKSHAPEELLIPSOID_H_ +#define MANTID_DATAOBJECTS_PEAKSHAPEELLIPSOID_H_ + +#include "MantidKernel/System.h" +#include "MantidKernel/V3D.h" +#include "MantidDataObjects/PeakShapeBase.h" + + +namespace Mantid +{ +namespace DataObjects +{ + + /** PeakShapeEllipsoid : PeakShape representing a 3D ellipsoid + + Copyright © 2015 ISIS Rutherford Appleton Laboratory, NScD Oak Ridge National Laboratory & European Spallation Source + + This file is part of Mantid. + + Mantid is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Mantid is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + File change history is stored at: + Code Documentation is available at: + */ + class DLLExport PeakShapeEllipsoid : public PeakShapeBase + { + public: + /// Constructor + PeakShapeEllipsoid(std::vector directions, std::vector abcRadius, std::vector abcBackgroundInnerRadius, std::vector abcBackgroundOuterRadius, API::SpecialCoordinateSystem frame, + std::string algorithmName = std::string(), + int algorithmVersion = -1); + /// Copy constructor + PeakShapeEllipsoid(const PeakShapeEllipsoid& other); + /// Assignment operator + PeakShapeEllipsoid& operator=(const PeakShapeEllipsoid& other); + /// Equals operator + bool operator==(const PeakShapeEllipsoid& other) const; + /// Destructor + virtual ~PeakShapeEllipsoid(); + /// Get radii + std::vector abcRadii() const; + /// Get background inner radii + std::vector abcRadiiBackgroundInner() const; + /// Get background outer radii + std::vector abcRadiiBackgroundOuter() const; + /// Get ellipsoid directions + std::vector directions() const; + + /// PeakShape interface + std::string toJSON() const; + /// Clone ellipsoid + PeakShape *clone() const; + /// Get the peak shape + std::string shapeName() const; + + private: + /// principle axis + std::vector m_directions; + /// radii + std::vector m_abc_radii; + /// inner radii + std::vector m_abc_radiiBackgroundInner; + /// outer radii + std::vector m_abc_radiiBackgroundOuter; + + + }; + + +} // namespace DataObjects +} // namespace Mantid + +#endif /* MANTID_DATAOBJECTS_PEAKSHAPEELLIPSOID_H_ */ diff --git a/Code/Mantid/Framework/DataObjects/src/PeakShapeEllipsoid.cpp b/Code/Mantid/Framework/DataObjects/src/PeakShapeEllipsoid.cpp new file mode 100644 index 000000000000..d33a19cadf3a --- /dev/null +++ b/Code/Mantid/Framework/DataObjects/src/PeakShapeEllipsoid.cpp @@ -0,0 +1,105 @@ +#include "MantidDataObjects/PeakShapeEllipsoid.h" +#include "MantidKernel/cow_ptr.h" +#include + +namespace Mantid { +namespace DataObjects { + +PeakShapeEllipsoid::PeakShapeEllipsoid( + std::vector directions, std::vector abcRadii, + std::vector abcRadiiBackgroundInner, + std::vector abcRadiiBackgroundOuter, + API::SpecialCoordinateSystem frame, std::string algorithmName, + int algorithmVersion) + : PeakShapeBase(frame, algorithmName, algorithmVersion), + m_directions(directions), m_abc_radii(abcRadii), + m_abc_radiiBackgroundInner(abcRadiiBackgroundInner), + m_abc_radiiBackgroundOuter(abcRadiiBackgroundOuter) { + + if (directions.size() != 3) { + throw std::invalid_argument("directions must be of size 3"); + } + if (abcRadii.size() != 3) { + throw std::invalid_argument("radii must be of size 3"); + } + if (abcRadiiBackgroundInner.size() != 3) { + throw std::invalid_argument("radii inner must be of size 3"); + } + if (abcRadiiBackgroundOuter.size() != 3) { + throw std::invalid_argument("radii outer must be of size 3"); + } +} + +PeakShapeEllipsoid::PeakShapeEllipsoid(const PeakShapeEllipsoid &other) + : PeakShapeBase(other), m_directions(other.directions()), + m_abc_radii(other.abcRadii()), + m_abc_radiiBackgroundInner(other.abcRadiiBackgroundInner()), + m_abc_radiiBackgroundOuter(other.abcRadiiBackgroundOuter()) {} + +PeakShapeEllipsoid &PeakShapeEllipsoid:: +operator=(const PeakShapeEllipsoid &other) { + if (&other != this) { + PeakShapeBase::operator=(other); + m_directions = other.directions(); + m_abc_radii = other.abcRadii(); + m_abc_radiiBackgroundInner = other.abcRadiiBackgroundInner(); + m_abc_radiiBackgroundOuter = other.abcRadiiBackgroundOuter(); + } + return *this; +} + +bool PeakShapeEllipsoid::operator==(const PeakShapeEllipsoid &other) const { + return PeakShapeBase::operator==(other) && + other.directions() == this->directions() && + other.abcRadii() == this->abcRadii() && + other.abcRadiiBackgroundInner() == this->abcRadiiBackgroundInner() && + other.abcRadiiBackgroundOuter() == this->abcRadiiBackgroundOuter(); +} + +PeakShapeEllipsoid::~PeakShapeEllipsoid() {} + +std::vector PeakShapeEllipsoid::abcRadii() const { return m_abc_radii; } + +std::vector PeakShapeEllipsoid::abcRadiiBackgroundInner() const { + return m_abc_radiiBackgroundInner; +} + +std::vector PeakShapeEllipsoid::abcRadiiBackgroundOuter() const { + return m_abc_radiiBackgroundOuter; +} + +std::vector PeakShapeEllipsoid::directions() const { + return m_directions; +} + +std::string PeakShapeEllipsoid::toJSON() const { + Json::Value root; + PeakShapeBase::buildCommon(root); + root["radius0"] = Json::Value(m_abc_radii[0]); + root["radius1"] = Json::Value(m_abc_radii[1]); + root["radius2"] = Json::Value(m_abc_radii[2]); + + root["background_inner_radius0"] = Json::Value(m_abc_radiiBackgroundInner[0]); + root["background_inner_radius1"] = Json::Value(m_abc_radiiBackgroundInner[1]); + root["background_inner_radius2"] = Json::Value(m_abc_radiiBackgroundInner[2]); + + root["background_outer_radius0"] = Json::Value(m_abc_radiiBackgroundOuter[0]); + root["background_outer_radius1"] = Json::Value(m_abc_radiiBackgroundOuter[1]); + root["background_outer_radius2"] = Json::Value(m_abc_radiiBackgroundOuter[2]); + + root["direction0"] = m_directions[0].toString(); + root["direction1"] = m_directions[1].toString(); + root["direction2"] = m_directions[2].toString(); + + Json::StyledWriter writer; + return writer.write(root); +} + +PeakShape *PeakShapeEllipsoid::clone() const { + return new PeakShapeEllipsoid(*this); +} + +std::string PeakShapeEllipsoid::shapeName() const { return "ellipsoid"; } + +} // namespace DataObjects +} // namespace Mantid diff --git a/Code/Mantid/Framework/DataObjects/test/PeakShapeEllipsoidTest.h b/Code/Mantid/Framework/DataObjects/test/PeakShapeEllipsoidTest.h new file mode 100644 index 000000000000..101a674bd40a --- /dev/null +++ b/Code/Mantid/Framework/DataObjects/test/PeakShapeEllipsoidTest.h @@ -0,0 +1,185 @@ +#ifndef MANTID_DATAOBJECTS_PEAKSHAPEELLIPSOIDTEST_H_ +#define MANTID_DATAOBJECTS_PEAKSHAPEELLIPSOIDTEST_H_ + +#include + +#include "MantidDataObjects/PeakShapeEllipsoid.h" +#include "MantidKernel/cow_ptr.h" +#include "MantidKernel/V3D.h" +#include +#include +#include + +using Mantid::DataObjects::PeakShapeEllipsoid; +using namespace Mantid; +using namespace Mantid::Kernel; +using namespace Mantid::API; +using namespace boost::assign; + +class PeakShapeEllipsoidTest : 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 PeakShapeEllipsoidTest *createSuite() { + return new PeakShapeEllipsoidTest(); + } + static void destroySuite(PeakShapeEllipsoidTest *suite) { delete suite; } + + void test_constructor() { + auto directions = list_of(V3D(1, 0, 0))(V3D(0, 1, 0))(V3D(0, 0, 1)) + .convert_to_container>(); + const MantidVec abcRadii = list_of(2)(3)(4); + const MantidVec abcInnerRadii = list_of(5)(6)(7); + const MantidVec abcOuterRadii = list_of(8)(9)(10); + const SpecialCoordinateSystem frame = HKL; + const std::string algorithmName = "foo"; + const int algorithmVersion = 3; + + // Construct it. + PeakShapeEllipsoid shape(directions, abcRadii, abcInnerRadii, abcOuterRadii, + frame, algorithmName, algorithmVersion); + + TS_ASSERT_EQUALS(abcRadii, shape.abcRadii()); + TS_ASSERT_EQUALS(abcInnerRadii, shape.abcRadiiBackgroundInner()); + TS_ASSERT_EQUALS(abcOuterRadii, shape.abcRadiiBackgroundOuter()); + + TS_ASSERT_EQUALS(frame, shape.frame()); + TS_ASSERT_EQUALS(algorithmName, shape.algorithmName()); + TS_ASSERT_EQUALS(algorithmVersion, shape.algorithmVersion()); + } + + void test_constructor_throws() { + auto directions = list_of(V3D(1, 0, 0))(V3D(0, 1, 0))(V3D(0, 0, 1)) + .convert_to_container>(); + auto bad_directions = + list_of(V3D(1, 0, 0)).convert_to_container>(); + const MantidVec abcRadii = list_of(2)(3)(4); + const MantidVec bad_abcRadii = list_of(2)(3)(4)(5); + const MantidVec abcInnerRadii = list_of(5)(6)(7); + const MantidVec bad_abcInnerRadii = list_of(5)(6); + const MantidVec abcOuterRadii = list_of(8)(9)(10); + const MantidVec bad_abcOuterRadii = list_of(8)(9)(10)(11); + const SpecialCoordinateSystem frame = HKL; + const std::string algorithmName = "foo"; + const int algorithmVersion = 3; + + TSM_ASSERT_THROWS("Should throw, bad directions", + PeakShapeEllipsoid(bad_directions, abcRadii, + abcInnerRadii, abcOuterRadii, frame), + std::invalid_argument &); + TSM_ASSERT_THROWS("Should throw, bad radii", + PeakShapeEllipsoid(directions, bad_abcRadii, + abcInnerRadii, abcOuterRadii, frame), + std::invalid_argument &); + TSM_ASSERT_THROWS("Should throw, bad inner radii", + PeakShapeEllipsoid(directions, abcRadii, + bad_abcInnerRadii, abcOuterRadii, + frame), + std::invalid_argument &); + TSM_ASSERT_THROWS("Should throw, bad outer radii", + PeakShapeEllipsoid(directions, abcRadii, abcInnerRadii, + bad_abcOuterRadii, frame), + std::invalid_argument &); + } + + void test_copy_constructor() { + auto directions = list_of(V3D(1, 0, 0))(V3D(0, 1, 0))(V3D(0, 0, 1)) + .convert_to_container>(); + const MantidVec abcRadii = list_of(2)(3)(4); + const MantidVec abcInnerRadii = list_of(5)(6)(7); + const MantidVec abcOuterRadii = list_of(8)(9)(10); + const SpecialCoordinateSystem frame = HKL; + const std::string algorithmName = "foo"; + const int algorithmVersion = 3; + + // Construct it. + PeakShapeEllipsoid a(directions, abcRadii, abcInnerRadii, abcOuterRadii, + frame, algorithmName, algorithmVersion); + + PeakShapeEllipsoid b(a); + TS_ASSERT_EQUALS(abcRadii, b.abcRadii()); + TS_ASSERT_EQUALS(abcInnerRadii, b.abcRadiiBackgroundInner()); + TS_ASSERT_EQUALS(abcOuterRadii, b.abcRadiiBackgroundOuter()); + + TS_ASSERT_EQUALS(frame, b.frame()); + TS_ASSERT_EQUALS(algorithmName, b.algorithmName()); + TS_ASSERT_EQUALS(algorithmVersion, b.algorithmVersion()); + } + + void test_assignment() { + PeakShapeEllipsoid a(list_of(V3D(1, 0, 0))(V3D(0, 1, 0))(V3D(0, 0, 1)) + .convert_to_container>(), + list_of(2)(3)(4), list_of(5)(6)(7), list_of(8)(9)(10), + HKL, "foo", 1); + + PeakShapeEllipsoid b(list_of(V3D(0, 0, 0))(V3D(0, 1, 0))(V3D(0, 0, 1)) + .convert_to_container>(), + list_of(1)(3)(4), list_of(1)(6)(7), list_of(8)(9)(10), + QLab, "bar", 2); + + b = a; + + TS_ASSERT_EQUALS(a.abcRadii(), b.abcRadii()); + TS_ASSERT_EQUALS(a.abcRadiiBackgroundInner(), b.abcRadiiBackgroundInner()); + TS_ASSERT_EQUALS(a.abcRadiiBackgroundOuter(), b.abcRadiiBackgroundOuter()); + + TS_ASSERT_EQUALS(a.frame(), b.frame()); + TS_ASSERT_EQUALS(a.algorithmName(), b.algorithmName()); + TS_ASSERT_EQUALS(a.algorithmVersion(), b.algorithmVersion()); + } + + void test_shape_name() { + + const double radius = 1; + const SpecialCoordinateSystem frame = HKL; + + // Construct it. + PeakShapeEllipsoid shape(list_of(V3D(1, 0, 0))(V3D(0, 1, 0))(V3D(0, 0, 1)) + .convert_to_container>(), + list_of(2)(3)(4), list_of(5)(6)(7), + list_of(8)(9)(10), HKL, "foo", 1); + + TS_ASSERT_EQUALS("ellipsoid", shape.shapeName()); + } + + void test_toJSON() { + + auto directions = list_of(V3D(1, 0, 0))(V3D(0, 1, 0))(V3D(0, 0, 1)) + .convert_to_container>(); + const MantidVec abcRadii = list_of(2)(3)(4); + const MantidVec abcInnerRadii = list_of(5)(6)(7); + const MantidVec abcOuterRadii = list_of(8)(9)(10); + const SpecialCoordinateSystem frame = HKL; + const std::string algorithmName = "foo"; + const int algorithmVersion = 3; + + // Construct it. + PeakShapeEllipsoid shape(directions, abcRadii, abcInnerRadii, abcOuterRadii, + frame, algorithmName, algorithmVersion); + + const std::string json = shape.toJSON(); + + Json::Reader reader; + Json::Value output; + TSM_ASSERT("Should parse as JSON", reader.parse(json, output)); + + TS_ASSERT_EQUALS(directions[0].toString(), output["direction0"].asString()); + TS_ASSERT_EQUALS(directions[1].toString(), output["direction1"].asString()); + TS_ASSERT_EQUALS(directions[2].toString(), output["direction2"].asString()); + TS_ASSERT_EQUALS(algorithmName, output["algorithm_name"].asString()); + TS_ASSERT_EQUALS(algorithmVersion, output["algorithm_version"].asInt()); + TS_ASSERT_EQUALS(frame, output["frame"].asInt()); + TS_ASSERT_EQUALS(abcRadii[0], output["radius0"].asDouble()); + TS_ASSERT_EQUALS(abcRadii[1], output["radius1"].asDouble()); + TS_ASSERT_EQUALS(abcRadii[2], output["radius2"].asDouble()); + TS_ASSERT_EQUALS(abcOuterRadii[0], output["background_outer_radius0"].asDouble()); + TS_ASSERT_EQUALS(abcOuterRadii[1], output["background_outer_radius1"].asDouble()); + TS_ASSERT_EQUALS(abcOuterRadii[2], output["background_outer_radius2"].asDouble()); + + } + + + +}; + +#endif /* MANTID_DATAOBJECTS_PEAKSHAPEELLIPSOIDTEST_H_ */