Skip to content

Commit

Permalink
refs #10904. Factory for elliptical peak shapes
Browse files Browse the repository at this point in the history
  • Loading branch information
OwenArnold committed Feb 6, 2015
1 parent 2387ce5 commit 78da658
Show file tree
Hide file tree
Showing 8 changed files with 266 additions and 26 deletions.
3 changes: 3 additions & 0 deletions Code/Mantid/Framework/DataObjects/CMakeLists.txt
Expand Up @@ -15,6 +15,7 @@ set ( SRC_FILES
src/PeakNoShapeFactory.cpp
src/PeakShapeBase.cpp
src/PeakShapeEllipsoid.cpp
src/PeakShapeEllipsoidFactory.cpp
src/PeakShapeSpherical.cpp
src/PeakShapeSphericalFactory.cpp
src/PeaksWorkspace.cpp
Expand Down Expand Up @@ -53,6 +54,7 @@ set ( INC_FILES
inc/MantidDataObjects/PeakShape.h
inc/MantidDataObjects/PeakShapeBase.h
inc/MantidDataObjects/PeakShapeEllipsoid.h
inc/MantidDataObjects/PeakShapeEllipsoidFactory.h
inc/MantidDataObjects/PeakShapeFactory.h
inc/MantidDataObjects/PeakShapeSpherical.h
inc/MantidDataObjects/PeakShapeSphericalFactory.h
Expand Down Expand Up @@ -81,6 +83,7 @@ set ( TEST_FILES
OffsetsWorkspaceTest.h
PeakColumnTest.h
PeakNoShapeFactoryTest.h
PeakShapeEllipsoidFactoryTest.h
PeakShapeEllipsoidTest.h
PeakShapeSphericalFactoryTest.h
PeakShapeSphericalTest.h
Expand Down
Expand Up @@ -64,6 +64,8 @@ namespace DataObjects
/// Get the peak shape
std::string shapeName() const;

static const std::string ellipsoidShapeName();

private:
/// principle axis
std::vector<Mantid::Kernel::V3D> m_directions;
Expand Down
@@ -0,0 +1,54 @@
#ifndef MANTID_DATAOBJECTS_PEAKSHAPEELLIPSOIDFACTORY_H_
#define MANTID_DATAOBJECTS_PEAKSHAPEELLIPSOIDFACTORY_H_

#include "MantidKernel/System.h"
#include "PeakShapeFactory.h"

namespace Mantid
{
namespace DataObjects
{

/** PeakShapeEllipsoidFactory : TODO: DESCRIPTION
Copyright &copy; 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 <http://www.gnu.org/licenses/>.
File change history is stored at: <https://github.com/mantidproject/mantid>
Code Documentation is available at: <http://doxygen.mantidproject.org>
*/
class DLLExport PeakShapeEllipsoidFactory : public PeakShapeFactory
{
public:
PeakShapeEllipsoidFactory();
virtual ~PeakShapeEllipsoidFactory();

// PeakShapeFactory interface

PeakShape *create(const std::string &source) const;
void setSuccessor(boost::shared_ptr<const PeakShapeFactory> successorFactory);

private:
/// Successor factory
PeakShapeFactory_const_sptr m_successor;
};


} // namespace DataObjects
} // namespace Mantid

#endif /* MANTID_DATAOBJECTS_PEAKSHAPEELLIPSOIDFACTORY_H_ */
7 changes: 6 additions & 1 deletion Code/Mantid/Framework/DataObjects/src/PeakShapeEllipsoid.cpp
Expand Up @@ -99,7 +99,12 @@ PeakShape *PeakShapeEllipsoid::clone() const {
return new PeakShapeEllipsoid(*this);
}

std::string PeakShapeEllipsoid::shapeName() const { return "ellipsoid"; }
std::string PeakShapeEllipsoid::shapeName() const { return PeakShapeEllipsoid::ellipsoidShapeName(); }

const std::string PeakShapeEllipsoid::ellipsoidShapeName()
{
return "ellipsoid";
}

} // namespace DataObjects
} // namespace Mantid
@@ -0,0 +1,98 @@
#include "MantidDataObjects/PeakShapeEllipsoidFactory.h"
#include "MantidDataObjects/PeakShapeEllipsoid.h"
#include "MantidAPI/SpecialCoordinateSystem.h"

#include <jsoncpp/json/json.h>
#include <stdexcept>

using namespace Mantid::Kernel;
using namespace Mantid::API;

namespace Mantid {
namespace DataObjects {

//----------------------------------------------------------------------------------------------
/** Constructor
*/
PeakShapeEllipsoidFactory::PeakShapeEllipsoidFactory() {}

//----------------------------------------------------------------------------------------------
/** Destructor
*/
PeakShapeEllipsoidFactory::~PeakShapeEllipsoidFactory() {}

/**
* @brief Create the PeakShape
* @param source : source JSON
* @return PeakShape via this factory or it's successors
*/
PeakShape *PeakShapeEllipsoidFactory::create(const std::string &source) const {
Json::Reader reader;
Json::Value root;
PeakShape *product = NULL;
if (reader.parse(source, root)) {
const std::string shape = root["shape"].asString();
if (shape == PeakShapeEllipsoid::ellipsoidShapeName()) {

const std::string algorithmName(root["algorithm_name"].asString());
const int algorithmVersion(root["algorithm_version"].asInt());
const SpecialCoordinateSystem frame(
static_cast<SpecialCoordinateSystem>(root["frame"].asInt()));
std::vector<double> abcRadii, abcRadiiBackgroundInner,
abcRadiiBackgroundOuter;
abcRadii.push_back(root["radius0"].asDouble());
abcRadii.push_back(root["radius1"].asDouble());
abcRadii.push_back(root["radius2"].asDouble());
abcRadiiBackgroundInner.push_back(
root["background_inner_radius0"].asDouble());
abcRadiiBackgroundInner.push_back(
root["background_inner_radius1"].asDouble());
abcRadiiBackgroundInner.push_back(
root["background_inner_radius2"].asDouble());
abcRadiiBackgroundOuter.push_back(
root["background_outer_radius0"].asDouble());
abcRadiiBackgroundOuter.push_back(
root["background_outer_radius1"].asDouble());
abcRadiiBackgroundOuter.push_back(
root["background_outer_radius2"].asDouble());

std::vector<V3D> directions(3);
directions[0].fromString(root["direction0"].asString());
directions[1].fromString(root["direction1"].asString());
directions[2].fromString(root["direction2"].asString());

product = new PeakShapeEllipsoid(
directions, abcRadii, abcRadiiBackgroundInner,
abcRadiiBackgroundOuter, frame, algorithmName, algorithmVersion);

} else {
if (m_successor) {
product = m_successor->create(source);
} else {
throw std::invalid_argument("PeakShapeSphericalFactory:: No successor "
"factory able to process : " +
source);
}
}

} else {

throw std::invalid_argument("PeakShapeSphericalFactory:: Source JSON for "
"the peak shape is not valid: " +
source);
}
return product;
}

/**
* @brief Set successor
* @param successorFactory : successor
*/
void PeakShapeEllipsoidFactory::setSuccessor(
boost::shared_ptr<const PeakShapeFactory> successorFactory) {
this->m_successor = successorFactory;
}


} // namespace DataObjects
} // namespace Mantid
Expand Up @@ -44,8 +44,9 @@ PeakShape *PeakShapeSphericalFactory::create(const std::string &source) const {
root["background_outer_radius"].asDouble());
const double backgroundInnerRadius(
root["background_inner_radius"].asDouble());
product = new PeakShapeSpherical(radius, backgroundInnerRadius, backgroundOuterRadius, frame, algorithmName,
algorithmVersion);
product = new PeakShapeSpherical(radius, backgroundInnerRadius,
backgroundOuterRadius, frame,
algorithmName, algorithmVersion);
}

