Newer
Older
#ifndef WBVMEDIANTESTTEST_H_
#define WBVMEDIANTESTTEST_H_
#include <cxxtest/TestSuite.h>
#include "WorkspaceCreationHelper.hh"
Steve Williams
committed
#include "MantidAlgorithms/MedianDetectorTest.h"
#include "MantidKernel/UnitFactory.h"
#include "MantidAPI/AnalysisDataService.h"
#include "MantidAPI/WorkspaceFactory.h"
#include "MantidAPI/SpectraDetectorMap.h"
#include "MantidDataObjects/Workspace2D.h"
#include "MantidDataHandling/LoadInstrument.h"
Steve Williams
committed
#include <boost/shared_ptr.hpp>
#include <boost/lexical_cast.hpp>
#include <math.h>
#include <iostream>
#include <sstream>
#include <fstream>
Steve Williams
committed
#include <ios>
#include <string>
using namespace Mantid::Kernel;
using namespace Mantid::Geometry;
using namespace Mantid::API;
using namespace Mantid::Algorithms;
using namespace Mantid::DataObjects;
Steve Williams
committed
class MedianDetectorTestTest : public CxxTest::TestSuite
{
public:
Steve Williams
committed
void testWorkspaceAndArray()
Steve Williams
committed
{
Steve Williams
committed
MedianDetectorTest alg;
TS_ASSERT_EQUALS( alg.name(), "MedianDetectorTest" )
Steve Williams
committed
TS_ASSERT_EQUALS( alg.version(), 1 )
Steve Williams
committed
//the spectra were setup in the constructor and passed to our algorithm through this function
TS_ASSERT_THROWS_NOTHING(
TS_ASSERT( runInit(alg) ) )
Steve Williams
committed
alg.setProperty("SignificanceTest", 1.0);
Steve Williams
committed
//these are realistic values that I just made up
Steve Williams
committed
alg.setProperty( "LowThreshold", 0.5 );
alg.setProperty( "HighThreshold", 1.3333 );
//we are using the defaults on StartSpectrum, EndSpectrum, RangeLower and RangeUpper which is to use the whole spectrum
Steve Williams
committed
Steve Williams
committed
TS_ASSERT_THROWS_NOTHING( alg.execute());
TS_ASSERT( alg.isExecuted() );
std::vector<int> OArray;
Steve Williams
committed
TS_ASSERT_THROWS_NOTHING( OArray = alg.getProperty( "BadDetectorIDs" ) )
Steve Williams
committed
// Get back the saved workspace
Workspace_sptr output;
Steve Williams
committed
TS_ASSERT_THROWS_NOTHING(output = AnalysisDataService::Instance().retrieve("MedianDetectorTestOutput"));
Steve Williams
committed
Workspace_sptr input;
TS_ASSERT_THROWS_NOTHING(input = AnalysisDataService::Instance().retrieve(m_IWSName));
MatrixWorkspace_sptr outputMat = boost::dynamic_pointer_cast<MatrixWorkspace>(output);
TS_ASSERT ( outputMat ) ;
Steve Williams
committed
TS_ASSERT_EQUALS( outputMat->YUnit(), "" )
Steve Williams
committed
//There are three outputs, a workspace (tested in the next code block), an array (later, this test) and a file (next test)
Steve Williams
committed
//were all the spectra output?
const int numberOfSpectra = outputMat->getNumberHistograms();
TS_ASSERT_EQUALS(numberOfSpectra, (int)Nhist);
// the numbers below are threshold values that were found by trail and error running these tests
int firstGoodSpec = 36;
int lastGoodSpec = 95;
Steve Williams
committed
int savedBySignific = Nhist-1;
for (int lHist = 1; lHist < firstGoodSpec; lHist++)
Steve Williams
committed
{
TS_ASSERT_EQUALS(
outputMat->readY(lHist).front(), BadVal )
}
for (int lHist=firstGoodSpec; lHist <= lastGoodSpec; lHist++)
{
TS_ASSERT_EQUALS(
outputMat->readY(lHist).front(), GoodVal )
}
Steve Williams
committed
for (int lHist = lastGoodSpec+1; lHist < savedBySignific; lHist++)
Steve Williams
committed
{
TS_ASSERT_EQUALS(
outputMat->readY(lHist).front(), BadVal )
}
Steve Williams
committed
for (int lHist = savedBySignific; lHist < Nhist; lHist++)
{
TS_ASSERT_EQUALS(
outputMat->readY(lHist).front(), GoodVal )
}
Steve Williams
committed
//now check the array
std::vector<int>::const_iterator it = OArray.begin();
for (int lHist = 0 ; lHist < firstGoodSpec; lHist++ )
{
TS_ASSERT_EQUALS( *it, lHist+1 )
TS_ASSERT_THROWS_NOTHING( if ( it != OArray.end() ) ++it )
}
Steve Williams
committed
for (int lHist = lastGoodSpec+1 ; lHist < savedBySignific ; lHist++ )
{
TS_ASSERT_EQUALS( *it, lHist+1 )
Steve Williams
committed
if ( it != OArray.end() ) ++it;
else TS_ASSERT_EQUALS( lHist, savedBySignific - 1 );
Steve Williams
committed
}
//check that extra entries haven't been written to the array
TS_ASSERT_EQUALS( it, OArray.end() )
Steve Williams
committed
}
void testFile()
{
Steve Williams
committed
MedianDetectorTest alg;
Steve Williams
committed
TS_ASSERT_THROWS_NOTHING(
TS_ASSERT( runInit(alg) ) )
Steve Williams
committed
// values a little extreme, I just made them up
alg.setProperty( "LowThreshold", 0.44444 );
alg.setProperty( "HighThreshold", 5.0 );
Steve Williams
committed
// this should turn off examining the errors. This makes things simplier, significance testing was tested in the last test
alg.setProperty("SignificanceTest", 0.0);
Steve Williams
committed
const int fSpec = 0, lSpec = Nhist/2;
alg.setProperty( "StartWorkspaceIndex", fSpec );
alg.setProperty( "EndWorkspaceIndex", lSpec );
Steve Williams
committed
//a couple of random numbers in the range
Steve Williams
committed
const double lRange = 4000, uRange = 10000;
alg.setProperty( "RangeLower", lRange );
alg.setProperty( "RangeUpper", uRange );
Steve Williams
committed
Steve Williams
committed
std::string OFileName("MedianDetectorTestTestFile.txt");
Steve Williams
committed
alg.setPropertyValue( "OutputFile", OFileName );
TS_ASSERT_THROWS_NOTHING( alg.execute());
TS_ASSERT( alg.isExecuted() );
Steve Williams
committed
//test file output
std::fstream testFile(OFileName.c_str(), std::ios::in);
//the tests here are done as unhandled exceptions cxxtest will handle the exceptions and display a message but only after this function has been abandoned, which leaves the file undeleted so it can be viewed
TS_ASSERT ( testFile )
Steve Williams
committed
// comfirmed these values by following the debugger up to this point
int firstGoodSpec = 16;
int lastGoodSpec = 360;
Steve Williams
committed
std::string fileLine = "";
Steve Williams
committed
for (int iHist = -1 ; iHist < firstGoodSpec; iHist++ )
Steve Williams
committed
{
std::ostringstream correctLine;
Steve Williams
committed
if ( iHist == -1 )
Steve Williams
committed
correctLine << "Index Spectrum UDET(S)";
else
{
Steve Williams
committed
correctLine << " Spectrum number " << iHist+1 << " is too low, ";
correctLine << "detector IDs: " << iHist+1;
Steve Williams
committed
}
std::getline( testFile, fileLine );
TS_ASSERT_EQUALS ( fileLine, correctLine.str() )
Steve Williams
committed
}
Steve Williams
committed
for (int iHist = lastGoodSpec+1 ; iHist < Nhist; iHist++ )
Steve Williams
committed
{
std::ostringstream correctLine;
Steve Williams
committed
correctLine << " Spectrum with number " << iHist+1 << " is too high";
correctLine << " detector IDs: " << iHist+1;
Steve Williams
committed
std::getline( testFile, fileLine );
TS_ASSERT_EQUALS ( fileLine, correctLine.str() )
Steve Williams
committed
}
testFile.close();
remove(OFileName.c_str());
Steve Williams
committed
}
Steve Williams
committed
Steve Williams
committed
MedianDetectorTestTest() : m_IWSName("MedianDetectorTestInput"), BadVal(100.0), GoodVal(0.0)
{
using namespace Mantid;
// Set up a small workspace for testing
Workspace_sptr space = WorkspaceFactory::Instance().create("Workspace2D",Nhist,11,10);
Workspace2D_sptr space2D = boost::dynamic_pointer_cast<Workspace2D>(space);
Steve Williams
committed
const short specLength = 22;
boost::shared_ptr<MantidVec> x(new MantidVec(specLength));
for (int i = 0; i < specLength; ++i)
{
(*x)[i]=i*1000;
}
Steve Williams
committed
// the data will be 21 random numbers
double yArray[specLength-1] =
{0.2,4,50,0.001,0,0,0,1,0,15,4,0,0.001,2e-10,0,8,0,1e-4,1,7,11};
Steve Williams
committed
m_YSum = 0; for (int i = 0; i < specLength-1; i++) m_YSum += yArray[i];
Steve Williams
committed
// most error values will be small so that they wont affect the tests
boost::shared_ptr<MantidVec> smallErrors(
new MantidVec( specLength-1, 0.01*m_YSum/specLength ) );
// if the SignificanceTest property is set to one, knowing what happens in the loop below, these errors will just make or break the tests
boost::shared_ptr<MantidVec> almostBigEnough( new MantidVec( specLength-1, 0) );
(*almostBigEnough)[0] = 0.9*m_YSum*(0.5*Nhist-1);
boost::shared_ptr<MantidVec> bigEnough( new MantidVec( specLength-1, 0 ) );
(*bigEnough)[0] = 1.2*m_YSum*(0.5*Nhist);
int forSpecDetMap[Nhist];
for (int j = 0; j < Nhist; ++j)
{
space2D->setX(j, x);
Steve Williams
committed
boost::shared_ptr<MantidVec> spectrum( new MantidVec );
//the spectravalues will be multiples of the random numbers above
Steve Williams
committed
for ( int l = 0; l < specLength-1; ++l )
{
spectrum->push_back( j*yArray[l] );
}
Steve Williams
committed
boost::shared_ptr<MantidVec> errors = smallErrors;
if ( j == Nhist-2 ) errors = almostBigEnough;
if ( j == Nhist-1 ) errors = bigEnough;
space2D->setData( j, spectrum, errors );
// Just set the spectrum number to match the index
space2D->getAxis(1)->spectraNo(j) = j+1;
forSpecDetMap[j] = j+1;
Steve Williams
committed
}
// Register the workspace in the data service
Steve Williams
committed
AnalysisDataService::Instance().add(m_IWSName, space);
// Load the instrument data
Mantid::DataHandling::LoadInstrument loader;
loader.initialize();
// Path to test input file assumes Test directory checked out from SVN
std::string inputFile = "../../../../Test/Instrument/INS_Definition.xml";
loader.setPropertyValue("Filename", inputFile);
loader.setPropertyValue("Workspace", m_IWSName);
loader.execute();
space2D->mutableSpectraMap().populate(forSpecDetMap, forSpecDetMap, Nhist);
space2D->getAxis(0)->unit() = UnitFactory::Instance().create("TOF");
Steve Williams
committed
bool runInit(MedianDetectorTest &alg)
{
TS_ASSERT_THROWS_NOTHING(alg.initialize());
Steve Williams
committed
bool good = alg.isInitialized();
// Set the properties
Steve Williams
committed
alg.setPropertyValue("InputWorkspace", m_IWSName);
alg.setPropertyValue("OutputWorkspace","MedianDetectorTestOutput");
Steve Williams
committed
return good;
}
private:
Steve Williams
committed
std::string m_IWSName;
double m_YSum;
enum { Nhist = 144 };
//these values must match the values in DetectorEfficiencyVariation.h
const double BadVal;
const double GoodVal;
};
#endif /*WBVMEDIANTESTTEST_H_*/