Newer
Older
Gigg, Martyn Anthony
committed
//---------------------------------------------------
// Includes
//---------------------------------------------------
#include "MantidDataHandling/LoadGSS.h"
#include "MantidAPI/ISpectrum.h"
Gigg, Martyn Anthony
committed
#include "MantidAPI/FileProperty.h"
#include "MantidAPI/RegisterFileLoader.h"
Gigg, Martyn Anthony
committed
#include "MantidAPI/WorkspaceValidators.h"
#include "MantidKernel/UnitFactory.h"
Russell Taylor
committed
#include "MantidGeometry/Instrument.h"

Zhou, Wenduo
committed
#include "MantidGeometry/Instrument/Detector.h"
#include "MantidGeometry/Instrument/CompAssembly.h"
#include "MantidGeometry/Instrument/Component.h"
Gigg, Martyn Anthony
committed
#include <boost/math/special_functions/fpclassify.hpp>
Gigg, Martyn Anthony
committed
#include <iostream>
#include <fstream>
Gigg, Martyn Anthony
committed
#include <iomanip>
using namespace Mantid::DataHandling;
using namespace Mantid::API;
using namespace Mantid::Kernel;
Janik Zikovsky
committed
namespace Mantid
Gigg, Martyn Anthony
committed
{

Zhou, Wenduo
committed
namespace DataHandling
{
DECLARE_FILELOADER_ALGORITHM(LoadGSS);
Gigg, Martyn Anthony
committed
/**
* 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 LoadGSS::confidence(Kernel::FileDescriptor & descriptor) const
{
if(!descriptor.isAscii()) return 0;
Gigg, Martyn Anthony
committed
std::string str;
std::istream & file = descriptor.data();
std::getline(file, str);//workspace title first line
while (!file.eof())
{
std::getline(file, str);
// Skip over empty and comment lines, as well as those coming from files saved with the 'ExtendedHeader' option
if (str.empty() || str[0] == '#' || str.compare(0, 8, "Monitor:") == 0)
{
continue;
}
if(str.compare(0, 4,"BANK") == 0 &&
(str.find("RALF") != std::string::npos || str.find("SLOG") != std::string::npos) &&
(str.find("FXYE") != std::string::npos))
{
return 80;
}
}
return 0;
}
Gigg, Martyn Anthony
committed

Zhou, Wenduo
committed
/**
* Initialise the algorithm
*/
void LoadGSS::init()
{
std::vector<std::string> exts;
exts.push_back(".gsa");
exts.push_back(".gss");

Zhou, Wenduo
committed
exts.push_back(".txt");
declareProperty(new API::FileProperty("Filename", "", API::FileProperty::Load, exts),
"The input filename of the stored data");
declareProperty(new API::WorkspaceProperty<>("OutputWorkspace", "", Kernel::Direction::Output),
"Workspace name to load into.");
declareProperty("UseBankIDasSpectrumNumber", false, "If true, spectrum number corresponding to each bank is to be its bank ID. ");

Zhou, Wenduo
committed
}
Janik Zikovsky
committed

Zhou, Wenduo
committed
/**
* Execute the algorithm
*/
void LoadGSS::exec()
{
using namespace Mantid::API;
std::string filename = getPropertyValue("Filename");
Janik Zikovsky
committed
bool m_useBankAsSpectrum = getProperty("UseBankIDasSpectrumNumber");

Zhou, Wenduo
committed
std::vector<MantidVec*> gsasDataX;
std::vector<MantidVec*> gsasDataY;
std::vector<MantidVec*> gsasDataE;
Janik Zikovsky
committed

Zhou, Wenduo
committed
double primaryflightpath = -1;
std::vector<double> twothetas;
std::vector<double> difcs;
std::vector<double> totalflightpaths;
std::vector<int> detectorIDs;
Janik Zikovsky
committed

Zhou, Wenduo
committed
MantidVec* X = new MantidVec();
MantidVec* Y = new MantidVec();
MantidVec* E = new MantidVec();
Janik Zikovsky
committed

Zhou, Wenduo
committed
Progress* prog = NULL;
Janik Zikovsky
committed

Zhou, Wenduo
committed
char currentLine[256];
std::string wsTitle;
std::string slogTitle;
std::string instrumentname = "Generic";
char filetype = 'x';
Janik Zikovsky
committed

Zhou, Wenduo
committed
std::ifstream input(filename.c_str(), std::ios_base::in);
// Gather data
if (input.is_open())
Gigg, Martyn Anthony
committed
{

Zhou, Wenduo
committed
// 1. First line: Title
if (!input.eof())
Gigg, Martyn Anthony
committed
{

Zhou, Wenduo
committed
// Get workspace title (should be first line or 2nd line for SLOG)
input.getline(currentLine, 256);
wsTitle = currentLine;
} // if
// 2. Loop all the lines
bool isOutOfHead = false;
bool slogtitleset = false;
bool multiplybybinwidth = false;
bool db1 = true;
int nSpec = 0;
bool calslogx0 = true;
double bc4 = 0;
double bc3 = 0;

Zhou, Wenduo
committed
while (!input.eof() && input.getline(currentLine, 256))
Gigg, Martyn Anthony
committed
{

Zhou, Wenduo
committed
if (nSpec != 0 && prog == NULL)
{
prog = new Progress(this, 0.0, 1.0, nSpec);
}
if (!slogtitleset)
Janik Zikovsky
committed
{

Zhou, Wenduo
committed
slogTitle = currentLine;
slogtitleset = true;
}

Zhou, Wenduo
committed
if (currentLine[0] == '\n' || currentLine[0] == '#')
{
// Comment/Information Line
Janik Zikovsky
committed

Zhou, Wenduo
committed
std::string key1, key2;
Janik Zikovsky
committed
std::istringstream inputLine(currentLine, std::ios::in);
inputLine.ignore(256, ' ');

Zhou, Wenduo
committed
inputLine >> key1 >> key2;
Janik Zikovsky
committed

Zhou, Wenduo
committed
if (key2 == "Histograms")
Janik Zikovsky
committed
{

Zhou, Wenduo
committed
// X Histograms
nSpec = atoi(key1.c_str());
g_log.debug() << "Histogram Line: " << key1 << " nSpec = " << nSpec << std::endl;
}
else if (key1 == "Instrument:")
{
// Instrument: XXXX
instrumentname = key2;
g_log.information() << "Instrument : " << key2 << std::endl;
}
else if (key1 == "with")
{
std::string s1;
inputLine >> s1;
if (s1 == "multiplied"){
multiplybybinwidth = true;

Zhou, Wenduo
committed
g_log.information() << "Y is multiplied by bin width" << std::endl;
} else {
g_log.debug() << "s1 = " << s1 << " is not allowed!\n";
}
Janik Zikovsky
committed
}

Zhou, Wenduo
committed
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
else if (key1 == "Primary")
{
// Primary flight path ...
std::string s1, s2;
inputLine >> s1 >> s2;
primaryflightpath = convertToDouble(s2);
g_log.information() << "L1 = " << primaryflightpath << std::endl;
}
else if (key1 == "Total")
{
// Total flight path .... ....
std::string s1, s2, s3, s4, s5, s6;
inputLine >> s1 >> s2 >> s3 >> s4 >> s5 >> s6;
double totalpath = convertToDouble(s2);
double tth = convertToDouble(s4);
double difc = convertToDouble(s6);
totalflightpaths.push_back(totalpath);
twothetas.push_back(tth);
difcs.push_back(difc);
g_log.information() << "Total flight path = " << totalpath << " 2Theta = " << tth << " DIFC = " << difc << std::endl;
} // if keys....
} // Line with #
else if (currentLine[0] == 'B')
{
// Line start with Bank including file format, X0 information and etc.
isOutOfHead = true;

Zhou, Wenduo
committed
// 1. Save the previous to array and initialze new MantiVec for (X, Y, E)
if (X->size() != 0)
{
gsasDataX.push_back(X);
gsasDataY.push_back(Y);
gsasDataE.push_back(E);
X = new MantidVec();
Y = new MantidVec();
E = new MantidVec();
if (prog != NULL)
prog->report();
}

Zhou, Wenduo
committed
// 2. Parse
Janik Zikovsky
committed

Zhou, Wenduo
committed
/* BANK <SpectraNo> <NBins> <NBins> RALF <BC1> <BC2> <BC1> <BC4>
* OR,
* BANK <SpectraNo> <NBins> <NBins> SLOG <BC1> <BC2> <BC3> 0>
* BC1 = X[0] * 32
* BC2 = X[1] * 32 - BC1
* BC4 = ( X[1] - X[0] ) / X[0]
*/
Gigg, Martyn Anthony
committed

Zhou, Wenduo
committed
// Parse B-line
int specno, nbin1, nbin2;
std::istringstream inputLine(currentLine, std::ios::in);
Janik Zikovsky
committed
double bc1 = 0;
double bc2 = 0;

Zhou, Wenduo
committed
/*
inputLine.ignore(256, 'F');
inputLine >> bc1 >> bc2 >> bc1 >> bc4;
*/
Gigg, Martyn Anthony
committed

Zhou, Wenduo
committed
inputLine.ignore(256, 'K');
std::string filetypestring;
Gigg, Martyn Anthony
committed

Zhou, Wenduo
committed
inputLine >> specno >> nbin1 >> nbin2 >> filetypestring;
g_log.debug() << "Bank: " << specno << " filetypestring = " << filetypestring << std::endl;
Janik Zikovsky
committed

Zhou, Wenduo
committed
detectorIDs.push_back(specno);

Zhou, Wenduo
committed
if (filetypestring[0] == 'S')
{
// SLOG
filetype = 's';
inputLine >> bc1 >> bc2 >> bc3 >> bc4;
}
else if (filetypestring[0] == 'R')
{
// RALF
filetype = 'r';
inputLine >> bc1 >> bc2 >> bc1 >> bc4;
}
else
{
g_log.error() << "Unsupported File Type: " << filetypestring << std::endl;
throw Exception::FileError("Not a GSAS file", filename);

Zhou, Wenduo
committed
}

Zhou, Wenduo
committed
// Determine x0
if (filetype == 'r')
{

Zhou, Wenduo
committed
g_log.debug() << "RALF: x0 = " << x0 << " bc4 = " << bc4 << std::endl;
X->push_back(x0);

Zhou, Wenduo
committed
else
{
// Cannot calculate x0, turn on the flag
calslogx0 = true;
}
} // Line with B
else if (isOutOfHead)

Zhou, Wenduo
committed
{
double xValue;
double yValue;
double eValue;

Zhou, Wenduo
committed
double xPrev;

Zhou, Wenduo
committed
// * Get previous X value
if (X->size() != 0)
{
xPrev = X->back();
}
else if (filetype == 'r')
{
// Except if RALF
throw Mantid::Kernel::Exception::NotImplementedError(
"LoadGSS: File was not in expected format.");
}
else
{
xPrev = -0.0;
}

Zhou, Wenduo
committed
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
std::istringstream inputLine(currentLine, std::ios::in);
inputLine >> xValue >> yValue >> eValue;
// It is different for the definition of X, Y, Z in SLOG and RALF format
if (filetype == 'r')
{
// RALF
double tempy = yValue;
xValue = (2 * xValue) - xPrev;
yValue = yValue / (xPrev * bc4);
eValue = eValue / (xPrev * bc4);
if (db1)
{
g_log.debug() << "Type: " << filetype << " xPrev = " << xPrev << " bc4 =" << bc4
<< std::endl;
g_log.debug() << "yValue = " << yValue << tempy << std::endl;
db1 = false;
}
} // filetype == r
else if (filetype == 's')
{
// SLOG
if (calslogx0)
{
// calculation of x0 must use the x'[0]
g_log.debug() << "x'_0 = " << xValue << " bc3 = " << bc3 << std::endl;
double x0 = 2 * xValue / (bc3 + 2.0);
X->push_back(x0);
xPrev = x0;
g_log.debug() << "SLOG: x0 = " << x0 << std::endl;
calslogx0 = false;
}
xValue = (2 * xValue) - xPrev;
if (multiplybybinwidth)
{
yValue = yValue / (xValue - xPrev);
eValue = eValue / (xValue - xPrev);
}
} // file type == s
// store read in data (x, y, e) to vector
X->push_back(xValue);
Y->push_back(yValue);
E->push_back(eValue);
} // Date Line
else{
g_log.debug() << "Line not defined: " << currentLine << std::endl;
}

Zhou, Wenduo
committed
} // while
// Clean up after file is read through
if (X->size() != 0)
{ // Put final spectra into data
gsasDataX.push_back(X);
gsasDataY.push_back(Y);
gsasDataE.push_back(E);
Janik Zikovsky
committed
}

Zhou, Wenduo
committed
input.close();
} // if input is_open
int nHist(static_cast<int> (gsasDataX.size()));
int xWidth(static_cast<int> (X->size()));
int yWidth(static_cast<int> (Y->size()));
// 2. Create workspace & GSS Files data is always in TOF
MatrixWorkspace_sptr outputWorkspace = boost::dynamic_pointer_cast<MatrixWorkspace>(
WorkspaceFactory::Instance().create("Workspace2D", nHist, xWidth, yWidth));
outputWorkspace->getAxis(0)->unit() = UnitFactory::Instance().create("TOF");
// 2.1 Set workspace title
if (filetype == 'r')
{
outputWorkspace->setTitle(wsTitle);
Gigg, Martyn Anthony
committed
}

Zhou, Wenduo
committed
else
{
outputWorkspace->setTitle(slogTitle);
Janik Zikovsky
committed
}
Gigg, Martyn Anthony
committed

Zhou, Wenduo
committed
// 2.2 Put data from MatidVec's into outputWorkspace
if (detectorIDs.size() != static_cast<size_t>(nHist))
{
mess << "Number of spectra (" << detectorIDs.size() << ") is not equal to number of histograms (" << nHist << ").";

Zhou, Wenduo
committed
for (int i = 0; i < nHist; ++i)
{
// Move data across
outputWorkspace->dataX(i) = *gsasDataX[i];
outputWorkspace->dataY(i) = *gsasDataY[i];
outputWorkspace->dataE(i) = *gsasDataE[i];
// Clean up after copy
delete gsasDataX[i];
delete gsasDataY[i];
delete gsasDataE[i];
// Reset spectrum number if
if (m_useBankAsSpectrum)
{
specid_t specno = static_cast<specid_t>(detectorIDs[i]);
outputWorkspace->getSpectrum(i)->setSpectrumNo(specno);
}

Zhou, Wenduo
committed
}
Gigg, Martyn Anthony
committed

Zhou, Wenduo
committed
// 2.3 Build instrument geometry
createInstrumentGeometry(outputWorkspace, instrumentname, primaryflightpath,
detectorIDs, totalflightpaths, twothetas);
Gigg, Martyn Anthony
committed
setProperty("OutputWorkspace", outputWorkspace);

Zhou, Wenduo
committed
// Clean up
delete prog;
if (!X)
delete X;
if (!Y)
delete Y;
if (!E)
delete E;

Zhou, Wenduo
committed
return;
}
Gigg, Martyn Anthony
committed

Zhou, Wenduo
committed
// Convert a string containing number and unit to double
double LoadGSS::convertToDouble(std::string inputstring)
{
Gigg, Martyn Anthony
committed

Zhou, Wenduo
committed
std::string temps = "";
int isize = (int)inputstring.size();
for (int i = 0; i < isize; i++)
Gigg, Martyn Anthony
committed
{

Zhou, Wenduo
committed
char thechar = inputstring[i];
if ((thechar <= 'Z' && thechar >= 'A') || (thechar <= 'z' && thechar >= 'a'))
{
break;
}
Peterson, Peter
committed
else
Janik Zikovsky
committed
{

Zhou, Wenduo
committed
temps += thechar;
Janik Zikovsky
committed
}
Gigg, Martyn Anthony
committed
}
Janik Zikovsky
committed

Zhou, Wenduo
committed
double rd = atof(temps.c_str());
return rd;
}
/* Create the instrument geometry with Instrument
*
*/
void LoadGSS::createInstrumentGeometry(MatrixWorkspace_sptr workspace, std::string instrumentname, double primaryflightpath,
std::vector<int> detectorids, std::vector<double> totalflightpaths, std::vector<double> twothetas){

Zhou, Wenduo
committed
g_log.information() << "L1 = " << primaryflightpath << std::endl;
if (detectorids.size() != totalflightpaths.size() || totalflightpaths.size() != twothetas.size()){
g_log.warning() << "Cannot create geometry, because the numbers of L2 and Polar are not equal." << std::endl;

Zhou, Wenduo
committed
return;
}
for (size_t i = 0; i < detectorids.size(); i ++){
g_log.debug() << "Detector " << detectorids[i] << " L1+L2 = " << totalflightpaths[i] << " 2Theta = " << twothetas[i] << std::endl;
Janik Zikovsky
committed
}
Gigg, Martyn Anthony
committed
Russell Taylor
committed
// 1. Create a new instrument and set its name
Geometry::Instrument_sptr instrument(new Geometry::Instrument(instrumentname));
workspace->setInstrument(instrument);

Zhou, Wenduo
committed
// 3. Add dummy source and samplepos to instrument
Geometry::ObjComponent *samplepos = new Geometry::ObjComponent("Sample",instrument.get());
instrument->add(samplepos);
instrument->markAsSamplePos(samplepos);
samplepos->setPos(0.0,0.0,0.0);
Geometry::ObjComponent *source = new Geometry::ObjComponent("Source",instrument.get());
instrument->add(source);
instrument->markAsSource(source);
double l1 = primaryflightpath;
source->setPos(0.0,0.0,-1.0*l1);
// 4. add detectors
// The L2 and 2-theta values from Raw file assumed to be relative to sample position
const int numDetector = (int)detectorids.size(); // number of detectors
std::vector<int> detID = detectorids; // detector IDs
std::vector<double> angle = twothetas; // angle between indicent beam and direction from sample to detector (two-theta)
// Assumption: detector IDs are in the same order of workspace index

Zhou, Wenduo
committed
for (int i = 0; i < numDetector; ++i)
{
// a) Create a new detector. Instrument will take ownership of pointer so no need to delete.

Zhou, Wenduo
committed
Geometry::Detector *detector = new Geometry::Detector("det",detID[i],samplepos);
Kernel::V3D pos;

Zhou, Wenduo
committed
double r = totalflightpaths[i] - l1;
pos.spherical(r, angle[i], 0.0 );
detector->setPos(pos);
// add copy to instrument, spectrum and mark it
API::ISpectrum *spec = workspace->getSpectrum(i);
if (!spec){
g_log.error() << "Workspace " << i << " has no spectrum!" << std::endl;
continue;
} else {
spec->clearDetectorIDs();
spec->addDetectorID(detID[i]);
}

Zhou, Wenduo
committed
instrument->add(detector);
instrument->markAsDetector(detector);
}
return;
}
}//namespace
Janik Zikovsky
committed
}//namespace