24#include <boost/regex.hpp>
39const boost::regex DET_POS_REG_EXP{
"^#.+flight path\\s+([0-9.]+).+"
42const boost::regex L1_REG_EXP{
"^#.+flight path\\s+([0-9.]+)\\s*m"};
57 std::istream &file = descriptor.
data();
58 std::getline(file, str);
60 std::getline(file, str);
63 if (str.empty() || str[0] ==
'#' || str.compare(0, 8,
"Monitor:") == 0) {
66 if (str.compare(0, 4,
"BANK") == 0 &&
67 (str.find(
"RALF") != std::string::npos || str.find(
"SLOG") != std::string::npos) &&
68 (str.find(
"FXYE") != std::string::npos)) {
79 const std::vector<std::string> exts{
".gsa",
".gss",
".gda",
".txt"};
81 "The input filename of the stored data");
84 "Workspace name to load into.");
87 "If true, spectrum number corresponding to each bank is to "
98 bool useBankAsSpectrum =
getProperty(
"UseBankIDasSpectrumNumber");
110 double primaryflightpath = -1;
111 std::vector<double> twothetas;
112 std::vector<double> difcs;
113 std::vector<double> totalflightpaths;
114 std::vector<int> detectorIDs;
117 std::vector<HistogramData::BinEdges> gsasDataX;
118 std::vector<HistogramData::Counts> gsasDataY;
119 std::vector<HistogramData::CountStandardDeviations> gsasDataE;
121 std::vector<double> vecX, vecY, vecE;
124 std::unique_ptr<Progress> prog =
nullptr;
127 char currentLine[256];
129 std::string slogTitle;
130 std::string instrumentname =
"Generic";
134 std::ifstream input(filename.c_str(), std::ios_base::in);
135 if (!input.is_open()) {
137 std::stringstream errss;
138 errss <<
"Unable to open GSAS file " << filename;
139 throw std::runtime_error(errss.str());
145 input.getline(currentLine, 256);
146 wsTitle = currentLine;
148 throw std::runtime_error(
"File is empty");
152 bool isOutOfHead =
false;
153 bool slogtitleset =
false;
154 bool multiplybybinwidth =
false;
156 bool calslogx0 =
true;
160 while (!input.eof() && input.getline(currentLine, 256)) {
162 if (nSpec != 0 && !prog) {
163 prog = std::make_unique<Progress>(
this, 0.0, 1.0, nSpec);
168 slogTitle = currentLine;
172 if (currentLine[0] ==
'\n' || currentLine[0] ==
'#') {
174 std::string key1, key2;
175 std::istringstream inputLine(currentLine, std::ios::in);
176 inputLine.ignore(256,
' ');
177 inputLine >> key1 >> key2;
179 if (key2 ==
"Histograms") {
181 nSpec = std::stoi(key1);
182 g_log.
information() <<
"Histogram Line: " << key1 <<
" nSpec = " << nSpec <<
"\n";
183 }
else if (key1 ==
"Instrument:") {
185 instrumentname = key2;
187 }
else if (key1 ==
"with") {
191 if (s1 ==
"multiplied") {
192 multiplybybinwidth =
true;
195 g_log.
warning() <<
"In line '" << currentLine <<
"', key word " << s1 <<
" is not allowed!\n";
197 }
else if (key1 ==
"Primary") {
199 boost::smatch result;
203 const std::string line = inputLine.str();
204 if (boost::regex_search(line, result, L1_REG_EXP) && result.size() == 2) {
205 primaryflightpath = std::stod(std::string(result[1]));
208 std::stringstream msg;
209 msg <<
"Failed to parse primary flight path from line \"" << inputLine.str() <<
"\"";
213 std::stringstream msg;
214 msg <<
"L1 = " << primaryflightpath;
216 }
else if (key1 ==
"Total") {
220 double totalpath(0.f);
224 boost::smatch result;
225 const std::string line = inputLine.str();
226 if (boost::regex_search(line, result, DET_POS_REG_EXP) && result.size() == 4) {
227 totalpath = std::stod(std::string(result[1]));
228 tth = std::stod(std::string(result[2]));
229 difc = std::stod(std::string(result[3]));
231 std::stringstream msg;
232 msg <<
"Failed to parse position from line \"" << inputLine.str() <<
"\"";
236 totalflightpaths.emplace_back(totalpath);
237 twothetas.emplace_back(tth);
238 difcs.emplace_back(
difc);
240 std::stringstream msg;
241 msg <<
"Bank " << difcs.size() - 1 <<
": Total flight path = " << totalpath <<
" 2Theta = " << tth
242 <<
" DIFC = " <<
difc;
247 else if (currentLine[0] ==
'B') {
254 gsasDataX.emplace_back(std::move(vecX));
255 gsasDataY.emplace_back(std::move(vecY));
256 gsasDataE.emplace_back(std::move(vecE));
273 int specno, nbin1, nbin2;
274 std::istringstream inputLine(currentLine, std::ios::in);
279 inputLine.ignore(256,
'K');
280 std::string filetypestring;
282 inputLine >> specno >> nbin1 >> nbin2 >> filetypestring;
283 g_log.
debug() <<
"Bank: " << specno <<
" filetypestring = " << filetypestring <<
'\n';
285 detectorIDs.emplace_back(specno);
287 if (filetypestring[0] ==
'S') {
290 inputLine >> bc1 >> bc2 >> bc3 >> bc4;
291 }
else if (filetypestring[0] ==
'R') {
294 inputLine >> bc1 >> bc2 >> bc1 >> bc4;
296 g_log.
error() <<
"Unsupported GSAS File Type: " << filetypestring <<
"\n";
301 if (filetype ==
'r') {
302 double x0 = bc1 / 32;
303 g_log.
debug() <<
"RALF: x0 = " << x0 <<
" bc4 = " << bc4 <<
'\n';
304 vecX.emplace_back(x0);
310 else if (isOutOfHead) {
321 }
else if (filetype ==
'r') {
329 if (filetype ==
'r') {
336 std::string str(currentLine, 15);
337 std::istringstream istr(str);
341 std::string str(currentLine + 15, 18);
342 std::istringstream istr(str);
346 std::string str(currentLine + 15 + 18, 18);
347 std::istringstream istr(str);
351 xValue = (2 * xValue) - xPrev;
353 }
else if (filetype ==
's') {
355 std::istringstream inputLine(currentLine, std::ios::in);
356 inputLine >> xValue >> yValue >> eValue;
359 g_log.
debug() <<
"x'_0 = " << xValue <<
" bc3 = " << bc3 <<
'\n';
361 double x0 = 2 * xValue / (bc3 + 2.0);
362 vecX.emplace_back(x0);
368 xValue = (2 * xValue) - xPrev;
370 g_log.
error() <<
"Unsupported GSAS File Type: " << filetype <<
"\n";
374 if (multiplybybinwidth) {
375 yValue = yValue / (xValue - xPrev);
376 eValue = eValue / (xValue - xPrev);
380 vecX.emplace_back(xValue);
381 vecY.emplace_back(yValue);
382 vecE.emplace_back(eValue);
385 g_log.
warning() <<
"Line not defined: " << currentLine <<
'\n';
390 auto nHist(
static_cast<int>(gsasDataX.size()));
391 auto xWidth(
static_cast<int>(vecX.size()));
392 auto yWidth(
static_cast<int>(vecY.size()));
396 gsasDataX.emplace_back(std::move(vecX));
397 gsasDataY.emplace_back(std::move(vecY));
398 gsasDataE.emplace_back(std::move(vecE));
415 outputWorkspace->setTitle(wsTitle);
417 outputWorkspace->setTitle(slogTitle);
420 if (detectorIDs.size() !=
static_cast<size_t>(nHist)) {
422 std::ostringstream mess(
"");
423 mess <<
"Number of spectra (" << detectorIDs.size() <<
") is not equal to number of histograms (" << nHist <<
").";
424 throw std::runtime_error(mess.str());
427 for (
int i = 0; i < nHist; ++i) {
429 outputWorkspace->setHistogram(i, BinEdges(std::move(gsasDataX[i])), Counts(std::move(gsasDataY[i])),
430 CountStandardDeviations(std::move(gsasDataE[i])));
433 if (useBankAsSpectrum) {
434 auto specno =
static_cast<specnum_t>(detectorIDs[i]);
435 outputWorkspace->getSpectrum(i).setSpectrumNo(specno);
440 createInstrumentGeometry(outputWorkspace, instrumentname, primaryflightpath, detectorIDs, totalflightpaths, twothetas,
443 return outputWorkspace;
451 auto isize =
static_cast<int>(inputstring.size());
452 for (
int i = 0; i < isize; i++) {
453 char thechar = inputstring[i];
454 if ((thechar <= 'Z' && thechar >=
'A') || (thechar <= 'z' && thechar >=
'a')) {
461 double rd = std::stod(temps);
470 const double &primaryflightpath,
const std::vector<int> &detectorids,
471 const std::vector<double> &totalflightpaths,
472 const std::vector<double> &twothetas,
const std::vector<double> &difcs) {
474 if (detectorids.size() != totalflightpaths.size() || totalflightpaths.size() != twothetas.size()) {
475 g_log.
warning(
"Cannot create geometry, because the numbers of L2 and Polar "
481 std::stringstream dbss;
482 dbss <<
"L1 = " << primaryflightpath <<
"\n";
483 for (
size_t i = 0; i < detectorids.size(); i++) {
484 dbss <<
"Detector " << detectorids[i] <<
" L1+L2 = " << totalflightpaths[i] <<
" 2Theta = " << twothetas[i]
494 instrument->add(samplepos);
495 instrument->markAsSamplePos(samplepos);
496 samplepos->
setPos(0.0, 0.0, 0.0);
499 instrument->add(source);
500 instrument->markAsSource(source);
502 double l1 = primaryflightpath;
503 source->
setPos(0.0, 0.0, -1.0 * l1);
508 const auto numDetector =
static_cast<int>(detectorids.size());
514 for (
int i = 0; i < numDetector; ++i) {
521 double r = totalflightpaths[i] - l1;
528 spec.clearDetectorIDs();
529 spec.addDetectorID(detectorids[i]);
530 instrument->add(detector);
531 instrument->markAsDetector(detector);
536 auto ¶mMap =
workspace->instrumentParameters();
537 for (
size_t i = 0; i <
workspace->getNumberHistograms(); i++) {
538 auto detector =
workspace->getDetector(i);
539 paramMap.addDouble(detector->getComponentID(),
"DIFC", difcs[i]);
IPeaksWorkspace_sptr workspace
#define DECLARE_FILELOADER_ALGORITHM(classname)
DECLARE_FILELOADER_ALGORITHM should be used in place of the standard DECLARE_ALGORITHM macro when wri...
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
@ Load
allowed here which will be passed to the algorithm
A property class for workspaces.
Loads a file as saved by SaveGSS.
void createInstrumentGeometry(const API::MatrixWorkspace_sptr &workspace, const std::string &instrumentname, const double &primaryflightpath, const std::vector< int > &detectorids, const std::vector< double > &totalflightpaths, const std::vector< double > &twothetas, const std::vector< double > &difcs)
Create an instrument geometry.
double convertToDouble(std::string inputstring)
Convert a string (value+unit) to double (value)
void exec() override
Execution code.
int confidence(Kernel::FileDescriptor &descriptor) const override
Returns a confidence value that this algorithm can load a file.
void init() override
Initialisation code.
API::MatrixWorkspace_sptr loadGSASFile(const std::string &filename, bool useBankAsSpectrum)
Main method to load GSAS.
Component is a wrapper for a Component which can modify some of its parameters, e....
void setPos(double, double, double) override
Set the IComponent position, x, y, z respective to parent (if present)
This class represents a detector - i.e.
Object Component class, this class brings together the physical attributes of the component to the po...
Records the filename and the description of failure.
Marks code as not implemented yet.
Defines a wrapper around an open file.
static bool isAscii(const std::string &filename, const size_t nbytes=256)
Returns true if the file is considered ascii.
std::istream & data()
Access the open file stream.
const std::string & extension() const
Access the file extension.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void debug(const std::string &msg)
Logs at debug level.
void error(const std::string &msg)
Logs at error level.
void warning(const std::string &msg)
Logs at warning level.
void information(const std::string &msg)
Logs at information level.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
void spherical(const double R, const double theta, const double phi) noexcept
Sets the vector position based on spherical coordinates.
Kernel::Logger g_log("ExperimentInfo")
static logger object
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::unique_ptr< T > create(const P &parent, const IndexArg &indexArg, const HistArg &histArg)
This is the create() method that all the other create() methods call.
std::shared_ptr< Instrument > Instrument_sptr
Shared pointer to an instrument object.
int32_t specnum_t
Typedef for a spectrum Number.
@ Output
An output workspace.