Skip to content

Commit

Permalink
Re #12687 clone() implementation for MatrixWorkspaces (not Event).
Browse files Browse the repository at this point in the history
  • Loading branch information
SimonHeybrock committed Jul 2, 2015
1 parent 864a6ed commit 38eb3ee
Show file tree
Hide file tree
Showing 18 changed files with 201 additions and 35 deletions.
2 changes: 1 addition & 1 deletion Code/Mantid/Framework/API/inc/MantidAPI/IMaskWorkspace.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class DLLExport IMaskWorkspace {

protected:
/// Protected copy constructor. May be used by childs for cloning.
IMaskWorkspace(const IMaskWorkspace &other);
IMaskWorkspace(const IMaskWorkspace &other) { (void)other; }
/// Protected copy assignment operator. Assignment not implemented.
IMaskWorkspace &operator=(const IMaskWorkspace &other);
};
Expand Down
31 changes: 2 additions & 29 deletions Code/Mantid/Framework/Algorithms/src/CloneWorkspace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,35 +56,8 @@ void CloneWorkspace::exec() {
setProperty("OutputWorkspace",
boost::dynamic_pointer_cast<Workspace>(outputWS));
} else if (inputMatrix) {
// Create the output workspace. This will copy many aspects fron the input
// one.
MatrixWorkspace_sptr outputWorkspace =
WorkspaceFactory::Instance().create(inputMatrix);

// ...but not the data, so do that here.

const int64_t numHists =
static_cast<int64_t>(inputMatrix->getNumberHistograms());
Progress prog(this, 0.0, 1.0, numHists);

PARALLEL_FOR2(inputMatrix, outputWorkspace)
for (int64_t i = 0; i < int64_t(numHists); ++i) {
PARALLEL_START_INTERUPT_REGION

outputWorkspace->setX(i, inputMatrix->refX(i));
outputWorkspace->dataY(i) = inputMatrix->readY(i);
outputWorkspace->dataE(i) = inputMatrix->readE(i);
// Be sure to not break sharing between Dx vectors by assigning pointers
outputWorkspace->getSpectrum(i)
->setDx(inputMatrix->getSpectrum(i)->ptrDx());

prog.report();

PARALLEL_END_INTERUPT_REGION
}
PARALLEL_CHECK_INTERUPT_REGION
setProperty("OutputWorkspace",
boost::dynamic_pointer_cast<Workspace>(outputWorkspace));
Workspace_sptr outputWS(inputWorkspace->clone().release());
setProperty("OutputWorkspace", outputWS);
} else if (inputMD) {
// Call the CloneMDWorkspace algo to handle MDEventWorkspace
IAlgorithm_sptr alg =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ class DLLExport GroupingWorkspace : public SpecialWorkspace2D {
GroupingWorkspace(size_t numvectors);
~GroupingWorkspace();

/// Returns a clone of the workspace
std::unique_ptr<GroupingWorkspace> clone() const {
return std::unique_ptr<GroupingWorkspace>(doClone());
}

/** Gets the name of the workspace type
@return Standard string name */
virtual const std::string id() const { return "GroupingWorkspace"; }
Expand All @@ -36,9 +41,15 @@ class DLLExport GroupingWorkspace : public SpecialWorkspace2D {

protected:
/// Protected copy constructor. May be used by childs for cloning.
GroupingWorkspace(const GroupingWorkspace &other);
GroupingWorkspace(const GroupingWorkspace &other)
: SpecialWorkspace2D(other) {}
/// Protected copy assignment operator. Assignment not implemented.
GroupingWorkspace &operator=(const GroupingWorkspace &other);

private:
virtual GroupingWorkspace *doClone() const {
return new GroupingWorkspace(*this);
}
};

/// shared pointer to the GroupingWorkspace class
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ class DLLExport MaskWorkspace : public SpecialWorkspace2D,
MaskWorkspace(const API::MatrixWorkspace_const_sptr parent);
~MaskWorkspace();

/// Returns a clone of the workspace
std::unique_ptr<MaskWorkspace> clone() const {
return std::unique_ptr<MaskWorkspace>(doClone());
}

bool isMasked(const detid_t detectorID) const;
bool isMasked(const std::set<detid_t> &detectorIDs) const;
bool isMaskedIndex(const std::size_t wkspIndex) const;
Expand All @@ -46,6 +51,8 @@ class DLLExport MaskWorkspace : public SpecialWorkspace2D,
virtual const std::string toString() const;

private:
virtual MaskWorkspace *doClone() const { return new MaskWorkspace(*this); }

/// Clear original incorrect mask
void clearMask();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,25 @@ class DLLExport OffsetsWorkspace : public SpecialWorkspace2D {
OffsetsWorkspace(Geometry::Instrument_const_sptr inst);
~OffsetsWorkspace();

/// Returns a clone of the workspace
std::unique_ptr<OffsetsWorkspace> clone() const {
return std::unique_ptr<OffsetsWorkspace>(doClone());
}

/** Gets the name of the workspace type
@return Standard string name */
virtual const std::string id() const { return "OffsetsWorkspace"; }

protected:
/// Protected copy constructor. May be used by childs for cloning.
OffsetsWorkspace(const OffsetsWorkspace &other);
OffsetsWorkspace(const OffsetsWorkspace &other) : SpecialWorkspace2D(other) {}
/// Protected copy assignment operator. Assignment not implemented.
OffsetsWorkspace &operator=(const OffsetsWorkspace &other);

private:
virtual OffsetsWorkspace *doClone() const {
return new OffsetsWorkspace(*this);
}
};

/// shared pointer to the OffsetsWorkspace class
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ class DLLExport RebinnedOutput : public Workspace2D {
/// Class destructor.
virtual ~RebinnedOutput();

/// Returns a clone of the workspace
std::unique_ptr<RebinnedOutput> clone() const {
return std::unique_ptr<RebinnedOutput>(doClone());
}

/// Get the workspace ID.
virtual const std::string id() const;

Expand Down Expand Up @@ -75,6 +80,9 @@ class DLLExport RebinnedOutput : public Workspace2D {

/// A vector that holds the 1D vectors for the fractional area.
std::vector<MantidVec> fracArea;

private:
virtual RebinnedOutput *doClone() const { return new RebinnedOutput(*this); }
};

/// shared pointer to the RebinnedOutput class
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ class DLLExport SpecialWorkspace2D : public Workspace2D {
SpecialWorkspace2D(API::MatrixWorkspace_const_sptr parent);
~SpecialWorkspace2D();

/// Returns a clone of the workspace
std::unique_ptr<SpecialWorkspace2D> clone() const {
return std::unique_ptr<SpecialWorkspace2D>(doClone());
}

/** Gets the name of the workspace type
@return Standard string name */
virtual const std::string id() const { return "SpecialWorkspace2D"; }
Expand All @@ -52,6 +57,9 @@ class DLLExport SpecialWorkspace2D : public Workspace2D {
virtual void copyFrom(boost::shared_ptr<const SpecialWorkspace2D> sourcews);

private:
virtual SpecialWorkspace2D *doClone() const {
return new SpecialWorkspace2D(*this);
}
bool isCompatible(boost::shared_ptr<const SpecialWorkspace2D> ws);

protected:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,7 @@ class DLLExport Workspace2D : public API::MatrixWorkspace {
std::vector<Mantid::API::ISpectrum *> data;

private:
virtual Workspace2D *doClone() const {
throw std::runtime_error("Cloning of Workspace2D is not implemented.");
}
virtual Workspace2D *doClone() const { return new Workspace2D(*this); }

virtual std::size_t getHistogramNumberHelper() const;
};
Expand Down
3 changes: 3 additions & 0 deletions Code/Mantid/Framework/DataObjects/src/MaskWorkspace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ const double ERROR_VALUE = 0.;
*/
MaskWorkspace::MaskWorkspace() {}

MaskWorkspace::MaskWorkspace(const MaskWorkspace &other)
: SpecialWorkspace2D(other), IMaskWorkspace(other) {}

/**
* Constructor - with a given dimension.
* @param[in] numvectors Number of vectors/histograms for this workspace.
Expand Down
3 changes: 3 additions & 0 deletions Code/Mantid/Framework/DataObjects/src/RebinnedOutput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ DECLARE_WORKSPACE(RebinnedOutput)

RebinnedOutput::RebinnedOutput() : Workspace2D() {}

RebinnedOutput::RebinnedOutput(const RebinnedOutput &other)
: Workspace2D(other), fracArea(other.fracArea) {}

RebinnedOutput::~RebinnedOutput() {}

/**
Expand Down
3 changes: 3 additions & 0 deletions Code/Mantid/Framework/DataObjects/src/SpecialWorkspace2D.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ SpecialWorkspace2D::SpecialWorkspace2D(API::MatrixWorkspace_const_sptr parent) {
}
}

SpecialWorkspace2D::SpecialWorkspace2D(const SpecialWorkspace2D &other)
: Workspace2D(other), detID_to_WI(other.detID_to_WI) {}

//----------------------------------------------------------------------------------------------
/** Destructor
*/
Expand Down
13 changes: 13 additions & 0 deletions Code/Mantid/Framework/DataObjects/src/Workspace2D.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,19 @@ DECLARE_WORKSPACE(Workspace2D)
/// Constructor
Workspace2D::Workspace2D(): m_noVectors(0) {}

Workspace2D::Workspace2D(const Workspace2D &other)
: MatrixWorkspace(other), m_noVectors(other.m_noVectors),
m_monitorList(other.m_monitorList) {
data.resize(m_noVectors);

for (size_t i = 0; i < m_noVectors; ++i) {
// Careful: data holds pointers to ISpectrum, but they point to Histogram1D.
// There are copy constructors, but we would need a clone() function that is
// aware of the polymorphism. Use cast + copy constructor for now.
data[i] = new Histogram1D(*static_cast<Histogram1D *>(other.data[i]));
}
}

/// Destructor
Workspace2D::~Workspace2D() {
// Clear out the memory
Expand Down
33 changes: 33 additions & 0 deletions Code/Mantid/Framework/DataObjects/test/GroupingWorkspaceTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,39 @@ class GroupingWorkspaceTest : public CxxTest::TestSuite
TS_ASSERT_EQUALS( map[45], 5 );
}

void testClone() {
// As test_constructor_from_Instrument(), set on ws, get on clone.
// Fake instrument with 5*9 pixels with ID starting at 1
Instrument_sptr inst = ComponentCreationHelper::createTestInstrumentCylindrical(5);

GroupingWorkspace_sptr ws(new GroupingWorkspace(inst));
auto cloned = ws->clone();

TS_ASSERT_EQUALS( cloned->getNumberHistograms(), 45);
TS_ASSERT_EQUALS( cloned->blocksize(), 1);
TS_ASSERT_EQUALS( cloned->getInstrument()->getName(), "basic"); // Name of the test instrument
std::set<detid_t> dets = cloned->getSpectrum(0)->getDetectorIDs();
TS_ASSERT_EQUALS(dets.size(), 1);

// Set the group numbers
for (int group=0; group<5; group++)
for (int i=0; i<9; i++)
ws->dataY(group*9+i)[0] = double(group+1);
cloned = ws->clone();

// Get the map
std::map<detid_t,int> map;
int64_t ngroups;
cloned->makeDetectorIDToGroupMap(map, ngroups);

TS_ASSERT_EQUALS(ngroups, 5);

TS_ASSERT_EQUALS( map[1], 1 );
TS_ASSERT_EQUALS( map[9], 1 );
TS_ASSERT_EQUALS( map[10], 2 );
TS_ASSERT_EQUALS( map[45], 5 );
}


};

Expand Down
35 changes: 35 additions & 0 deletions Code/Mantid/Framework/DataObjects/test/MaskWorkspaceTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,41 @@ class MaskWorkspaceTest : public CxxTest::TestSuite
TS_ASSERT(maskWS.isMasked(0));
}

void testClone() {
// As test_mask_accessors(), set on ws, get on clone.
int pixels = 10;
int maskpixels = 25;

Mantid::Geometry::Instrument_sptr inst =
ComponentCreationHelper::createTestInstrumentRectangular2(1,pixels);
inst->setName("MaskWorkspaceTest_Instrument");

Mantid::DataObjects::MaskWorkspace maskWS(inst, false);
for (int i = 0; i < maskpixels; i++)
maskWS.setMasked(i); // mask the pixel

auto cloned = maskWS.clone();
TS_ASSERT_EQUALS(cloned->getNumberHistograms(), pixels*pixels);
TS_ASSERT_EQUALS(cloned->getNumberMasked(), maskpixels);
TS_ASSERT(cloned->isMasked(0));
TS_ASSERT_EQUALS(cloned->isMasked(maskpixels), false); // one past the masked ones

// unmask a pixel and check it
maskWS.setMasked(0, false);
cloned = maskWS.clone();
TS_ASSERT_EQUALS(cloned->isMasked(0), false);

// check of a group of pixels
std::set<Mantid::detid_t> detIds;
detIds.insert(0); // isn't masked
TS_ASSERT_EQUALS(cloned->isMasked(detIds), false);
detIds.insert(1); // is masked
TS_ASSERT_EQUALS(cloned->isMasked(detIds), false);
detIds.erase(0);
detIds.insert(2);
TS_ASSERT_EQUALS(cloned->isMasked(detIds), true);
}

void test_mask_accessors()
{
int pixels = 10;
Expand Down
6 changes: 6 additions & 0 deletions Code/Mantid/Framework/DataObjects/test/OffsetsWorkspaceTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <iomanip>

#include "MantidDataObjects/OffsetsWorkspace.h"
#include "MantidTestHelpers/ComponentCreationHelper.h"

using namespace Mantid::DataObjects;
using namespace Mantid::API;
Expand All @@ -20,7 +21,12 @@ class OffsetsWorkspaceTest : public CxxTest::TestSuite
{
}

void testClone() {
auto inst = ComponentCreationHelper::createTestInstrumentCylindrical(5);

OffsetsWorkspace ws(inst);
TS_ASSERT_THROWS_NOTHING(ws.clone());
}
};


Expand Down
15 changes: 15 additions & 0 deletions Code/Mantid/Framework/DataObjects/test/RebinnedOutputTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,21 @@ class RebinnedOutputTest : public CxxTest::TestSuite
ws = WorkspaceCreationHelper::CreateRebinnedOutputWorkspace();
}

void testClone() {
RebinnedOutput_sptr cloned(ws->clone().release());

// Swap ws with cloned pointer, such that we can reuse existing tests.
ws.swap(cloned);

// Run all other tests on ws.
testId();
testRepresentation();
testSetF();

// Undo swap, to avoid possible interferences.
ws.swap(cloned);
}

void testId()
{
TS_ASSERT_EQUALS( ws->id(), "RebinnedOutput" );
Expand Down
26 changes: 26 additions & 0 deletions Code/Mantid/Framework/DataObjects/test/SpecialWorkspace2DTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,32 @@ class SpecialWorkspace2DTest : public CxxTest::TestSuite
TS_ASSERT_EQUALS( ws->blocksize(), 1);
}

void testClone() {
// As test_setValue_getValue, set on ws, get on clone.
Instrument_sptr inst =
ComponentCreationHelper::createTestInstrumentCylindrical(5);
SpecialWorkspace2D_sptr ws(new SpecialWorkspace2D(inst));

auto cloned = ws->clone();
TS_ASSERT_DIFFERS(cloned->getValue(1), 12.3);
TS_ASSERT_THROWS_NOTHING(ws->setValue(1, 12.3));
cloned = ws->clone();
TS_ASSERT_DELTA(cloned->getValue(1), 12.3, 1e-6);
TS_ASSERT_THROWS_ANYTHING(ws->setValue(46, 789));
TS_ASSERT_THROWS_ANYTHING(ws->setValue(-1, 789));
cloned = ws->clone();
TS_ASSERT_THROWS_ANYTHING(cloned->getValue(47));
TS_ASSERT_THROWS_ANYTHING(cloned->getValue(-34));
TS_ASSERT_EQUALS(cloned->getValue(47, 5.0), 5.0);
TS_ASSERT_EQUALS(cloned->getValue(147, -12.0), -12.0);

// Some extra tests: 1. clone ws, 2. set on ws, 3. clone should differ.
cloned = ws->clone();
TS_ASSERT_DELTA(cloned->getValue(1), 12.3, 1e-6);
TS_ASSERT_THROWS_NOTHING(ws->setValue(1, 1.1));
TS_ASSERT_DIFFERS(cloned->getValue(1), 1.1);
}

void test_constructor_from_Instrument()
{
// Fake instrument with 5*9 pixels with ID starting at 1
Expand Down

0 comments on commit 38eb3ee

Please sign in to comment.