17#include <boost/date_time/posix_time/posix_time.hpp>
18#include <boost/regex.hpp>
19#include <boost/scoped_array.hpp>
21#include <Poco/DateTimeFormat.h>
22#include <Poco/DateTimeParser.h>
23#include <Poco/DirectoryIterator.h>
39using namespace Kernel;
44 :
Algorithm(), m_isisRaw(
std::make_unique<
ISISRAW2>()), handle(), rawFile(), nper(0), nsp(0), ntc(0), nmon(0),
45 ndet(0), counts_link(), period_index_link(), spectrum_index_link(), time_of_flight_link(),
46 time_of_flight_raw_link() {}
52 const std::vector<std::string> inputExts{
".raw",
".s*",
".add"};
54 "The name of the RAW file to read, including its full or relative\n"
55 "path. (N.B. case sensitive if running on Linux).");
59 const std::vector<std::string> outputExts{
".nxs",
".nx5",
".xml"};
61 "The name of the Nexus file to write, as a full or relative\n"
102 m_isisRaw = std::make_unique<ISISRAW2>();
120 status = NXopen(outputFilename.c_str(), NXACC_CREATE5, &
handle);
121 if (status != NX_OK) {
122 throw std::runtime_error(
"Cannot open file " + outputFilename +
" for writing.");
124 NXmakegroup(
handle,
"raw_data_1",
"NXentry");
125 NXopengroup(
handle,
"raw_data_1",
"NXentry");
129 flt =
static_cast<float>(
m_isisRaw->rpb.r_dur);
136 putAttr(
"url",
"http://definition.nexusformat.org/instruments/TOFRAW/?version=1.0");
141 putAttr(
"url",
"http://svn.isis.rl.ac.uk/instruments/ISISTOFRAW/?version=1.0");
144 flt =
static_cast<float>(
m_isisRaw->rpb.r_dur);
170 saveChar(
"experiment_identifier", &experiment_identifier[0],
static_cast<int>(experiment_identifier.size()));
172 saveInt(
"measurement_first_run", &tmp_int);
310 if (str_vec.empty()) {
314 int buff_size = max_str_size;
316 for (
const auto &str : str_vec) {
317 buff_size = std::max(buff_size,
int(str.size()));
321 auto buff =
new char[buff_size];
323 dim[0] =
static_cast<int>(str_vec.size());
327 for (std::size_t i = 0; i < str_vec.size(); ++i) {
328 int start[] = {
static_cast<int>(i), 0};
329 int sizes[] = {1, buff_size};
330 const char *str = str_vec[i].c_str();
331 std::fill_n(buff, buff_size,
' ');
332 int n = std::min(buff_size,
int(str_vec[i].size()));
333 std::copy(str, str +
n, buff);
334 NXputslab(
handle, buff, start, sizes);
348 std::string buff(str);
349 saveChar(
name, &buff[0],
static_cast<int>(buff.size()));
360 std::string buff(str);
365 boost::scoped_array<char> buff(
new char[
value.size()]);
366 std::copy(
value.begin(),
value.end(), buff.get());
367 NXputattr(
handle,
name, buff.get(),
static_cast<int>(
value.size()), NX_CHAR);
375 static const std::string months[] = {
"JAN",
"FEB",
"MAR",
"APR",
"MAY",
"JUN",
376 "JUL",
"AUG",
"SEP",
"OCT",
"NOV",
"DEC"};
377 static const std::string monthsn[] = {
"01",
"02",
"03",
"04",
"05",
"06",
"07",
"08",
"09",
"10",
"11",
"12"};
378 const std::string mon = str.substr(3, 3);
379 const std::string *i = std::find(months, months + 12, mon);
380 std::string iso8601 = str.substr(7, 4) +
"-" + monthsn[i - months] +
"-" + str.substr(0, 2);
386 NXmakegroup(
handle,
"isis_vms_compat",
"IXvms");
387 NXopengroup(
handle,
"isis_vms_compat",
"IXvms");
428 std::string user_info(160,
' ');
447 for (
int i = 0; i <
n; ++i) {
458 NXmakegroup(
handle,
"instrument",
"NXinstrument");
459 NXopengroup(
handle,
"instrument",
"NXinstrument");
471 NXmakegroup(
handle,
"detector_1",
"NXdata");
472 NXopengroup(
handle,
"detector_1",
"NXdata");
474 for (
int i = 0; i <
nmon; ++i) {
485 NXmakedata(
handle,
"counts", NX_INT32, 3, dim);
486 NXopendata(
handle,
"counts");
489 putAttr(
"axes",
"period_index,spectrum_index,time_of_flight");
491 int size[] = {1, 1,
ntc};
493 for (
int p = 0; p <
nper; ++p) {
496 for (
int si = 0; si <
nsp; ++si) {
502 int start[] = {p, ispec, 0};
514 std::vector<int> spec_minus_monitors(
nsp -
nmon);
523 std::vector<float> float_vec(
ndet -
nmon);
548 NXmakegroup(
handle,
"moderator",
"NXmoderator");
549 NXopengroup(
handle,
"moderator",
"NXmoderator");
562 NXmakegroup(
handle,
"source",
"NXsource");
563 NXopengroup(
handle,
"source",
"NXsource");
577 NXmakegroup(
handle,
"detector_1",
"NXdata");
578 NXopengroup(
handle,
"detector_1",
"NXdata");
599 for (
int i = 0; i <
nmon; ++i) {
612 int size[] = {1, 1,
ntc};
613 std::ostringstream ostr;
615 ostr <<
"monitor_" << mon_num;
616 NXmakegroup(
handle, ostr.str().c_str(),
"NXmonitor");
617 NXopengroup(
handle, ostr.str().c_str(),
"NXmonitor");
620 NXmakedata(
handle,
"data", NX_INT32, 3, dim);
621 NXopendata(
handle,
"data");
622 for (
int p = 0; p <
nper; ++p) {
623 int start[] = {p, 0, 0};
628 putAttr(
"axes",
"period_index,spectrum_index,time_of_flight");
631 saveInt(
"monitor_number", &mon_num);
640 NXmakegroup(
handle,
"dae",
"IXdae");
641 NXopengroup(
handle,
"dae",
"IXdae");
651 NXmakegroup(
handle,
"time_channels_1",
"IXtime_channels");
652 NXopengroup(
handle,
"time_channels_1",
"IXtime_channels");
654 boost::scoped_array<float> timeChannels(
new float[
ntc + 1]);
655 m_isisRaw->getTimeChannels(timeChannels.get(),
ntc + 1);
659 putAttr(
"units",
"microseconds");
665 putAttr(
"frequency",
"32 MHz");
675 NXmakegroup(
handle,
"user_1",
"NXuser");
676 NXopengroup(
handle,
"user_1",
"NXuser");
685 NXmakegroup(
handle,
"sample",
"NXsample");
686 NXopengroup(
handle,
"sample",
"NXsample");
695 std::string shape[] = {
"cylinder",
"flat plate",
"HRPD slab",
"unknown"};
700 std::string type[] = {
"sample+can",
"empty can",
"vanadium",
"absorber",
"nothing",
"sample, no can",
"unknown"};
715 std::string ICPevent_filename;
716 std::string::size_type i = ICPstatus_filename.find_last_of(
'.');
717 if (i != std::string::npos)
719 ICPstatus_filename.erase(i);
721 ICPevent_filename = ICPstatus_filename +
"_ICPevent.txt";
722 ICPstatus_filename +=
"_ICPstatus.txt";
724 std::ifstream fil(ICPstatus_filename.c_str());
726 g_log.
warning(
"Cannot find the ICPstatus file. Skipping runlog");
731 std::vector<float> time_vec;
732 std::vector<int> period_vec;
733 std::vector<int> is_running_vec;
734 std::vector<int> is_waiting_vec;
735 std::vector<int> good_frames_vec;
736 std::vector<int> raw_frames_vec;
737 std::vector<int> monitor_sum_1_vec;
738 std::vector<int> total_counts_vec;
739 std::vector<int> run_status_vec;
740 std::vector<float> proton_charge_vec;
741 std::vector<float> proton_charge_raw_vec;
742 std::vector<float> dae_beam_current_vec;
743 std::vector<float> count_rate_vec;
744 std::vector<float> np_ratio_vec;
747 boost::posix_time::ptime start_time(boost::posix_time::time_from_string(
start_time_str));
750 std::getline(fil, line);
751 while (std::getline(fil, line)) {
752 std::string date_time_str;
761 float proton_charge_raw;
762 float dae_beam_current;
765 std::istringstream istr(line);
766 istr >> date_time_str >> period >> is_running >> is_waiting >> good_frames >> raw_frames >> proton_charge >>
767 proton_charge_raw >> monitor_sum_1 >> dae_beam_current >> total_counts >> count_rate >> np_ratio;
768 date_time_str[10] =
' ';
769 boost::posix_time::ptime time(boost::posix_time::time_from_string(date_time_str));
770 boost::posix_time::time_duration dt = time - start_time;
771 time_vec.emplace_back(
float(dt.total_seconds()));
772 period_vec.emplace_back(period);
773 is_running_vec.emplace_back(is_running);
774 is_waiting_vec.emplace_back(is_waiting);
775 good_frames_vec.emplace_back(good_frames);
776 raw_frames_vec.emplace_back(raw_frames);
777 monitor_sum_1_vec.emplace_back(monitor_sum_1);
778 total_counts_vec.emplace_back(total_counts);
779 proton_charge_vec.emplace_back(proton_charge);
780 proton_charge_raw_vec.emplace_back(proton_charge_raw);
781 dae_beam_current_vec.emplace_back(dae_beam_current);
782 count_rate_vec.emplace_back(count_rate);
783 np_ratio_vec.emplace_back(np_ratio);
787 run_status_vec.resize(time_vec.size());
788 using std::placeholders::_1;
789 std::transform(is_running_vec.begin(), is_running_vec.end(), run_status_vec.begin(),
790 std::bind(std::plus<int>(), _1, 1));
792 NXmakegroup(
handle,
"runlog",
"IXrunlog");
793 NXopengroup(
handle,
"runlog",
"IXrunlog");
795 auto time_vec_size =
static_cast<int>(time_vec.size());
797 write_runlog(
"period", &time_vec[0], &period_vec[0], NX_INT32, time_vec_size,
"none");
798 write_runlog(
"is_running", &time_vec[0], &is_running_vec[0], NX_INT32, time_vec_size,
"none");
799 write_runlog(
"is_waiting", &time_vec[0], &is_waiting_vec[0], NX_INT32, time_vec_size,
"none");
800 write_runlog(
"good_frames", &time_vec[0], &good_frames_vec[0], NX_INT32, time_vec_size,
"frames");
801 write_runlog(
"raw_frames", &time_vec[0], &raw_frames_vec[0], NX_INT32, time_vec_size,
"frames");
802 write_runlog(
"monitor_sum_1", &time_vec[0], &monitor_sum_1_vec[0], NX_INT32, time_vec_size,
"counts");
803 write_runlog(
"total_counts", &time_vec[0], &total_counts_vec[0], NX_INT32, time_vec_size,
"counts");
804 write_runlog(
"proton_charge", &time_vec[0], &proton_charge_vec[0], NX_FLOAT32, time_vec_size,
"uAh");
805 write_runlog(
"proton_charge_raw", &time_vec[0], &proton_charge_raw_vec[0], NX_FLOAT32, time_vec_size,
"uAh");
806 write_runlog(
"dae_beam_current", &time_vec[0], &dae_beam_current_vec[0], NX_FLOAT32, time_vec_size,
"uAh");
807 write_runlog(
"count_rate", &time_vec[0], &count_rate_vec[0], NX_FLOAT32, time_vec_size,
"counts");
808 write_runlog(
"np_ratio", &time_vec[0], &np_ratio_vec[0], NX_FLOAT32, time_vec_size,
"nones");
810 write_runlog(
"run_status", &time_vec[0], &run_status_vec[0], NX_INT32, time_vec_size,
"none");
813 std::ifstream icpevent_fil(ICPevent_filename.c_str());
821 std::vector<std::string> event_vec;
822 while (std::getline(icpevent_fil, line)) {
825 std::string date_time_str = line.substr(0, 19);
826 date_time_str[10] =
' ';
827 boost::posix_time::ptime time(boost::posix_time::time_from_string(date_time_str));
828 boost::posix_time::time_duration dt = time - start_time;
829 time_vec.emplace_back(
float(dt.total_seconds()));
830 event_vec.emplace_back(line.substr(20));
832 icpevent_fil.close();
834 NXmakegroup(
handle,
"icp_event",
"NXlog");
835 NXopengroup(
handle,
"icp_event",
"NXlog");
837 saveFloatOpen(
"time", &time_vec[0],
static_cast<int>(time_vec.size()));
861 const std::string &units) {
876 const std::string &units) {
885 if (type == NX_INT32) {
887 }
else if (type == NX_FLOAT32) {
897 std::vector<std::string> potentialLogFiles;
899 std::string l_filenamePart = Poco::Path(l_path.path()).getFileName();
900 std::string::size_type i = l_filenamePart.find_last_of(
'.');
901 if (i != std::string::npos)
903 l_filenamePart.erase(i);
905 std::string base_name = l_filenamePart;
906 boost::regex regex(l_filenamePart +
"_.*\\.txt", boost::regex_constants::icase);
907 Poco::DirectoryIterator end_iter;
908 for (Poco::DirectoryIterator dir_itr(Poco::Path(
inputFilename).parent()); dir_itr != end_iter; ++dir_itr) {
909 if (!Poco::File(dir_itr->path()).isFile())
912 l_filenamePart = Poco::Path(dir_itr->path()).getFileName();
914 if (boost::regex_match(l_filenamePart, regex)) {
915 potentialLogFiles.emplace_back(dir_itr->path());
919 Progress prog(
this, 0.5, 1.0, potentialLogFiles.size());
921 NXmakegroup(
handle,
"selog",
"IXselog");
922 NXopengroup(
handle,
"selog",
"IXselog");
925 std::size_t nBase = base_name.size() + 1;
926 for (
auto &potentialLogFile : potentialLogFiles) {
927 std::string logName = Poco::Path(potentialLogFile).getFileName();
928 logName.erase(0, nBase);
929 logName.erase(logName.size() - 4);
930 if (logName.size() > 3) {
931 std::string icp = logName.substr(0, 3);
932 std::transform(icp.begin(), icp.end(), icp.begin(), toupper);
937 std::ifstream fil(potentialLogFile.c_str());
939 g_log.
warning(
"Cannot open log file " + potentialLogFile);
944 boost::posix_time::ptime start_time(boost::posix_time::time_from_string(
start_time_str));
946 std::vector<float> time_vec;
947 std::vector<std::string> str_vec;
948 std::vector<float> flt_vec;
950 bool isNotNumeric =
false;
951 while (std::getline(fil, line)) {
954 std::string date_time_str = line.substr(0, 19);
955 date_time_str[10] =
' ';
956 boost::posix_time::ptime time(boost::posix_time::time_from_string(date_time_str));
957 boost::posix_time::time_duration dt = time - start_time;
958 time_vec.emplace_back(
float(dt.total_seconds()));
959 std::istringstream istr(line.substr(20));
964 if (istr.bad() || istr.fail()) {
967 flt_vec.emplace_back(flt);
970 str_vec.emplace_back(istr.str());
973 NXmakegroup(
handle, &logName[0],
"IXseblock");
974 NXopengroup(
handle, &logName[0],
"IXseblock");
986 NXmakegroup(
handle,
"value_log",
"NXlog");
987 NXopengroup(
handle,
"value_log",
"NXlog");
989 saveFloatOpen(
"time", &time_vec[0],
static_cast<int>(time_vec.size()));
994 if (flt_vec.size() == str_vec.size()) {
995 saveFloatOpen(
"value", &flt_vec[0],
static_cast<int>(flt_vec.size()));
1024 int dim[] = {32, 4};
1025 NXmakedata(
handle,
"CRPB", NX_CHAR, 2, dim);
1026 NXopendata(
handle,
"CRPB");
1035 int dim[] = {64, 4};
1036 NXmakedata(
handle,
"CSPB", NX_CHAR, 2, dim);
1037 NXopendata(
handle,
"CSPB");
#define DECLARE_ALGORITHM(classname)
double value
The value of the point.
std::map< DeltaEMode::Type, std::string > index
Base class from which all concrete algorithm classes should be derived.
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.
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
@ Save
to specify a file to write to, the file may or may not exist
@ Load
allowed here which will be passed to the algorithm
Helper class for reporting progress from algorithms.
The SaveISISNexus algorithm will convert a RAW file to a NeXus file.
void instrument()
Write instrument.
std::unique_ptr< ISISRAW2 > m_isisRaw
void exec() override
Overwrites Algorithm method.
void run_cycle()
Write run cycle.
void saveCharOpen(const char *name, void *data, int size)
Save char data and leave the dataset open.
void saveInt(const char *name, void *data, int size=1)
Save int data.
void write_logOpen(const char *name, void *times, void *data, int type, int size, const std::string &units)
write NXlog
void source()
Write instrument/source.
void closegroup()
close an open group.
SaveISISNexus()
Default constructor.
void sample()
Write sample.
int ndet
number of detectors
void init() override
Overwrites Algorithm method.
void saveFloat(const char *name, void *data, int size)
Save float data.
void close()
close an open dataset.
void moderator()
Write instrument/moderator.
NXlink spectrum_index_link
void runlog()
Write runlog.
int saveStringVectorOpen(const char *name, const std::vector< std::string > &str_vec, int max_str_size=-1)
Save a vector of string in a dataset.
std::string inputFilename
The name and path of the input file.
void write_isis_vms_compat()
Write vms_compat.
int ntc
number of time channels
std::vector< int > monitorData
int nmon
number of monitors
NXlink time_of_flight_raw_link
void write_monitors()
Write monitors.
void dae()
Write instrument/dae.
void saveIntOpen(const char *name, void *data, int size=1)
Save int data and leave the dataset open.
void saveStringOpen(const char *name, const std::string &str)
Save a string in a dataset.
std::vector< std::string > log_notes
void make_detector_1_link()
Create a link to some of detector_1's data.
void detector_1()
Write instrument/detector_1.
void write_runlog(const char *name, void *times, void *data, int type, int size, const std::string &units)
write one run log
void saveChar(const char *name, void *data, int size)
Save char data.
const std::string name() const override
Algorithm's name for identification overriding a virtual method.
void saveString(const char *name, const std::string &str)
Save a string in a dataset.
std::string start_time_str
void saveFloatOpen(const char *name, void *data, int size)
Save float data ald leave the dataset open.
int nper
number of periods
void monitor_i(int i)
Write single monitor.
void putAttr(const char *name, const std::string &value)
void toISO8601(std::string &str)
NXlink time_of_flight_link
std::map< int, int > monitor_index
<spectrum_index,monitor_index>.
int * getMonitorData(int period, int imon)
Get a pointer to the saved monitor data.
void logNotes()
Write notes from LOG_STRUCT.
To be used with std::generate to copy only those values from a dataset that don't relate to monitors.
SaveISISNexus * m_alg
this algorithm
int m_index
index to m_data array
T * m_data
pointer to the data
T operator()()
function operator.
getWithoutMonitors(SaveISISNexus *alg, T *data)
Constructor.
Records the filename and the description of failure.
void warning(const std::string &msg)
Logs at warning level.
void report()
Increments the loop counter by 1, then sends the progress notification on behalf of its algorithm.
std::string to_string(const wide_integer< Bits, Signed > &n)