Skip to content

Commit

Permalink
refs #5626. Separate tests for inst and det level fit functions.
Browse files Browse the repository at this point in the history
  • Loading branch information
OwenArnold committed Jul 19, 2012
1 parent 665926d commit fe0e71e
Showing 1 changed file with 137 additions and 44 deletions.
181 changes: 137 additions & 44 deletions Code/Mantid/Framework/Algorithms/test/NormaliseByDetectorTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include "MantidKernel/System.h"
#include "MantidAPI/WorkspaceGroup.h"
#include "MantidAPI/FrameworkManager.h"
#include "boost/format.hpp"
#include "boost/algorithm/string.hpp"
#include <iostream>
#include <iomanip>
#include <fstream>
Expand All @@ -24,6 +26,40 @@ class NormaliseByDetectorTest : public CxxTest::TestSuite

private:

/// File object type. Provides exception save file creation/destruction.
class FileObject
{
public:

/// Create a simple input file.
FileObject(const std::string& fileContents, const std::string& filename) : m_filename(filename)
{
m_file.open (filename.c_str());
m_file << fileContents;
m_file.close();
}

std::string getFileName() const
{
return m_filename;
}

/// Free up resources.
~FileObject()
{
m_file.close();
if( remove( m_filename.c_str() ) != 0 )
throw std::runtime_error("cannot remove " + m_filename);
}

private:
const std::string m_filename;
std::ofstream m_file;
// Following methods keeps us from being able to put objects of this type on the heap.
void *operator new(size_t);
void *operator new[](size_t);
};

/** Helper function, creates a histogram workspace with an instrument with 2 detectors, and 2 spectra.
Y-values are flat accross the x bins. Which makes it easy to calculate the expected value for any fit function applied to the X-data.
*/
Expand All @@ -44,45 +80,27 @@ class NormaliseByDetectorTest : public CxxTest::TestSuite
return ws;
}

/**
Helper function. Runs LoadParameterAlg, to get an instrument parameter definition from a file onto a workspace.
*/
void apply_instrument_parameter_file_to_workspace(MatrixWorkspace_sptr ws, const FileObject& file)
{
// Load the Instrument Parameter file over the existing test workspace + instrument.
using DataHandling::LoadParameterFile;
LoadParameterFile loadParameterAlg;
loadParameterAlg.setRethrows(true);
loadParameterAlg.initialize();
loadParameterAlg.setPropertyValue("Filename", file.getFileName());
loadParameterAlg.setProperty("Workspace", ws);
loadParameterAlg.execute();
}

/**
Helper function, applies fit functions from a fabricated, fake instrument parameter file ontop of an existing instrument definition.
The fit function is set at the instrument level.
*/
MatrixWorkspace_sptr create_workspace_with_fitting_functions()
{
/// File object type. Provides exception save file creation/destruction.
class FileObject
{
public:

/// Create a simple input file.
FileObject(const std::string& fileContents, const std::string& filename) : m_filename(filename)
{
m_file.open (filename.c_str());
m_file << fileContents;
m_file.close();
}

std::string getFileName() const
{
return m_filename;
}

/// Free up resources.
~FileObject()
{
m_file.close();
if( remove( m_filename.c_str() ) != 0 )
throw std::runtime_error("cannot remove " + m_filename);
}

private:
const std::string m_filename;
std::ofstream m_file;
// Following methods keeps us from being able to put objects of this type on the heap.
void *operator new(size_t);
void *operator new[](size_t);
};

// Create a default workspace with no-fitting functions.
MatrixWorkspace_sptr ws = create_workspace_with_no_fitting_functions();
const std::string instrumentName = ws->getInstrument()->getName();
Expand All @@ -105,14 +123,54 @@ class NormaliseByDetectorTest : public CxxTest::TestSuite
// Create a temporary Instrument Parameter file.
FileObject file(parameterFileContents, instrumentName + "_Parameters.xml");

// Load the Instrument Parameter file over the existing test workspace + instrument.
using DataHandling::LoadParameterFile;
LoadParameterFile loadParameterAlg;
loadParameterAlg.setRethrows(true);
loadParameterAlg.initialize();
loadParameterAlg.setPropertyValue("Filename", file.getFileName());
loadParameterAlg.setProperty("Workspace", ws);
loadParameterAlg.execute();
// Apply parameter file to workspace.
apply_instrument_parameter_file_to_workspace(ws, file);

return ws;
}

