Skip to content

Commit

Permalink
Changes to LoadLiveData to handle workspace groups. Re #8226.
Browse files Browse the repository at this point in the history
  • Loading branch information
mantid-roman committed Feb 3, 2014
1 parent cbb0275 commit 9f677b2
Show file tree
Hide file tree
Showing 7 changed files with 386 additions and 20 deletions.
2 changes: 2 additions & 0 deletions Code/Mantid/Framework/ISISLiveData/src/FakeISISEventDAE.cpp
Expand Up @@ -79,11 +79,13 @@ class TestServerConnection: public Poco::Net::TCPServerConnection
{
Kernel::MersenneTwister tof(0,100.0,200.0);
Kernel::MersenneTwister spec(1234,0.0,static_cast<double>(m_nSpectra));
Kernel::MersenneTwister period(0,0.0,static_cast<double>(m_nPeriods));
for(;;)
{
Poco::Thread::sleep(m_Rate);
TCPStreamEventDataNeutron data;
data.head_n.nevents = m_nEvents;
data.head_n.period = static_cast<uint32_t>(period.nextValue());

socket().sendBytes(&data.head,(int)sizeof(data.head));
socket().sendBytes(&data.head_n,(int)sizeof(data.head_n));
Expand Down
Expand Up @@ -62,6 +62,7 @@ namespace LiveData
void addChunk(Mantid::API::Workspace_sptr chunkWS);
void addMatrixWSChunk(const std::string &algoName, API::Workspace_sptr accumWS, API::Workspace_sptr chunkWS);
void appendChunk(Mantid::API::Workspace_sptr chunkWS);
API::Workspace_sptr appendMatrixWSChunk(API::Workspace_sptr accumWS, Mantid::API::Workspace_sptr chunkWS);

void doSortEvents(Mantid::API::Workspace_sptr ws);

Expand Down
119 changes: 101 additions & 18 deletions Code/Mantid/Framework/LiveData/src/LoadLiveData.cpp
Expand Up @@ -67,6 +67,7 @@ This could cause Mantid to run very slowly or to crash due to lack of memory.
#include "MantidKernel/CPUTimer.h"

#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>

using namespace Mantid::Kernel;
using namespace Mantid::API;
Expand Down Expand Up @@ -250,9 +251,19 @@ namespace LiveData

if (!PostProcess)
{
if ( !temp )
{
// a group workspace cannot be returned by wsProp
temp = AnalysisDataService::Instance().retrieve(inputName);
}
// Remove the chunk workspace from the ADS, it is no longer needed there.
AnalysisDataService::Instance().remove(inputName);
}
else if ( !temp )
{
// a group workspace cannot be returned by wsProp
temp = AnalysisDataService::Instance().retrieve(getPropertyValue("OutputWorkspace"));
}
return temp;
}
else
Expand Down Expand Up @@ -385,31 +396,78 @@ namespace LiveData
//----------------------------------------------------------------------------------------------
/** Accumulate the data by appending the spectra into the
* the output workspace.
* Calls AppendSpectra algorithm.
* Checks if the chunk is a group and if it is calls appendMatrixWSChunk for each item.
* If it's a matrix just calls appendMatrixWSChunk.
* Sets m_accumWS.
*
* @param chunkWS :: processed live data chunk workspace
*/
void LoadLiveData::appendChunk(Mantid::API::Workspace_sptr chunkWS)
{
IAlgorithm_sptr alg;
ReadLock _lock1(*m_accumWS);
ReadLock _lock2(*chunkWS);
// ISIS multi-period data come in workspace groups
WorkspaceGroup_sptr chunk_gws = boost::dynamic_pointer_cast<WorkspaceGroup>(chunkWS);

alg = this->createChildAlgorithm("AppendSpectra");
alg->setProperty("InputWorkspace1", m_accumWS);
alg->setProperty("InputWorkspace2", chunkWS);
alg->setProperty("ValidateInputs", false);
alg->execute();
if (!alg->isExecuted())
{
throw std::runtime_error("Error when calling AppendSpectra to append the spectra of the chunk of live data. See log.");
}
// TODO: What about workspace groups?
MatrixWorkspace_sptr temp = alg->getProperty("OutputWorkspace");
m_accumWS = temp;
// And sort the events, if any
doSortEvents(m_accumWS);
if ( chunk_gws )
{
WorkspaceGroup_sptr accum_gws = boost::dynamic_pointer_cast<WorkspaceGroup>(m_accumWS);
if ( !accum_gws )
{
throw std::runtime_error("Two workspace groups are expected.");
}
if ( accum_gws->getNumberOfEntries() != chunk_gws->getNumberOfEntries() )
{
throw std::runtime_error("Accumulation and chunk workspace groups are expected to have the same size.");
}
// disassemble the accum group and put it back together again with updated items
size_t nItems = static_cast<size_t>(chunk_gws->getNumberOfEntries());
std::vector<Workspace_sptr> items(nItems);
for(size_t i = 0; i < nItems; ++i)
{
items[i] = accum_gws->getItem(i);
}
accum_gws->removeAll();
// append members one by one
for(size_t i = 0; i < nItems; ++i)
{
accum_gws->addWorkspace( appendMatrixWSChunk( items[i], chunk_gws->getItem(i) ) );
}
}
else
{
// just append the chunk
m_accumWS = appendMatrixWSChunk( m_accumWS, chunkWS );
}
}

//----------------------------------------------------------------------------------------------
/** Accumulate the data by appending the spectra into the
* the output workspace.
* Calls AppendSpectra algorithm.
*
* @param accumWS :: accumulation matrix workspace
* @param chunkWS :: processed live data chunk matrix workspace
*/
Workspace_sptr LoadLiveData::appendMatrixWSChunk(Workspace_sptr accumWS, Workspace_sptr chunkWS)
{
IAlgorithm_sptr alg;
ReadLock _lock1(*accumWS);
ReadLock _lock2(*chunkWS);

alg = this->createChildAlgorithm("AppendSpectra");
alg->setProperty("InputWorkspace1", accumWS);
alg->setProperty("InputWorkspace2", chunkWS);
alg->setProperty("ValidateInputs", false);
alg->execute();
if (!alg->isExecuted())
{
throw std::runtime_error("Error when calling AppendSpectra to append the spectra of the chunk of live data. See log.");
}

MatrixWorkspace_sptr temp = alg->getProperty("OutputWorkspace");
accumWS = temp;
// And sort the events, if any
doSortEvents(accumWS);
return accumWS;
}

//----------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -547,6 +605,31 @@ namespace LiveData
this->setProperty("OutputWorkspace", m_outputWS);
}

