Skip to content

Commit

Permalink
refs #6279. ConcretePeaksPresenter chooses factory.
Browse files Browse the repository at this point in the history
Redesign so that the ConcretePeaksPresenter uses a different PeakOverlayViewFactory if the PeaksWorkspace has not been integrated. This used to just throw in the past.
  • Loading branch information
OwenArnold committed Dec 11, 2012
1 parent 884c03b commit 373691b
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace MantidQt
class DLLExport ConcretePeaksPresenter : public PeaksPresenter
{
public:
ConcretePeaksPresenter(boost::shared_ptr<PeakOverlayViewFactory> viewFactory, boost::shared_ptr<Mantid::API::IPeaksWorkspace> peaksWS, boost::shared_ptr<PeakTransformFactory> transformFactory);
ConcretePeaksPresenter(boost::shared_ptr<PeakOverlayViewFactory> nonIntegratedViewFactory, boost::shared_ptr<PeakOverlayViewFactory> integratedViewFactory, boost::shared_ptr<Mantid::API::IPeaksWorkspace> peaksWS, boost::shared_ptr<PeakTransformFactory> transformFactory);
virtual ~ConcretePeaksPresenter();
virtual void update();
virtual void updateWithSlicePoint(const double& slicePoint);
Expand Down
32 changes: 22 additions & 10 deletions Code/Mantid/MantidQt/SliceViewer/src/ConcretePeaksPresenter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,42 @@ namespace SliceViewer
2) Then iterate over the MODEL and use it to construct VIEWs via the factory.
3) A collection of views is stored internally
@param viewFactory : View Factory (THE VIEW via factory)
@param nonIntegratedViewFactory : View Factory (THE VIEW via factory)
@param integratedViewFactory : View Factory (THE VIEW via factory)
@param peaksWS : IPeaksWorkspace to visualise (THE MODEL)
@param peaksTransform : Peak Transformation Factory. This is about interpreting the MODEL.
*/
ConcretePeaksPresenter::ConcretePeaksPresenter(PeakOverlayViewFactory_sptr viewFactory, Mantid::API::IPeaksWorkspace_sptr peaksWS, PeakTransformFactory_sptr transformFactory) : m_viewPeaks(peaksWS->getNumberPeaks())
, m_viewFactory(viewFactory), m_transformFactory(transformFactory), m_transform(transformFactory->createDefaultTransform()), m_slicePoint(0)
ConcretePeaksPresenter::ConcretePeaksPresenter(PeakOverlayViewFactory_sptr nonIntegratedViewFactory, PeakOverlayViewFactory_sptr integratedViewFactory, Mantid::API::IPeaksWorkspace_sptr peaksWS, PeakTransformFactory_sptr transformFactory) : m_viewPeaks(peaksWS->getNumberPeaks())
, m_viewFactory(integratedViewFactory), m_transformFactory(transformFactory), m_transform(transformFactory->createDefaultTransform()), m_slicePoint(0)
{
if(viewFactory == NULL)
if(integratedViewFactory == NULL)
{
throw std::invalid_argument("PeakOverlayViewFactory is null");
throw std::invalid_argument("Integrated PeakOverlayViewFactory is null");
}
if(nonIntegratedViewFactory == NULL)
{
throw std::invalid_argument("NonIntegrated PeakOverlayViewFactory is null");
}
if(peaksWS == NULL)
{
throw std::invalid_argument("PeaksWorkspace is null");
}
if(!peaksWS->hasIntegratedPeaks())

double peakIntegrationRadius = 0;
if(peaksWS->hasIntegratedPeaks())
{
peakIntegrationRadius = boost::lexical_cast<double>(peaksWS->run().getProperty("PeakRadius")->value());
}
else
{
throw std::invalid_argument("PeaksWorkspace does not contain integrated peaks."); // We might consider drawing these in the future anyway.
// Swap the view factory. We are not plotting integrated peaks now.
m_viewFactory.swap(nonIntegratedViewFactory);
}
m_viewFactory->setRadius(peakIntegrationRadius);

const bool transformSucceeded = this->configureMappingTransform();
// Extract the integration radius from the workspace.
const double peakIntegrationRadius = boost::lexical_cast<double>(peaksWS->run().getProperty("PeakRadius")->value());
viewFactory->setRadius(peakIntegrationRadius);

// Make and register each peak widget.
for(int i = 0; i < peaksWS->getNumberPeaks(); ++i)
{
const Mantid::API::IPeak& peak = peaksWS->getPeak(i);
Expand Down
6 changes: 4 additions & 2 deletions Code/Mantid/MantidQt/SliceViewer/src/SliceViewer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2180,10 +2180,12 @@ void SliceViewer::peakOverlay_toggled(bool checked)
for(int i = 0; i < list.size(); ++i)
{
IPeaksWorkspace_sptr peaksWS = AnalysisDataService::Instance().retrieveWS<IPeaksWorkspace>(list[i].toStdString());
PeakOverlayViewFactory_sptr viewFactory = boost::make_shared<PeakOverlayFactory>(m_plot, m_plot->canvas(), m_peaksPresenter->size());
const int numberOfChildPresenters = m_peaksPresenter->size();
PeakOverlayViewFactory_sptr viewFactoryIntegratedPeaks = boost::make_shared<PeakOverlayFactory>(m_plot, m_plot->canvas(), numberOfChildPresenters);
PeakOverlayViewFactory_sptr viewFactoryNonIntegratedPeaks = boost::make_shared<PeakOverlayFactory>(m_plot, m_plot->canvas(), numberOfChildPresenters);
try
{
m_peaksPresenter->addPeaksPresenter(boost::make_shared<ConcretePeaksPresenter>(viewFactory, peaksWS, transformFactory));
m_peaksPresenter->addPeaksPresenter(boost::make_shared<ConcretePeaksPresenter>(viewFactoryNonIntegratedPeaks, viewFactoryIntegratedPeaks, peaksWS, transformFactory));
}
catch(std::invalid_argument& e)
{
Expand Down
134 changes: 90 additions & 44 deletions Code/Mantid/MantidQt/SliceViewer/test/ConcretePeaksPresenterTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,55 +33,49 @@ class ConcretePeaksPresenterTest : public CxxTest::TestSuite

public:

void test_constructor_throws_if_view_factory_null()
void test_constructor_throws_if_either_view_factory_null()
{
PeakOverlayViewFactory* nullViewFactory = NULL; // View factory is null
PeakOverlayViewFactory_sptr viewFactory(nullViewFactory);
IPeaksWorkspace_sptr peaksWS = createPeaksWorkspace(1);

PeakTransform_sptr mockTransform(new MockPeakTransform);

auto pMockTransformFactory = new NiceMock<MockPeakTransformFactory>;
PeakTransformFactory_sptr peakTransformFactory(pMockTransformFactory);
EXPECT_CALL(*pMockTransformFactory, createDefaultTransform()).WillRepeatedly(Return(mockTransform));
PeakOverlayViewFactory* pNullViewFactory = NULL; // View factory is null
PeakOverlayViewFactory_sptr nullViewFactory(pNullViewFactory);

TS_ASSERT_THROWS(ConcretePeaksPresenter(viewFactory, peaksWS, peakTransformFactory), std::invalid_argument);
}

void test_constructor_throws_if_peaks_workspace_not_integrated()
{
auto mockViewFactory = new NiceMock<MockPeakOverlayFactory>;
PeakOverlayViewFactory_sptr viewFactory(mockViewFactory);
PeakOverlayViewFactory* pNormalViewFactory = new MockPeakOverlayFactory;
PeakOverlayViewFactory_sptr normalViewFactory(pNormalViewFactory);

IPeaksWorkspace_sptr peaksWS = WorkspaceCreationHelper::createPeaksWorkspace(1); // Peaks workspace is not integrated.
IPeaksWorkspace_sptr peaksWS = createPeaksWorkspace(1);

PeakTransform_sptr mockTransform(new MockPeakTransform);

auto pMockTransformFactory = new NiceMock<MockPeakTransformFactory>;
PeakTransformFactory_sptr peakTransformFactory(pMockTransformFactory);
EXPECT_CALL(*pMockTransformFactory, createDefaultTransform()).WillRepeatedly(Return(mockTransform));

TS_ASSERT_THROWS(ConcretePeaksPresenter(viewFactory, peaksWS, peakTransformFactory), std::invalid_argument);
TSM_ASSERT_THROWS("Non integrated view factory is null, should throw.", ConcretePeaksPresenter(nullViewFactory, normalViewFactory, peaksWS, peakTransformFactory), std::invalid_argument);
TSM_ASSERT_THROWS("Integrated view factory is null, should throw.", ConcretePeaksPresenter(normalViewFactory, nullViewFactory, peaksWS, peakTransformFactory), std::invalid_argument);
}

void test_construction()
{
// Create a widget factory mock
auto mockViewFactory = new NiceMock<MockPeakOverlayFactory>;
// Expected number of peaks to create
const size_t expectedNumberPeaks = 3;

// Set the expectation on the number of calls
const int expectedNumberPeaks = 10;
// Create a mock view object that will be returned by the mock factory.
// Peaks workspace IS INTEGRATED.
IPeaksWorkspace_sptr peaksWS = createPeaksWorkspace(expectedNumberPeaks);

// Mock View Factory Product
auto pMockView = new NiceMock<MockPeakOverlayView>;
auto mockView = boost::shared_ptr<NiceMock<MockPeakOverlayView> >(pMockView);
EXPECT_CALL(*mockViewFactory, setRadius(_)).Times(1);
EXPECT_CALL(*mockViewFactory, createView(_)).Times(expectedNumberPeaks).WillRepeatedly(Return(mockView));
EXPECT_CALL(*mockViewFactory, getPlotXLabel()).WillOnce(Return("H"));
EXPECT_CALL(*mockViewFactory, getPlotYLabel()).WillOnce(Return("K"));

// Create an input workspace.
Mantid::API::IPeaksWorkspace_sptr peaksWS = createPeaksWorkspace(expectedNumberPeaks);
// Mock View Factory for NON-integrated peaks. We expect that this will be used.
auto pMockNonIntegratedViewFactory = new MockPeakOverlayFactory;
PeakOverlayViewFactory_sptr mockNonIntegratedViewFactory(pMockNonIntegratedViewFactory);

// Mock View Factory for integrated peaks. We expect that this will never be used.
auto pMockIntegratedViewFactory = new MockPeakOverlayFactory;
PeakOverlayViewFactory_sptr mockIntegratedViewFactory(pMockIntegratedViewFactory);
EXPECT_CALL(*pMockIntegratedViewFactory, setRadius(_)).Times(1);
EXPECT_CALL(*pMockIntegratedViewFactory, createView(_)).Times(expectedNumberPeaks).WillRepeatedly(Return(mockView));
EXPECT_CALL(*pMockIntegratedViewFactory, getPlotXLabel()).WillOnce(Return("H"));
EXPECT_CALL(*pMockIntegratedViewFactory, getPlotYLabel()).WillOnce(Return("K"));

// Create a mock transform object.
auto pMockTransform = new NiceMock<MockPeakTransform>;
Expand All @@ -95,19 +89,71 @@ class ConcretePeaksPresenterTest : public CxxTest::TestSuite
EXPECT_CALL(*pMockTransformFactory, createDefaultTransform()).WillOnce(Return(mockTransform));
EXPECT_CALL(*pMockTransformFactory, createTransform(_,_)).WillOnce(Return(mockTransform));

// Construction should cause the widget factory to be used to generate peak overlay objects.
ConcretePeaksPresenter presenter(PeakOverlayViewFactory_sptr(mockViewFactory), peaksWS, peakTransformFactory);
// Construct the presenter.
ConcretePeaksPresenter presenter(mockNonIntegratedViewFactory, mockIntegratedViewFactory, peaksWS, peakTransformFactory);

TSM_ASSERT("MockViewFactory not used as expected.", Mock::VerifyAndClearExpectations(mockViewFactory));
TSM_ASSERT("Non-Integrated View Factory has not been used as expected", Mock::VerifyAndClearExpectations(pMockNonIntegratedViewFactory));
TSM_ASSERT("Integrated View Factory has not been used as expected", Mock::VerifyAndClearExpectations(pMockIntegratedViewFactory));
TSM_ASSERT("MockView not used as expected.", Mock::VerifyAndClearExpectations(pMockView));
TSM_ASSERT("MockTransformFactory not used as expected", Mock::VerifyAndClearExpectations(pMockTransformFactory));
TSM_ASSERT("MockTransform not used as expected", Mock::VerifyAndClearExpectations(pMockTransform));
}

void test_constructor_swaps_view_factory_if_peaks_workspace_not_integrated()
{
// Expected number of peaks to create
const size_t expectedNumberPeaks = 3;

// Peaks workspace IS NOT INTEGRATED.
IPeaksWorkspace_sptr peaksWS = WorkspaceCreationHelper::createPeaksWorkspace(expectedNumberPeaks);

// Mock View Factory Product
auto pMockView = new NiceMock<MockPeakOverlayView>;
auto mockView = boost::shared_ptr<NiceMock<MockPeakOverlayView> >(pMockView);

// Mock View Factory for NON-INTEGRATED peaks. We expect that this will be used.
auto pMockNonIntegratedViewFactory = new MockPeakOverlayFactory;
PeakOverlayViewFactory_sptr mockNonIntegratedViewFactory(pMockNonIntegratedViewFactory);
EXPECT_CALL(*pMockNonIntegratedViewFactory, setRadius(_)).Times(1);
EXPECT_CALL(*pMockNonIntegratedViewFactory, createView(_)).Times(expectedNumberPeaks).WillRepeatedly(Return(mockView));
EXPECT_CALL(*pMockNonIntegratedViewFactory, getPlotXLabel()).WillOnce(Return("H"));
EXPECT_CALL(*pMockNonIntegratedViewFactory, getPlotYLabel()).WillOnce(Return("K"));

// Mock View Factory for integrated peaks. We expect that this will never be used.
auto pMockIntegratedViewFactory = new MockPeakOverlayFactory;
PeakOverlayViewFactory_sptr mockIntegratedViewFactory(pMockIntegratedViewFactory);

// Mock Peaks transform
auto pMockTransform = new MockPeakTransform;
PeakTransform_sptr mockTransform(pMockTransform);
const int numberOfTimesCalled = static_cast<int>(peaksWS->rowCount());// Should be called for every peak i.e. row.
EXPECT_CALL(*pMockTransform, transformPeak(_)).Times(numberOfTimesCalled).WillRepeatedly(Return(V3D()));

// Mock Peak transform factory
auto pMockTransformFactory = new NiceMock<MockPeakTransformFactory>;
PeakTransformFactory_sptr peakTransformFactory(pMockTransformFactory);
EXPECT_CALL(*pMockTransformFactory, createDefaultTransform()).WillRepeatedly(Return(mockTransform));
EXPECT_CALL(*pMockTransformFactory, createDefaultTransform()).WillOnce(Return(mockTransform));
EXPECT_CALL(*pMockTransformFactory, createTransform(_,_)).WillOnce(Return(mockTransform));

// Construct the presenter.
ConcretePeaksPresenter presenter(mockNonIntegratedViewFactory, mockIntegratedViewFactory, peaksWS, peakTransformFactory);

TSM_ASSERT("Non-Integrated View Factory has not been used as expected", Mock::VerifyAndClearExpectations(pMockNonIntegratedViewFactory));
TSM_ASSERT("Integrated View Factory has not been used as expected", Mock::VerifyAndClearExpectations(pMockIntegratedViewFactory));
TSM_ASSERT("MockTransformFactory not used as expected", Mock::VerifyAndClearExpectations(pMockTransformFactory));
TSM_ASSERT("MockTransform not used as expected", Mock::VerifyAndClearExpectations(pMockTransform));
}

void test_update()
{
// Create a widget factory mock
auto mockViewFactory = new MockPeakOverlayFactory;
// Create a non-integrated widget factory mock.
auto pMockNonIntegratedPeakViewFactory = new MockPeakOverlayFactory;
PeakOverlayViewFactory_sptr mockNonIntegratedPeakViewFactory(pMockNonIntegratedPeakViewFactory);

// Create a spherical widget factory mock
auto pMockIntegratedPeakViewFactory = new MockPeakOverlayFactory;
PeakOverlayViewFactory_sptr mockIntegratedPeakViewFactory(pMockIntegratedPeakViewFactory);

// Set the expectation on the number of calls
const int expectedNumberPeaks = 10;
Expand All @@ -117,10 +163,10 @@ class ConcretePeaksPresenterTest : public CxxTest::TestSuite
EXPECT_CALL(*pMockView, updateView()).Times(expectedNumberPeaks);
auto mockView = boost::shared_ptr<NiceMock<MockPeakOverlayView> >(pMockView);

EXPECT_CALL(*mockViewFactory, setRadius(_)).Times(1);
EXPECT_CALL(*mockViewFactory, createView(_)).WillRepeatedly(Return(mockView));
EXPECT_CALL(*mockViewFactory, getPlotXLabel()).WillOnce(Return("H"));
EXPECT_CALL(*mockViewFactory, getPlotYLabel()).WillOnce(Return("K"));
EXPECT_CALL(*pMockIntegratedPeakViewFactory, setRadius(_)).Times(1);
EXPECT_CALL(*pMockIntegratedPeakViewFactory, createView(_)).WillRepeatedly(Return(mockView));
EXPECT_CALL(*pMockIntegratedPeakViewFactory, getPlotXLabel()).WillOnce(Return("H"));
EXPECT_CALL(*pMockIntegratedPeakViewFactory, getPlotYLabel()).WillOnce(Return("K"));
Mantid::API::IPeaksWorkspace_sptr peaksWS = createPeaksWorkspace(expectedNumberPeaks);

// Create a mock transform object.
Expand All @@ -135,7 +181,7 @@ class ConcretePeaksPresenterTest : public CxxTest::TestSuite
EXPECT_CALL(*pMockTransformFactory, createTransform(_,_)).WillOnce(Return(mockTransform));

// Construction should cause the widget factory to be used to generate peak overlay objects.
ConcretePeaksPresenter presenter(PeakOverlayViewFactory_sptr(mockViewFactory), peaksWS, peakTransformFactory);
ConcretePeaksPresenter presenter(mockNonIntegratedPeakViewFactory, mockIntegratedPeakViewFactory, peaksWS, peakTransformFactory);

// Updating should cause all of the held views to be updated too.
presenter.update();
Expand Down Expand Up @@ -175,7 +221,7 @@ class ConcretePeaksPresenterTest : public CxxTest::TestSuite
EXPECT_CALL(*pMockTransformFactory, createTransform(_,_)).WillOnce(Return(mockTransform));

// Construction should cause the widget factory to be used to generate peak overlay objects.
ConcretePeaksPresenter presenter(PeakOverlayViewFactory_sptr(mockViewFactory), peaksWS, peakTransformFactory);
ConcretePeaksPresenter presenter(boost::make_shared<MockPeakOverlayFactory>(), PeakOverlayViewFactory_sptr(mockViewFactory), peaksWS, peakTransformFactory);

// Updating should cause all of the held views to be updated too.
presenter.updateWithSlicePoint(slicePoint);
Expand Down Expand Up @@ -214,7 +260,7 @@ class ConcretePeaksPresenterTest : public CxxTest::TestSuite
EXPECT_CALL(*pMockTransformFactory, createTransform(_,_)).WillOnce(Return(mockTransform));

{
ConcretePeaksPresenter presenter(PeakOverlayViewFactory_sptr(mockViewFactory), peaksWS, peakTransformFactory);
ConcretePeaksPresenter presenter(boost::make_shared<MockPeakOverlayFactory>(), PeakOverlayViewFactory_sptr(mockViewFactory), peaksWS, peakTransformFactory);
} // Guaranteed destruction at this point. Destructor should trigger hide on all owned views.

TSM_ASSERT("MockView not used as expected.", Mock::VerifyAndClearExpectations(pMockView));
Expand Down Expand Up @@ -250,7 +296,7 @@ class ConcretePeaksPresenterTest : public CxxTest::TestSuite
EXPECT_CALL(*pMockTransformFactory, createDefaultTransform()).WillOnce(Return(mockTransform));
EXPECT_CALL(*pMockTransformFactory, createTransform(_,_)).WillRepeatedly(Throw(PeakTransformException())); // The actual transform will throw if a mix of Qx and Qy were used.

ConcretePeaksPresenter presenter(PeakOverlayViewFactory_sptr(mockViewFactory), peaksWS, peakTransformFactory);
ConcretePeaksPresenter presenter(boost::make_shared<MockPeakOverlayFactory>(), PeakOverlayViewFactory_sptr(mockViewFactory), peaksWS, peakTransformFactory);
TSM_ASSERT("MockView not used as expected.", Mock::VerifyAndClearExpectations(pMockView));
TSM_ASSERT("MockTransformFactory not used as expected", Mock::VerifyAndClearExpectations(pMockTransformFactory));
}
Expand Down

0 comments on commit 373691b

Please sign in to comment.