"git@code.ornl.gov:mantidproject/mantid.git" did not exist on "f298b0945f62d0d3ef1e96e4abd36a5db60a5ee9"
Newer
Older
//---------------------------------------------------
// Includes
//---------------------------------------------------
#include "MantidDataHandling/LoadSPE.h"
Steve Williams
committed
#include "MantidDataHandling/SaveSPE.h"
Federico Montesino Pouzols
committed
#include "MantidAPI/Axis.h"
#include "MantidAPI/BinEdgeAxis.h"
Federico Montesino Pouzols
committed
#include "MantidAPI/FileProperty.h"
#include "MantidAPI/MatrixWorkspace.h"
#include "MantidAPI/RegisterFileLoader.h"
Federico Montesino Pouzols
committed
#include "MantidAPI/WorkspaceFactory.h"
#include "MantidDataObjects/Histogram1D.h"
#include "MantidKernel/UnitFactory.h"
Federico Montesino Pouzols
committed
Steve Williams
committed
#include <limits>
Sofia Antony
committed
#include <fstream>
namespace Mantid {
namespace DataHandling {
using namespace Kernel;
using namespace API;
/**
* Return the confidence with with this algorithm can load the file
* @param descriptor A descriptor for the file
* @returns An integer specifying the confidence level. 0 indicates it will not
* be used
int LoadSPE::confidence(Kernel::FileDescriptor &descriptor) const {
if (!descriptor.isAscii())
return 0;
auto &file = descriptor.data();
std::string fileline;
// First line - expected to be a line 2 columns which is histogram & bin
// numbers
std::getline(file, fileline);
std::istringstream is(fileline);
unsigned int dummy(0);
is >> dummy >> dummy;
return 0; // Couldn't read 2 numbers so fail
}
// Trying to read another should produce eof
is >> dummy;
// Next line should be comment line: "### Phi Grid" or "### Q Grid"
std::getline(file, fileline);
if (fileline.find("Phi Grid") != std::string::npos ||
fileline.find("Q Grid") != std::string::npos) {
return 80;
//---------------------------------------------------
// Private member functions
//---------------------------------------------------
/**
* Initialise the algorithm
*/
void LoadSPE::init() {
declareProperty(new FileProperty("Filename", "", FileProperty::Load, ".spe"),
"The name of the SPE file to load.");
declareProperty(
new WorkspaceProperty<>("OutputWorkspace", "", Direction::Output),
"The name to use for the output workspace");
}
/**
* Execute the algorithm
*/
// Retrieve filename and try to open the file
m_filename = getPropertyValue("Filename");
FILE *speFile;
speFile = fopen(m_filename.c_str(), "r");
if (!speFile) {
g_log.error("Failed to open file: " + m_filename);
throw Exception::FileError("Failed to open file: ", m_filename);
// The first two numbers are the number of histograms and the number of bins
size_t nhist = 0, nbins = 0;
unsigned int nhistTemp = 0, nbinsTemp = 0;
int retval = fscanf(speFile, "%8u%8u\n", &nhistTemp, &nbinsTemp);
if (retval != 2)
reportFormatError("Header line");
// Cast from temp values to size_t values
nhist = static_cast<size_t>(nhistTemp);
nbins = static_cast<size_t>(nbinsTemp);
// Next line should be comment line: "### Phi Grid" or "### Q Grid"
char comment[100];
fgets(comment, 100, speFile);
if (comment[0] != '#')
reportFormatError(std::string(comment));
// Create the axis that will hold the phi values
auto *phiAxis = new BinEdgeAxis(nhist + 1);
// Look at previously read comment field to see what unit vertical axis should
// have
if (comment[4] == 'Q' || comment[4] == 'q') {
phiAxis->unit() = UnitFactory::Instance().create("MomentumTransfer");
phiAxis->unit() = boost::make_shared<Units::Phi>();
}
// Read in phi grid
for (size_t i = 0; i <= nhist; ++i) {
retval = fscanf(speFile, "%10le", &phi);
if (retval != 1) {
std::stringstream ss;
ss << "Reading phi value" << i;
reportFormatError(ss.str());
}
// Next line should be comment line: "### Energy Grid"
fgets(comment, 100, speFile);
if (comment[0] != '#')
reportFormatError(std::string(comment));
// Now the X bin boundaries
Janik Zikovsky
committed
MantidVecPtr XValues;
MantidVec &X = XValues.access();
X.resize(nbins + 1);
for (size_t i = 0; i <= nbins; ++i) {
retval = fscanf(speFile, "%10le", &X[i]);
if (retval != 1) {
std::stringstream ss;
ss << "Reading energy value" << i;
reportFormatError(ss.str());
}
}
// Read to EOL
// Now create the output workspace
MatrixWorkspace_sptr workspace = WorkspaceFactory::Instance().create(
"Workspace2D", nhist, nbins + 1, nbins);
workspace->getAxis(0)->unit() = UnitFactory::Instance().create("DeltaE");
Russell Taylor
committed
workspace->isDistribution(true); // It should be a distribution
workspace->setYUnitLabel("S(Phi,Energy)");
// Replace the default spectrum axis with the phi values one
workspace->replaceAxis(1, phiAxis);
// Now read in the data spectrum-by-spectrum
Progress progress(this, 0, 1, nhist);
for (size_t j = 0; j < nhist; ++j) {
readHistogram(speFile, workspace, j);
progress.report();
}
// Close the file
fclose(speFile);
// Set the output workspace property
setProperty("OutputWorkspace", workspace);
}
/** Reads in the data corresponding to a single spectrum
Janik Zikovsky
committed
* @param speFile :: The file handle
* @param workspace :: The output workspace
* @param index :: The index of the current spectrum
void LoadSPE::readHistogram(FILE *speFile, API::MatrixWorkspace_sptr workspace,
size_t index) {
// First, there should be a comment line
char comment[100];
fgets(comment, 100, speFile);
if (comment[0] != '#')
reportFormatError(std::string(comment));
// Then it's the Y values
MantidVec &Y = workspace->dataY(index);
const size_t nbins = workspace->blocksize();
for (size_t i = 0; i < nbins; ++i) {
retval = fscanf(speFile, "%10le", &Y[i]);
// g_log.error() << Y[i] << std::endl;
if (retval != 1) {
std::stringstream ss;
ss << "Reading data value" << i << " of histogram " << index;
reportFormatError(ss.str());
}
// -10^30 is the flag for not a number used in SPE files (from
// www.mantidproject.org/images/3/3d/Spe_file_format.pdf)
if (Y[i] == SaveSPE::MASK_FLAG) {
Steve Williams
committed
Y[i] = std::numeric_limits<double>::quiet_NaN();
}
fgets(comment, 100, speFile);
if (comment[0] != '#')
reportFormatError(std::string(comment));
// And then the error values
MantidVec &E = workspace->dataE(index);
for (size_t i = 0; i < nbins; ++i) {
retval = fscanf(speFile, "%10le", &E[i]);
if (retval != 1) {
std::stringstream ss;
ss << "Reading error value" << i << " of histogram " << index;
reportFormatError(ss.str());
}
}
// Read to EOL
return;
}
/** Called if the file is not formatted as expected
Janik Zikovsky
committed
* @param what :: A string describing where the problem occurred
* @throw Mantid::Kernel::Exception::FileError terminating the algorithm
void LoadSPE::reportFormatError(const std::string &what) {
g_log.error("Unexpected formatting in file " + m_filename + " : " + what);
throw Exception::FileError("Unexpected formatting in file: ", m_filename);
}
} // namespace DataHandling
} // namespace Mantid