/**
Helper function, applies fit functions from a fabricated, fake instrument parameter file ontop of an existing instrument definition.
The fit function is different for every detector.
*/
MatrixWorkspace_sptr create_workspace_with_detector_level_only_fit_functions()
{
// Create a default workspace with no-fitting functions.
MatrixWorkspace_sptr ws = create_workspace_with_no_fitting_functions();
const std::string instrumentName = ws->getInstrument()->getName();

const double A1 = 1;
std::string componentLinks = "";
for(size_t wsIndex = 0; wsIndex < ws->getNumberHistograms(); ++wsIndex)
{
Geometry::IDetector_const_sptr det = ws->getDetector( wsIndex );

// A0, will vary with workspace index, from detector to detector, A1 is constant = 1.
componentLinks += boost::str(boost::format(
"<component-link name=\"%1%\">\n\
<parameter name=\"LinearBackground:A0\" type=\"fitting\">\n\
<formula eq=\"%2%\" result-unit=\"Wavelength\"/>\n\
<fixed />\n\
</parameter>\n\
<parameter name=\"LinearBackground:A1\" type=\"fitting\">\n\
<formula eq=\"%3%\" result-unit=\"Wavelength\"/>\n\
<fixed />\n\
</parameter>\n\
</component-link>\n") % det->getName() % wsIndex % A1);
}

// Create a parameter file, with a root equation that will apply to all detectors.
const std::string parameterFileContents = std::string("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n") +
"<parameter-file instrument = \"" + instrumentName + "\" date = \"2012-01-31T00:00:00\">\n" +
componentLinks +
"</parameter-file>\n";

// Create a temporary Instrument Parameter file.
FileObject file(parameterFileContents, instrumentName + "_Parameters.xml");

// Apply parameter file to workspace.
apply_instrument_parameter_file_to_workspace(ws, file);

return ws;
}

Expand Down Expand Up @@ -156,7 +214,7 @@ class NormaliseByDetectorTest : public CxxTest::TestSuite
void test_applies_instrument_function_to_child_detectors_calculates_correctly()
{
const std::string outWSName = "normalised_ws";
// Linear function 2*x + 1 applied to each x-value.
// Linear function 2*x + 1 applied to each x-value. INSTRUMENT LEVEL FIT FUNCTION ONLY.
MatrixWorkspace_sptr inputWS = create_workspace_with_fitting_functions();
NormaliseByDetector alg;
alg.initialize();
Expand All @@ -182,7 +240,42 @@ class NormaliseByDetectorTest : public CxxTest::TestSuite
for(size_t binIndex = 0; binIndex < (xValues.size() - 1); ++binIndex)
{
const double wavelength = (xValues[binIndex] + xValues[binIndex+1])/2;
const double expectedValue = (2*wavelength) + 1;
const double expectedValue = (2*wavelength) + 1; // According to the equation written into the instrument parameter file for the instrument component link.
TS_ASSERT_EQUALS(expectedValue, yValues[binIndex]);
}
}
}

void test_distribute_function_parameters_accross_object_hierachy()
{
const std::string outWSName = "normalised_ws";
// Linear function 1*x + N applied to each x-value, where N is the workspace index. DETECTOR LEVEL FIT FUNCTIONS ONLY.
MatrixWorkspace_sptr inputWS = create_workspace_with_detector_level_only_fit_functions();
NormaliseByDetector alg;
alg.initialize();
alg.setPropertyValue("OutputWorkspace", outWSName);
alg.setProperty("InputWorkspace", inputWS);
alg.execute();
// Extract the output workspace so that we can verify the normalisation.
MatrixWorkspace_sptr outWS =AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(outWSName);

// Output workspace should have 2 histograms.
TS_ASSERT_EQUALS(2, outWS->getNumberHistograms());
// Test the application of the linear function
for(size_t wsIndex = 0; wsIndex < outWS->getNumberHistograms(); ++wsIndex)
{
const MantidVec& yValues = outWS->readY(wsIndex);
const MantidVec& xValues = outWS->readX(wsIndex);
const MantidVec& eValues = outWS->readE(wsIndex);

TS_ASSERT_EQUALS(3, yValues.size());
TS_ASSERT_EQUALS(3, eValues.size());
TS_ASSERT_EQUALS(4, xValues.size());

for(size_t binIndex = 0; binIndex < (xValues.size() - 1); ++binIndex)
{
const double wavelength = (xValues[binIndex] + xValues[binIndex+1])/2;
const double expectedValue = (1*wavelength) + wsIndex; // According to the equation written into the instrument parameter file for the detector component link.
TS_ASSERT_EQUALS(expectedValue, yValues[binIndex]);
}
}
Expand Down

0 comments on commit fe0e71e

Please sign in to comment.