7#include <boost/algorithm/string.hpp>
21#include <boost/algorithm/string/finder.hpp>
22#include <boost/algorithm/string/iter_find.hpp>
29using Mantid::Types::Core::DateAndTime;
38 if (s.size() < subs.size())
42 std::string tail = s.substr(s.size() - subs.size());
49 std::sort(v1.begin(), v1.end());
50 std::sort(v2.begin(), v2.end());
53 std::vector<std::string> intersectvec(v1.size() + v2.size());
54 auto outiter = std::set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), intersectvec.begin());
55 return static_cast<int>(outiter - intersectvec.begin()) != 0;
87 "Name of SPICE data file.");
90 auto floatspckeyprop = std::make_unique<ArrayProperty<std::string>>(
"FloatSampleLogNames",
Direction::Input);
91 declareProperty(std::move(floatspckeyprop),
"List of log names that will be imported as float property.");
94 auto intspckeyprop = std::make_unique<ArrayProperty<std::string>>(
"IntegerSampleLogNames",
Direction::Input);
95 declareProperty(std::move(intspckeyprop),
"List of log names that will be imported as integer property.");
98 auto strspckeyprop = std::make_unique<ArrayProperty<std::string>>(
"StringSampleLogNames",
Direction::Input);
99 declareProperty(std::move(strspckeyprop),
"List of log names that will be imported as string property.");
102 "If it is true, all log names are not listed in any of above "
103 "3 input lists will be ignored. "
104 "Otherwise, any log name is not listed will be treated as "
109 std::vector<std::string> defaultlogformat(4);
110 defaultlogformat[0] =
"date";
111 defaultlogformat[1] =
"MM/DD/YYYY";
112 defaultlogformat[2] =
"time";
113 defaultlogformat[3] =
"HH:MM:SS AM";
115 "Name and format for date and time");
119 "Name of TableWorkspace containing experimental data.");
122 "Name of TableWorkspace containing experimental information.");
131 std::vector<std::string> strlognames =
getProperty(
"StringSampleLogNames");
132 std::vector<std::string> intlognames =
getProperty(
"IntegerSampleLogNames");
133 std::vector<std::string> floatlognames =
getProperty(
"FloatSampleLogNames");
134 bool ignoreunlisted =
getProperty(
"IgnoreUnlistedLogs");
135 std::vector<std::string> datetimeprop =
getProperty(
"DateAndTimeLog");
139 throw std::runtime_error(
"At one log name appears in multiple log type lists");
142 std::vector<std::vector<std::string>> datalist;
143 std::vector<std::string> titles;
144 std::map<std::string, std::string> runinfodict;
152 createRunInfoWS(runinfodict, floatlognames, intlognames, strlognames, ignoreunlisted);
171 const std::vector<std::string> &intlognames,
172 const std::vector<std::string> &strlognames) {
173 std::vector<std::vector<std::string>> vec_lognamelist;
174 vec_lognamelist.emplace_back(floatlognames);
175 vec_lognamelist.emplace_back(intlognames);
176 vec_lognamelist.emplace_back(strlognames);
179 bool hascommon =
false;
180 for (
size_t i = 0; i < 3; ++i)
181 for (
size_t j = i + 1; j < 3; ++j) {
184 std::stringstream ess;
185 ess <<
"logsets[" << i <<
"] and log sets[" << j <<
"] has intersection.";
203 std::vector<std::string> &titles,
204 std::map<std::string, std::string> &runinfodict) {
206 std::ifstream spicefile(filename.c_str());
207 if (!spicefile.is_open()) {
208 std::stringstream ess;
209 ess <<
"File " << filename <<
" cannot be opened.";
210 throw std::runtime_error(ess.str());
214 while (std::getline(spicefile, line)) {
224 if (line[0] ==
'#') {
229 if (line.find(
'=') != std::string::npos) {
231 std::vector<std::string> terms;
232 boost::split(terms, line, boost::is_any_of(
"="));
233 boost::trim(terms[0]);
234 g_log.
debug() <<
"Title = " << terms[0] <<
", number of splitted terms = " << terms.size() <<
"\n";
235 std::string infovalue;
236 if (terms.size() == 2) {
237 infovalue = terms[1];
238 boost::trim(infovalue);
239 }
else if (terms.size() > 2) {
241 for (
size_t j = 1; j < terms.size(); ++j) {
244 infovalue += terms[j];
247 std::stringstream wss;
248 wss <<
"Line '" << line <<
"' is hard to parse. It has more than 1 '='.";
251 runinfodict.emplace(terms[0], infovalue);
252 }
else if (line.find(
"Pt.") != std::string::npos) {
254 boost::split(titles, line, boost::is_any_of(
"\t\n "), boost::token_compress_on);
255 }
else if (
endswith(line,
"scan completed.")) {
256 std::vector<std::string> terms;
257 boost::iter_split(terms, line, boost::algorithm::first_finder(
"scan completed."));
258 std::string time = terms.front();
260 runinfodict.emplace(
"runend", time);
263 std::stringstream wss;
264 wss <<
"File " << filename <<
": line \"" << line <<
"\" cannot be parsed. It is ignored then.";
270 std::vector<std::string> terms;
271 boost::split(terms, line, boost::is_any_of(
" \t\n"), boost::token_compress_on);
272 datalist.emplace_back(terms);
276 g_log.
debug() <<
"Run info dictionary has " << runinfodict.size() <<
" entries."
289 const std::vector<std::string> &titles) {
293 for (
size_t i = 0; i < titles.size(); ++i) {
294 if (titles[i] ==
"Pt.") {
295 outws->addColumn(
"int", titles[i]);
298 outws->addColumn(
"double", titles[i]);
303 size_t numrows = datalist.size();
304 size_t numcols = outws->columnCount();
305 for (
size_t irow = 0; irow < numrows; ++irow) {
306 TableRow newrow = outws->appendRow();
307 for (
size_t icol = 0; icol < numcols; ++icol) {
308 std::string item = datalist[irow][icol];
310 newrow << std::stoi(item);
312 newrow << std::stod(item);
331 std::vector<std::string> &floatlognamelist,
332 std::vector<std::string> &intlognamelist,
333 std::vector<std::string> &strlognamelist,
334 bool ignoreunlisted) {
339 std::sort(floatlognamelist.begin(), floatlognamelist.end());
340 std::sort(intlognamelist.begin(), intlognamelist.end());
341 std::sort(strlognamelist.begin(), strlognamelist.end());
344 std::map<std::string, std::string>::iterator miter;
345 for (miter = runinfodict.begin(); miter != runinfodict.end(); ++miter) {
346 const std::string title = miter->first;
347 const std::string strvalue = miter->second;
349 g_log.
debug() <<
"Trying to add property " << title <<
" with value " << strvalue <<
"\n";
351 if (std::binary_search(floatlognamelist.begin(), floatlognamelist.end(), title)) {
353 bool adderrorvalue =
false;
357 if (strvalue.find(
"+/-") != std::string::npos) {
358 adderrorvalue =
true;
360 std::vector<std::string> terms;
361 boost::iter_split(terms, strvalue, boost::algorithm::first_finder(
"+/-"));
362 value = std::stod(terms[0]);
363 error = std::stod(terms[1]);
365 value = std::stod(strvalue);
370 addProperty<double>(infows, title,
value);
372 std::stringstream tss;
373 tss << title <<
".error";
374 addProperty<double>(infows, tss.str(),
error);
376 }
else if (std::binary_search(intlognamelist.begin(), intlognamelist.end(), title)) {
378 addProperty<int>(infows, title, std::stoi(strvalue));
379 }
else if (!ignoreunlisted || std::binary_search(strlognamelist.begin(), strlognamelist.end(), title)) {
381 addProperty<std::string>(infows, title, strvalue);
395 const std::vector<std::string> &datetimeprop) {
397 if (datetimeprop.empty()) {
403 if (datetimeprop.size() != 4) {
404 g_log.
warning() <<
"Run start date and time property must contain 4 "
405 "strings. User only specifies "
406 << datetimeprop.size() <<
". Set up failed."
412 std::string datelogname = datetimeprop[0];
413 std::string timelogname = datetimeprop[2];
414 if (!(runinfows->run().hasProperty(datelogname) && runinfows->run().hasProperty(timelogname))) {
415 std::stringstream errss;
416 errss <<
"Unable to locate user specified date and time sample logs " << datelogname <<
" and " << timelogname
418 <<
"run_start will not be set up.";
423 const std::string &rawdatestring = runinfows->run().getProperty(datelogname)->value();
424 const std::string &dateformat = datetimeprop[1];
427 const std::string &rawtimestring = runinfows->run().getProperty(timelogname)->value();
428 const std::string &timeformat = datetimeprop[3];
431 std::string mtddatetimestr = mtddatestring +
"T" + mtdtimestring;
434 DateAndTime runstart(mtddatetimestr);
435 addProperty<std::string>(runinfows,
"run_start", runstart.toISO8601String());
447 std::string splitter;
448 if (dateformat.find(
'/') != std::string::npos)
450 else if (dateformat.find(
'-') != std::string::npos)
452 else if (dateformat.find(
'.') != std::string::npos)
455 throw std::runtime_error(
"Input date format does not contain any of / - "
456 "or '.'. Format unsupported.");
459 std::vector<std::string> dateterms;
460 std::vector<std::string> formatterms;
461 boost::split(dateterms, rawdate, boost::is_any_of(splitter));
462 boost::split(formatterms, dateformat, boost::is_any_of(splitter));
464 if (dateterms.size() != formatterms.size() || dateterms.size() != 3)
465 throw std::runtime_error(
"Unsupported date string and format");
469 for (
size_t i = 0; i < 3; ++i) {
470 if (formatterms[i].find(
'Y') != std::string::npos)
472 else if (formatterms[i].find(
'M') != std::string::npos) {
473 month = dateterms[i];
474 if (month.size() == 1)
475 month.insert(0, 1,
'0');
479 day.insert(0, 1,
'0');
483 std::string formatdate = year +
"-" + month +
"-" + day;
497 std::string timeformatcpy(timeformat);
498 boost::trim(timeformatcpy);
501 if (timeformatcpy.find(
' ') == std::string::npos)
511 std::vector<std::string> terms;
512 boost::split(terms, rawtime, boost::is_any_of(
" "));
514 if (terms[1] ==
"PM")
517 std::vector<std::string> terms2;
518 boost::split(terms2, terms[0], boost::is_any_of(
":"));
519 int hour = std::stoi(terms[0]);
523 std::stringstream hourss;
525 std::string hourstr = hourss.str();
526 if (hourstr.size() == 1)
527 hourstr =
"0" + hourstr;
528 std::string minstr = terms2[1];
529 if (minstr.size() == 1)
530 minstr =
"0" + minstr;
531 std::string secstr = terms2[2];
532 if (secstr.size() == 1)
533 secstr =
"0" + secstr;
535 mtdtime = hourstr +
":" + minstr +
":" + secstr;
#define DECLARE_ALGORITHM(classname)
double value
The value of the point.
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
TableRow represents a row in a TableWorkspace.
A property class for workspaces.
LoadSpiceAscii : TODO: DESCRIPTION.
void exec() override
Exec.
const std::string name() const override
Name.
void setupRunStartTime(const API::MatrixWorkspace_sptr &runinfows, const std::vector< std::string > &datetimeprop)
Set up run start time.
const std::string summary() const override
Summary.
bool validateLogNamesType(const std::vector< std::string > &floatlognames, const std::vector< std::string > &intlognames, const std::vector< std::string > &strlognames)
Check whether 3 sets of values have intersection.
int version() const override
Version.
void init() override
Declaration of properties.
const std::string category() const override
Category.
std::string processTimeString(const std::string &rawtime, const std::string &timeformat)
Convert input time string to mantid time string.
API::MatrixWorkspace_sptr createRunInfoWS(std::map< std::string, std::string > runinfodict, std::vector< std::string > &floatlognamelist, std::vector< std::string > &intlognamelist, std::vector< std::string > &strlognamelist, bool ignoreunlisted)
Create run information workspace.
std::string processDateString(const std::string &rawdate, const std::string &dateformat)
Convert input date string to mantid date string.
void parseSPICEAscii(const std::string &filename, std::vector< std::vector< std::string > > &datalist, std::vector< std::string > &titles, std::map< std::string, std::string > &runinfodict)
Parse SPICE Ascii file to dictionary.
API::ITableWorkspace_sptr createDataWS(const std::vector< std::vector< std::string > > &datalist, const std::vector< std::string > &titles)
Create data workspace.
void addProperty(const API::MatrixWorkspace_sptr &ws, const std::string &pname, T pvalue)
Add property to workspace.
Support for a property that holds an array of values.
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.
The concrete, templated class for properties.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
std::shared_ptr< ITableWorkspace > ITableWorkspace_sptr
shared pointer to Mantid::API::ITableWorkspace
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
static bool checkIntersection(std::vector< std::string > v1, std::vector< std::string > v2)
static bool endswith(const std::string &s, const std::string &subs)
std::shared_ptr< TableWorkspace > TableWorkspace_sptr
shared pointer to Mantid::DataObjects::TableWorkspace
@ Input
An input workspace.
@ Output
An output workspace.