Skip to content

Commit

Permalink
Initial, very simple, 'fake data' listener. Re #4812.
Browse files Browse the repository at this point in the history
  • Loading branch information
RussellTaylor committed Feb 17, 2012
1 parent b700137 commit a81f2b1
Show file tree
Hide file tree
Showing 5 changed files with 216 additions and 1 deletion.
3 changes: 2 additions & 1 deletion Code/Mantid/Framework/API/inc/MantidAPI/ILiveListener.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ namespace Mantid

/** Get the data that's been buffered since the last call to this method
* (or since connect() was called).
* The implementation should reset its internal buffer when this method is called.
* The implementation should reset its internal buffer when this method is called
* - the returned workspace is for the caller to do with as they wish.
* @return A pointer to the workspace containing the buffered data.
* TODO: Consider whether there should be a default implementation of this method
*/
Expand Down
3 changes: 3 additions & 0 deletions Code/Mantid/Framework/DataHandling/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ set ( SRC_FILES
src/CreateSampleShape.cpp
src/DefineGaugeVolume.cpp
src/DeleteTableRows.cpp
src/FakeEventDataListener.cpp
src/FindDetectorsInShape.cpp
src/FindDetectorsPar.cpp
src/GetMaskedDetectors.cpp
Expand Down Expand Up @@ -122,6 +123,7 @@ set ( INC_FILES
inc/MantidDataHandling/CreateSampleShape.h
inc/MantidDataHandling/DefineGaugeVolume.h
inc/MantidDataHandling/DeleteTableRows.h
inc/MantidDataHandling/FakeEventDataListener.h
inc/MantidDataHandling/FindDetectorsInShape.h
inc/MantidDataHandling/FindDetectorsPar.h
inc/MantidDataHandling/GetMaskedDetectors.h
Expand Down Expand Up @@ -235,6 +237,7 @@ set ( TEST_FILES
test/CreateSampleShapeTest.h
test/DefineGaugeVolumeTest.h
test/DeleteTableRowsTest.h
test/FakeEventDataListenerTest.h
test/FindDetectorsInShapeTest.h
test/FindDetectorsParTest.h
test/GetMaskedDetectorsTest.h
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#ifndef MANTID_DATAHANDLING_FAKEEVENTDATALISTENER_H_
#define MANTID_DATAHANDLING_FAKEEVENTDATALISTENER_H_

//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidAPI/ILiveListener.h"
#include "MantidDataObjects/EventWorkspace.h"
#include "MantidKernel/RandomNumberGenerator.h"

namespace Mantid
{
namespace DataHandling
{
/** An implementation of ILiveListener for testing purposes that fills its event
workspace buffer with randomly generated events.
Copyright © 2012 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory
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/>.
*/
class FakeEventDataListener : public API::ILiveListener
{
public:
FakeEventDataListener();
~FakeEventDataListener();

std::string name() const { return "FakeEventDataListener"; }
bool supportsHistory() const { return false; } // For the time being at least
bool buffersEvents() const { return true; }

bool connect(const Poco::Net::SocketAddress& address);
void start(Kernel::DateAndTime startTime = Kernel::DateAndTime());
boost::shared_ptr<API::MatrixWorkspace> extractData();

bool isConnected();

private:
DataObjects::EventWorkspace_sptr m_buffer;
Kernel::RandomNumberGenerator * m_rand;
};

} // namespace DataHandling
} // namespace Mantid

#endif /* MANTID_DATAHANDLING_FAKEEVENTDATALISTENER_H_ */
80 changes: 80 additions & 0 deletions Code/Mantid/Framework/DataHandling/src/FakeEventDataListener.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#include "MantidDataHandling/FakeEventDataListener.h"
#include "MantidAPI/LiveListenerFactory.h"
#include "MantidAPI/WorkspaceFactory.h"
#include "MantidKernel/MersenneTwister.h"

using namespace Mantid::API;

namespace Mantid
{
namespace DataHandling
{
DECLARE_LISTENER(FakeEventDataListener)

/// Constructor
FakeEventDataListener::FakeEventDataListener() : ILiveListener(),
m_buffer(), m_rand(new Kernel::MersenneTwister)
{
}

/// Destructor
FakeEventDataListener::~FakeEventDataListener()
{
delete m_rand;
}

bool FakeEventDataListener::connect(const Poco::Net::SocketAddress&)
{
// Do nothing for now. Later, put in stuff to help test failure modes.
return true;
}

bool FakeEventDataListener::isConnected()
{
return true; // For the time being at least
}

void FakeEventDataListener::start(Kernel::DateAndTime /*startTime*/) // Ignore the start time for now at least
{
// Set up the workspace buffer (probably won't know its dimensions before this point)
// 2 spectra event workspace for now. Will make larger later.
// No instrument, meta-data etc - will need to figure out who's responsible for that
m_buffer = boost::dynamic_pointer_cast<DataObjects::EventWorkspace>(
WorkspaceFactory::Instance().create("EventWorkspace", 2, 2, 1) );
// Set a sample tof range
m_rand->setRange(40000,60000);
m_rand->setSeed(Kernel::DateAndTime::get_current_time().total_nanoseconds());

return;
}

boost::shared_ptr<MatrixWorkspace> FakeEventDataListener::extractData()
{
// TODO: Add protection against calling this before start() has been called

/* For the very first try, just add a small number of uniformly distributed events.
* Next: 1. Add some kind of distribution
* 2. Continuously add events in a separate thread once start has been called
*/
using namespace DataObjects;
EventList & el1 = m_buffer->getEventList(0);
EventList & el2 = m_buffer->getEventList(1);
for (int i = 0; i < 100; ++i)
{
el1.addEventQuickly(TofEvent(m_rand->next()));
el2.addEventQuickly(TofEvent(m_rand->next()));
}

// Copy the workspace pointer to a temporary variable
EventWorkspace_sptr extracted = m_buffer;
// Create a new, empty workspace of the same dimensions and assign to the buffer variable
// TODO: Think about whether creating a new workspace at this point is scalable
m_buffer = boost::dynamic_pointer_cast<EventWorkspace>(
WorkspaceFactory::Instance().create("EventWorkspace",2,2,1) );
// Will need an 'initializeFromParent' here later on....

return extracted;
}

} // namespace Mantid
} // namespace DataHandling
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#ifndef MANTID_DATAHANDLING_FAKEEVENTDATALISTENERTEST_H_
#define MANTID_DATAHANDLING_FAKEEVENTDATALISTENERTEST_H_

#include <cxxtest/TestSuite.h>
#include "MantidAPI/LiveListenerFactory.h"
#include "MantidDataObjects/EventWorkspace.h"

using namespace Mantid::API;

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

FakeEventDataListenerTest()
{
// Create the listener. Remember: this will call connect()
fakel = LiveListenerFactory::Instance().create("FakeEventDataListener");
}

void testProperties()
{
TS_ASSERT( fakel )
TS_ASSERT_EQUALS( fakel->name(), "FakeEventDataListener")
TS_ASSERT( ! fakel->supportsHistory() )
TS_ASSERT( fakel->buffersEvents() )
TS_ASSERT( fakel->isConnected() )
}

void testStart()
{
// Nothing much to test just yet
TS_ASSERT_THROWS_NOTHING( fakel->start(0) )
}

void testExtractData()
{
using namespace Mantid::DataObjects;
MatrixWorkspace_const_sptr buffer;
TS_ASSERT_THROWS_NOTHING( buffer = fakel->extractData())
// Check this is the only surviving reference to it
TS_ASSERT_EQUALS( buffer.use_count(), 1 )
// Check it's an event workspace
EventWorkspace_const_sptr evbuf = boost::dynamic_pointer_cast<const EventWorkspace>(buffer);
TS_ASSERT( evbuf )
// Check the events are there
TS_ASSERT_EQUALS( evbuf->getNumberHistograms(), 2 )
TS_ASSERT_EQUALS( evbuf->getNumberEvents(), 200 )

// Call it again, and check things again
TS_ASSERT_THROWS_NOTHING( buffer = fakel->extractData())
// Check this is the only surviving reference to it
TS_ASSERT_EQUALS( buffer.use_count(), 1 )
// Check it's a different workspace to last time
TS_ASSERT_DIFFERS( buffer.get(), evbuf.get() )
// Check it's an event workspace
evbuf = boost::dynamic_pointer_cast<const EventWorkspace>(buffer);
TS_ASSERT( evbuf )
// Check the events are there
TS_ASSERT_EQUALS( evbuf->getNumberHistograms(), 2 )
TS_ASSERT_EQUALS( evbuf->getNumberEvents(), 200 )
}

private:
boost::shared_ptr<ILiveListener> fakel;
};


#endif /* MANTID_DATAHANDLING_FAKEEVENTDATALISTENERTEST_H_ */

0 comments on commit a81f2b1

Please sign in to comment.