// Output group requires some additional handling
WorkspaceGroup_sptr out_gws = boost::dynamic_pointer_cast<WorkspaceGroup>(m_outputWS);
if ( out_gws )
{
size_t n = static_cast<size_t>(out_gws->getNumberOfEntries());
for(size_t i = 0; i < n; ++i)
{
auto ws = out_gws->getItem(i);
std::string itemName = ws->name();
std::string wsName = getPropertyValue("OutputWorkspace") + "_" + boost::lexical_cast<std::string>(i+1);
if ( wsName != itemName )
{
if ( AnalysisDataService::Instance().doesExist(itemName) )
{
// replace the temporary name with the proper one
AnalysisDataService::Instance().rename(itemName,wsName);
}
}
else
{
// touch the workspace in the ADS to issue a notification to update the GUI
AnalysisDataService::Instance().addOrReplace(itemName,ws);
}
}
}

}

Expand Down
1 change: 1 addition & 0 deletions Code/Mantid/Framework/LiveData/test/CMakeLists.txt
Expand Up @@ -5,6 +5,7 @@ if ( CXXTEST_FOUND )
# This variable is used within the cxxtest_add_test macro to build this helper class into the test executable.
# It will go out of scope at the end of this file so doesn't need un-setting
set ( TESTHELPER_SRCS TestDataListener.cpp
TestGroupDataListener.cpp
../../TestHelpers/src/ComponentCreationHelper.cpp
../../TestHelpers/src/WorkspaceCreationHelper.cpp
../../TestHelpers/src/StartFrameworkManager.cpp
Expand Down
163 changes: 161 additions & 2 deletions Code/Mantid/Framework/LiveData/test/LoadLiveDataTest.h
Expand Up @@ -9,10 +9,12 @@
#include <cxxtest/TestSuite.h>
#include <iomanip>
#include <iostream>
#include <numeric>
#include "MantidDataObjects/Workspace2D.h"
#include "MantidKernel/ConfigService.h"
#include "MantidAPI/LiveListenerFactory.h"
#include "MantidTestHelpers/FacilityHelper.h"
#include "TestGroupDataListener.h"

using namespace Mantid;
using namespace Mantid::LiveData;
Expand Down Expand Up @@ -83,12 +85,16 @@ class LoadLiveDataTest : public CxxTest::TestSuite
alg.exec();
TS_ASSERT( alg.isExecuted() );

TSM_ASSERT_LESS_THAN( "Run number should be non-zero", 0, alg.runNumber() );

// Retrieve the workspace from data service.
boost::shared_ptr<TYPE> ws;
TS_ASSERT_THROWS_NOTHING( ws = AnalysisDataService::Instance().retrieveWS<TYPE>("fake") );
TS_ASSERT(ws);

if ( dynamic_cast<MatrixWorkspace*>(ws.get()) )
{
TSM_ASSERT_LESS_THAN( "Run number should be non-zero", 0, alg.runNumber() );
}

return ws;
}