else {
Expand All @@ -64,17 +65,17 @@ PeakShape *PeakShapeSphericalFactory::create(const std::string &source) const {
}

} else {
if (m_successor) {
product = m_successor->create(source);
} else {
throw std::invalid_argument("PeakShapeSphericalFactory:: Source JSON for "
"the peak shape is not valid: " +
source);
}
throw std::invalid_argument("PeakShapeSphericalFactory:: Source JSON for "
"the peak shape is not valid: " +
source);
}
return product;
}

/**
* @brief Set successor
* @param successorFactory : successor
*/
void PeakShapeSphericalFactory::setSuccessor(
PeakShapeFactory_const_sptr successorFactory) {
m_successor = successorFactory;
Expand Down
@@ -0,0 +1,93 @@
#ifndef MANTID_DATAOBJECTS_PEAKSHAPEELLIPSOIDFACTORYTEST_H_
#define MANTID_DATAOBJECTS_PEAKSHAPEELLIPSOIDFACTORYTEST_H_

#ifdef _WIN32
#pragma warning(disable : 4251)
#endif

#include <cxxtest/TestSuite.h>
#include <gmock/gmock.h>
#include <jsoncpp/json/json.h>
#include <boost/assign/list_of.hpp>

#include "MantidDataObjects/PeakShapeEllipsoid.h"
#include "MantidKernel/VMD.h"
#include "MantidKernel/cow_ptr.h"
#include "MantidAPI/SpecialCoordinateSystem.h"
#include "MockObjects.h"

#include "MantidDataObjects/PeakShapeEllipsoidFactory.h"

using namespace Mantid;
using namespace Mantid::DataObjects;
using namespace Mantid::Kernel;
using namespace Mantid::API;
using namespace boost::assign;

class PeakShapeEllipsoidFactoryTest : 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 PeakShapeEllipsoidFactoryTest *createSuite() {
return new PeakShapeEllipsoidFactoryTest();
}
static void destroySuite(PeakShapeEllipsoidFactoryTest *suite) {
delete suite;
}

void test_invalid_json_with_no_successor() {
PeakShapeEllipsoidFactory factory;
TS_ASSERT_THROWS(factory.create(""), std::invalid_argument &);
}

void test_use_successor_when_different_shape_found() {
using namespace testing;

// We expect it to try to use the deletate factory. If it cannot process the
// json.
MockPeakShapeFactory *delegate = new MockPeakShapeFactory;
EXPECT_CALL(*delegate, create(_)).Times(1);

PeakShapeEllipsoidFactory factory;
factory.setSuccessor(PeakShapeFactory_const_sptr(delegate));

// Minimal valid JSON for describing the shape.
Json::Value root;
root["shape"] = "square";
Json::StyledWriter writer;
const std::string str_json = writer.write(root);

factory.create(str_json);

TS_ASSERT(Mock::VerifyAndClearExpectations(delegate));
}

void test_create() {

auto directions = list_of(V3D(1, 0, 0))(V3D(0, 1, 0))(V3D(0, 0, 1))
.convert_to_container<std::vector<V3D>>();
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;

// Make a source shape
PeakShapeEllipsoid sourceShape(directions, abcRadii, abcInnerRadii,
abcOuterRadii, frame, algorithmName,
algorithmVersion);

PeakShapeEllipsoidFactory factory;
PeakShape *productShape = factory.create(sourceShape.toJSON());

PeakShapeEllipsoid *ellipsoidShapeProduct =
dynamic_cast<PeakShapeEllipsoid *>(productShape);
TS_ASSERT(ellipsoidShapeProduct);

TS_ASSERT_EQUALS(sourceShape, *ellipsoidShapeProduct);
delete productShape;
}
};

#endif /* MANTID_DATAOBJECTS_PEAKSHAPEELLIPSOIDFACTORYTEST_H_ */
Expand Up @@ -35,22 +35,6 @@ class PeakShapeSphericalFactoryTest : public CxxTest::TestSuite {
TS_ASSERT_THROWS(factory.create(""), std::invalid_argument &);
}

void test_invalid_json_with_successor() {
using namespace testing;

// We expect it to try to use the deletate factory. If it cannot process the
// json.
MockPeakShapeFactory *delegate = new MockPeakShapeFactory;
EXPECT_CALL(*delegate, create(_)).Times(1);

PeakShapeSphericalFactory factory;
factory.setSuccessor(PeakShapeFactory_const_sptr(delegate));
// Run create with empty JSON.
factory.create("");

TS_ASSERT(Mock::VerifyAndClearExpectations(delegate));
}

void test_use_successor_when_different_shape_found() {
using namespace testing;

Expand Down

0 comments on commit 78da658

Please sign in to comment.