-
Doucet, Mathieu authoredDoucet, Mathieu authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
LoadSNSspec.cpp 7.84 KiB
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidDataHandling/LoadSNSspec.h"
#include "MantidDataObjects/Workspace2D.h"
#include "MantidKernel/UnitFactory.h"
#include "MantidAPI/FileProperty.h"
#include "MantidAPI/LoadAlgorithmFactory.h"
#include <fstream>
#include <cstring>
#include <boost/tokenizer.hpp>
namespace Mantid
{
namespace DataHandling
{
// Register the algorithm into the algorithm factory
DECLARE_ALGORITHM(LoadSNSspec)
//register the algorithm into loadalgorithm factory
DECLARE_LOADALGORITHM(LoadSNSspec)
/// Sets documentation strings for this algorithm
void LoadSNSspec::initDocs()
{
this->setWikiSummary("Loads data from a text file and stores it in a 2D [[workspace]] ([[Workspace2D]] class). ");
this->setOptionalMessage("Loads data from a text file and stores it in a 2D workspace (Workspace2D class).");
}
using namespace Kernel;
using namespace API;
/// Empty constructor
LoadSNSspec::LoadSNSspec() {}
/// Initialisation method.
void LoadSNSspec::init()
{
std::vector<std::string> exts;
exts.push_back(".dat");
exts.push_back(".txt");
declareProperty(new FileProperty("Filename", "", FileProperty::Load, exts),
"A SNS Spec Ascii file");
declareProperty(new WorkspaceProperty<>("OutputWorkspace",
"",Direction::Output), "The name of the workspace that will be created.");
std::vector<std::string> units = UnitFactory::Instance().getKeys();
declareProperty("Unit","Energy",new Kernel::ListValidator(units),
"The unit to assign to the X axis (default: Energy)");
}
/**
* Executes the algorithm.
*/
void LoadSNSspec::exec()
{
std::string filename = getProperty("Filename");
std::string separator = " "; //separator can be 1 or more spaces
std::ifstream file(filename.c_str());
file.seekg (0, std::ios::end);
Progress progress(this,0,1,static_cast<int>(file.tellg()));
file.seekg (0, std::ios::beg);
std::string str;
std::vector<DataObjects::Histogram1D> spectra;
//size_t iLine=0; // line number
size_t ncols = 3; // number of columns
int nSpectra = 0;
int nBins = 0; //number of rows
std::string first_character;
std::string axes_infos;
//bool numeric = true;
std::vector<double> input;
//determine the number of lines starting by #L
//as there is one per set of data
int spectra_nbr = 0;
while(getline(file,str))
{
if (str.empty() ) continue;
if (str[0] == '#' && str[1] == 'L')
{
spectra_nbr++;
}
}
spectra.resize(spectra_nbr);
file.clear(); //end of file has been reached so we need to clear file state
file.seekg (0, std::ios::beg); //go back to beginning of file
int working_with_spectrum_nbr = -1; //spectrum number
while(getline(file,str))
{
progress.report(static_cast<int>(file.tellg()));
//line with data, need to be parsed by white spaces
if (!str.empty() && str[0] != '#')
{
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
boost::char_separator<char> sep(" ");
tokenizer tok(str, sep);
ncols = 0;
for (tokenizer::iterator beg=tok.begin(); beg!=tok.end(); ++beg)
{
std::stringstream ss;
ss << *beg;
double d;
ss >> d;
input.push_back(d);
}
}
if (str.empty())
{
if (working_with_spectrum_nbr != -1)
{
for(int j=0; j<static_cast<int>(input.size()-1); j++)
{
spectra[working_with_spectrum_nbr].dataX().push_back(input[j]);
j++;
spectra[working_with_spectrum_nbr].dataY().push_back(input[j]);
j++;
spectra[working_with_spectrum_nbr].dataE().push_back(input[j]);
nBins = j/3;
}
}
working_with_spectrum_nbr++;
input.clear();
}
} //end of read file
try
{
if (spectra_nbr == 0)
throw "Undefined number of spectra";
if (working_with_spectrum_nbr == (spectra_nbr-1))
{
for(int j=0; j<static_cast<int>(input.size()-1); j++)
{
spectra[working_with_spectrum_nbr].dataX().push_back(input[j]);
j++;
spectra[working_with_spectrum_nbr].dataY().push_back(input[j]);
j++;
spectra[working_with_spectrum_nbr].dataE().push_back(input[j]);
nBins = j/3;
}
}
}
catch (...)
{
}
try
{
nSpectra = spectra_nbr;
MatrixWorkspace_sptr localWorkspace = boost::dynamic_pointer_cast<MatrixWorkspace>
(WorkspaceFactory::Instance().create("Workspace2D",nSpectra,nBins,nBins));
localWorkspace->getAxis(0)->unit() = UnitFactory::Instance().create(getProperty("Unit"));
for(int i=0;i<nSpectra;i++)
{
localWorkspace->dataX(i) = spectra[i].dataX();
localWorkspace->dataY(i) = spectra[i].dataY();
localWorkspace->dataE(i) = spectra[i].dataE();
// Just have spectrum number start at 1 and count up
localWorkspace->getAxis(1)->spectraNo(i) = i+1;
}
setProperty("OutputWorkspace",localWorkspace);
}
catch (Exception::NotFoundError &)
{
// Asked for dimensionless workspace (obviously not in unit factory)
}
}
/**This method does a quick file check by checking the no.of bytes read nread params and header buffer
* @param filePath- path of the file including name.
* @param nread :: no.of bytes read
* @param header :: The first 100 bytes of the file as a union
* @return true if the given file is of type which can be loaded by this algorithm
*/
bool LoadSNSspec::quickFileCheck(const std::string& filePath,size_t nread,const file_header& header)
{
std::string extn=extension(filePath);
bool bascii(false);
(!extn.compare("txt"))?bascii=true:bascii=false;
bool is_ascii (true);
for(size_t i=0; i<nread; i++)
{
if (!isascii(header.full_hdr[i]))
is_ascii =false;
}
return(is_ascii|| bascii?true:false);
}
/**checks the file by opening it and reading few lines
* @param filePath :: name of the file including its path
* @return an integer value how much this algorithm can load the file
*/
int LoadSNSspec::fileCheck(const std::string& filePath)
{
std::ifstream file(filePath.c_str());
if (!file)
{
g_log.error("Unable to open file: " + filePath);
throw Exception::FileError("Unable to open file: " , filePath);
}
int bret=0;
int axiscols=0;
int datacols=0;
std::string str;
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
boost::char_separator<char> sep(" ");
bool bsnsspec(false);
while(!file.eof())
{
//read line
std::getline(file,str);
if(str.empty())
{
continue;
}
try
{
//if it's comment line
if (str.at(0)=='#' )
{
if(str.at(1) =='L')
{
tokenizer tok(str, sep);
for (tokenizer::iterator beg=tok.begin(); beg!=tok.end(); ++beg)
{
++axiscols;
}
//if the file contains a comment line starting with "#L" followed
//by three columns this could be loadsnsspec file
if(axiscols>2)
{
bsnsspec=true;
}
}
}
else
{
//check first data line is a 3 column line
tokenizer tok(str, sep);
for (tokenizer::iterator beg=tok.begin(); beg!=tok.end(); ++beg)
{
++datacols;
}
break;
}
}
catch(std::out_of_range& )
{
}
}
if(bsnsspec && datacols==3 )//three column data
{
bret=80;
}
return bret;
}
} // namespace DataHandling
} // namespace Mantid