Expand Down Expand Up @@ -297,6 +303,159 @@ class LoadLiveDataTest : public CxxTest::TestSuite
TS_ASSERT_EQUALS(ws->getNPoints(), 400);
}

//--------------------------------------------------------------------------------------------
/** Handle WorkspaceGroups returned by the listener */
void test_WorkspaceGroup_Replace_None_None()
{
WorkspaceGroup_sptr ws = doExec<WorkspaceGroup>("Replace", "", "", "", "", false, ILiveListener_sptr(new TestGroupDataListener) );
TS_ASSERT(ws);
TS_ASSERT_EQUALS(ws->getNumberOfEntries(),3);
TS_ASSERT_EQUALS(ws->name(),"fake");
MatrixWorkspace_sptr mws = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>("fake_2");
TS_ASSERT(mws);
TS_ASSERT_EQUALS( mws->getNumberHistograms(), 2 );
TS_ASSERT_EQUALS( mws->blocksize(), 10 );
TS_ASSERT_EQUALS( mws->readX(1)[10], 10.0 );
TS_ASSERT_EQUALS( mws->readY(1)[5], 2.0 );
TS_ASSERT_EQUALS( std::accumulate( mws->readY(1).begin(), mws->readY(1).end(), 0.0, std::plus<double>() ), 20.0 );
AnalysisDataService::Instance().clear();
}
//--------------------------------------------------------------------------------------------
void test_WorkspaceGroup_Replace_Rebin_None()
{
WorkspaceGroup_sptr ws = doExec<WorkspaceGroup>("Replace", "Rebin", "Params=0,2,8", "", "", false, ILiveListener_sptr(new TestGroupDataListener) );
TS_ASSERT(ws);
TS_ASSERT_EQUALS(ws->getNumberOfEntries(),3);
TS_ASSERT_EQUALS(ws->name(),"fake");
MatrixWorkspace_sptr mws = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>("fake_2");
TS_ASSERT(mws);
TS_ASSERT_EQUALS( mws->getNumberHistograms(), 2 );
TS_ASSERT_EQUALS( mws->blocksize(), 4 );
TS_ASSERT_EQUALS( mws->readX(1)[4], 8.0 );
TS_ASSERT_EQUALS( mws->readY(1)[3], 4.0 );
TS_ASSERT_EQUALS( std::accumulate( mws->readY(1).begin(), mws->readY(1).end(), 0.0, std::plus<double>() ), 16.0 );
AnalysisDataService::Instance().clear();
}
//--------------------------------------------------------------------------------------------
void test_WorkspaceGroup_Replace_None_Rebin()
{
WorkspaceGroup_sptr ws = doExec<WorkspaceGroup>("Replace", "", "", "Rebin", "Params=0,2,8", false, ILiveListener_sptr(new TestGroupDataListener) );
TS_ASSERT(ws);
TS_ASSERT_EQUALS(ws->getNumberOfEntries(),3);
TS_ASSERT_EQUALS(ws->name(),"fake");
MatrixWorkspace_sptr mws = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>("fake_2");
TS_ASSERT(mws);
TS_ASSERT_EQUALS( mws->getNumberHistograms(), 2 );
TS_ASSERT_EQUALS( mws->blocksize(), 4 );
TS_ASSERT_EQUALS( mws->readX(1)[4], 8.0 );
TS_ASSERT_EQUALS( mws->readY(1)[3], 4.0 );
TS_ASSERT_EQUALS( std::accumulate( mws->readY(1).begin(), mws->readY(1).end(), 0.0, std::plus<double>() ), 16.0 );
AnalysisDataService::Instance().clear();
}
//--------------------------------------------------------------------------------------------
/** Handle WorkspaceGroups returned by the listener */
void test_WorkspaceGroup_Add_None_None()
{
doExec<WorkspaceGroup>("Add", "", "", "", "", false, ILiveListener_sptr(new TestGroupDataListener) );
WorkspaceGroup_sptr ws = doExec<WorkspaceGroup>("Add", "", "", "", "", false, ILiveListener_sptr(new TestGroupDataListener) );
TS_ASSERT(ws);
TS_ASSERT_EQUALS(ws->getNumberOfEntries(),3);
TS_ASSERT_EQUALS(ws->name(),"fake");
MatrixWorkspace_sptr mws = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>("fake_2");
TS_ASSERT(mws);
TS_ASSERT_EQUALS( mws->getNumberHistograms(), 2 );
TS_ASSERT_EQUALS( mws->blocksize(), 10 );
TS_ASSERT_EQUALS( mws->readX(1)[10], 10.0 );
TS_ASSERT_EQUALS( mws->readY(1)[5], 4.0 );
TS_ASSERT_EQUALS( std::accumulate( mws->readY(1).begin(), mws->readY(1).end(), 0.0, std::plus<double>() ), 40.0 );
AnalysisDataService::Instance().clear();
}
//--------------------------------------------------------------------------------------------
void test_WorkspaceGroup_Add_Rebin_None()
{
doExec<WorkspaceGroup>("Add", "Rebin", "Params=0,2,8", "", "", false, ILiveListener_sptr(new TestGroupDataListener) );
WorkspaceGroup_sptr ws = doExec<WorkspaceGroup>("Add", "Rebin", "Params=0,2,8", "", "", false, ILiveListener_sptr(new TestGroupDataListener) );
TS_ASSERT(ws);
TS_ASSERT_EQUALS(ws->getNumberOfEntries(),3);
TS_ASSERT_EQUALS(ws->name(),"fake");
MatrixWorkspace_sptr mws = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>("fake_2");
TS_ASSERT(mws);
TS_ASSERT_EQUALS( mws->getNumberHistograms(), 2 );
TS_ASSERT_EQUALS( mws->blocksize(), 4 );
TS_ASSERT_EQUALS( mws->readX(1)[4], 8.0 );
TS_ASSERT_EQUALS( mws->readY(1)[3], 8.0 );
TS_ASSERT_EQUALS( std::accumulate( mws->readY(1).begin(), mws->readY(1).end(), 0.0, std::plus<double>() ), 32.0 );
AnalysisDataService::Instance().clear();
}
//--------------------------------------------------------------------------------------------
void test_WorkspaceGroup_Add_None_Rebin()
{
doExec<WorkspaceGroup>("Add", "", "", "Rebin", "Params=0,2,8", false, ILiveListener_sptr(new TestGroupDataListener) );
WorkspaceGroup_sptr ws = doExec<WorkspaceGroup>("Add", "", "", "Rebin", "Params=0,2,8", false, ILiveListener_sptr(new TestGroupDataListener) );
TS_ASSERT(ws);
TS_ASSERT_EQUALS(ws->getNumberOfEntries(),3);
TS_ASSERT_EQUALS(ws->name(),"fake");
MatrixWorkspace_sptr mws = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>("fake_2");
TS_ASSERT(mws);
TS_ASSERT_EQUALS( mws->getNumberHistograms(), 2 );
TS_ASSERT_EQUALS( mws->blocksize(), 4 );
TS_ASSERT_EQUALS( mws->readX(1)[4], 8.0 );
TS_ASSERT_EQUALS( mws->readY(1)[3], 8.0 );
TS_ASSERT_EQUALS( std::accumulate( mws->readY(1).begin(), mws->readY(1).end(), 0.0, std::plus<double>() ), 32.0 );
AnalysisDataService::Instance().clear();
}
//--------------------------------------------------------------------------------------------
/** Handle WorkspaceGroups returned by the listener */
void test_WorkspaceGroup_Append_None_None()
{
doExec<WorkspaceGroup>("Append", "", "", "", "", false, ILiveListener_sptr(new TestGroupDataListener) );
WorkspaceGroup_sptr ws = doExec<WorkspaceGroup>("Append", "", "", "", "", false, ILiveListener_sptr(new TestGroupDataListener) );
TS_ASSERT(ws);
TS_ASSERT_EQUALS(ws->getNumberOfEntries(),3);
TS_ASSERT_EQUALS(ws->name(),"fake");
MatrixWorkspace_sptr mws = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>("fake_2");
TS_ASSERT(mws);
TS_ASSERT_EQUALS( mws->getNumberHistograms(), 4 );
TS_ASSERT_EQUALS( mws->blocksize(), 10 );
TS_ASSERT_EQUALS( mws->readX(1)[10], 10.0 );
TS_ASSERT_EQUALS( mws->readY(1)[5], 2.0 );
TS_ASSERT_EQUALS( std::accumulate( mws->readY(1).begin(), mws->readY(1).end(), 0.0, std::plus<double>() ), 20.0 );
AnalysisDataService::Instance().clear();
}
//--------------------------------------------------------------------------------------------
void test_WorkspaceGroup_Append_Rebin_None()
{
doExec<WorkspaceGroup>("Append", "Rebin", "Params=0,2,8", "", "", false, ILiveListener_sptr(new TestGroupDataListener) );
WorkspaceGroup_sptr ws = doExec<WorkspaceGroup>("Append", "Rebin", "Params=0,2,8", "", "", false, ILiveListener_sptr(new TestGroupDataListener) );
TS_ASSERT(ws);
TS_ASSERT_EQUALS(ws->getNumberOfEntries(),3);
TS_ASSERT_EQUALS(ws->name(),"fake");
MatrixWorkspace_sptr mws = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>("fake_2");
TS_ASSERT(mws);
TS_ASSERT_EQUALS( mws->getNumberHistograms(), 4 );
TS_ASSERT_EQUALS( mws->blocksize(), 4 );
TS_ASSERT_EQUALS( mws->readX(1)[4], 8.0 );
TS_ASSERT_EQUALS( mws->readY(1)[3], 4.0 );
TS_ASSERT_EQUALS( std::accumulate( mws->readY(1).begin(), mws->readY(1).end(), 0.0, std::plus<double>() ), 16.0 );
AnalysisDataService::Instance().clear();
}
//--------------------------------------------------------------------------------------------
void test_WorkspaceGroup_Append_None_Rebin()
{
doExec<WorkspaceGroup>("Append", "", "", "Rebin", "Params=0,2,8", false, ILiveListener_sptr(new TestGroupDataListener) );
WorkspaceGroup_sptr ws = doExec<WorkspaceGroup>("Append", "", "", "Rebin", "Params=0,2,8", false, ILiveListener_sptr(new TestGroupDataListener) );
TS_ASSERT(ws);
TS_ASSERT_EQUALS(ws->getNumberOfEntries(),3);
TS_ASSERT_EQUALS(ws->name(),"fake");
MatrixWorkspace_sptr mws = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>("fake_2");
TS_ASSERT(mws);
TS_ASSERT_EQUALS( mws->getNumberHistograms(), 4 );
TS_ASSERT_EQUALS( mws->blocksize(), 4 );
TS_ASSERT_EQUALS( mws->readX(1)[4], 8.0 );
TS_ASSERT_EQUALS( mws->readY(1)[3], 4.0 );
TS_ASSERT_EQUALS( std::accumulate( mws->readY(1).begin(), mws->readY(1).end(), 0.0, std::plus<double>() ), 16.0 );
AnalysisDataService::Instance().clear();
}
};


Expand Down

0 comments on commit 9f677b2

Please sign in to comment.