Mantid
Loading...
Searching...
No Matches
SaveISISNexus.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
7// SaveISISNexus
8// @author Freddie Akeroyd, STFC ISIS Faility
9// @author Ronald Fowler, STFC eScience. Modified to fit with
10// SaveISISNexusProcessed
11//----------------------------------------------------------------------
12// Includes
13//----------------------------------------------------------------------
16
17#include <boost/date_time/posix_time/posix_time.hpp>
18#include <boost/regex.hpp>
19#include <boost/scoped_array.hpp>
20
21#include <Poco/DateTimeFormat.h>
22#include <Poco/DateTimeParser.h>
23#include <Poco/DirectoryIterator.h>
24#include <Poco/File.h>
25#include <Poco/Path.h>
26
27#include <algorithm>
28#include <fstream>
29#include <iterator>
30#include <map>
31#include <memory>
32#include <sstream>
33
34namespace Mantid::DataHandling {
35
36// Register the algorithm into the algorithm factory
37DECLARE_ALGORITHM(SaveISISNexus)
38
39using namespace Kernel;
40using namespace API;
41
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() {}
47
52 const std::vector<std::string> inputExts{".raw", ".s*", ".add"};
53 declareProperty(std::make_unique<FileProperty>("InputFilename", "", FileProperty::Load, inputExts),
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).");
56
57 // Declare required parameters, filename with ext {.nx,.nx5,xml} and input
58 // workspace
59 const std::vector<std::string> outputExts{".nxs", ".nx5", ".xml"};
60 declareProperty(std::make_unique<FileProperty>("OutputFilename", "", FileProperty::Save, outputExts),
61 "The name of the Nexus file to write, as a full or relative\n"
62 "path");
63}
64
69template <typename T> class getWithoutMonitors {
70public:
76 getWithoutMonitors(SaveISISNexus *alg, T *data) : m_alg(alg), m_data(data), m_index(-1) {}
81 ++m_index;
82 while (m_alg->monitor_index.find(m_index) != m_alg->monitor_index.end())
83 ++m_index;
84 return m_data[m_index];
85 }
86
87private:
89 T *m_data;
90 int m_index;
91};
92
99 // Retrieve the filename from the properties
100 inputFilename = getPropertyValue("InputFileName");
101
102 m_isisRaw = std::make_unique<ISISRAW2>();
103 rawFile = fopen(inputFilename.c_str(), "rb");
104 if (rawFile == nullptr) {
105 throw Exception::FileError("Cannot open file ", inputFilename);
106 }
107 m_isisRaw->ioRAW(rawFile, true);
108
109 nper = m_isisRaw->t_nper; // number of periods
110 nsp = m_isisRaw->t_nsp1; // number of spectra
111 ntc = m_isisRaw->t_ntc1; // number of time channels
112 nmon = m_isisRaw->i_mon; // number of monitors
113 ndet = m_isisRaw->i_det; // number of detectors
114
115 std::string outputFilename = getPropertyValue("OutputFileName");
116
117 NXstatus status;
118 float flt;
119
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.");
123 }
124 NXmakegroup(handle, "raw_data_1", "NXentry");
125 NXopengroup(handle, "raw_data_1", "NXentry");
127 saveString("beamline", " ");
128
129 flt = static_cast<float>(m_isisRaw->rpb.r_dur); // could be wrong
130 saveFloatOpen("collection_time", &flt, 1);
131 putAttr("units", "second");
132 close();
133
134 saveStringOpen("definition", "TOFRAW");
135 putAttr("version", "1.0");
136 putAttr("url", "http://definition.nexusformat.org/instruments/TOFRAW/?version=1.0");
137 close();
138
139 saveStringOpen("definition_local", "ISISTOFRAW");
140 putAttr("version", "1.0");
141 putAttr("url", "http://svn.isis.rl.ac.uk/instruments/ISISTOFRAW/?version=1.0");
142 close();
143
144 flt = static_cast<float>(m_isisRaw->rpb.r_dur);
145 saveFloatOpen("duration", &flt, 1);
146 putAttr("units", "second");
147 close();
148
149 start_time_str.assign(m_isisRaw->hdr.hd_date, m_isisRaw->hdr.hd_date + 12);
151 start_time_str += 'T';
152 start_time_str += std::string(m_isisRaw->hdr.hd_time, m_isisRaw->hdr.hd_time + 8);
153 saveCharOpen("start_time", &start_time_str[0], 19);
154 putAttr("units", "ISO8601");
155 close();
156
157 std::string str;
158 str.assign(m_isisRaw->rpb.r_enddate, m_isisRaw->rpb.r_enddate + 12);
159 toISO8601(str);
160 str += 'T';
161 str += std::string(m_isisRaw->rpb.r_endtime, m_isisRaw->rpb.r_endtime + 8);
162 saveCharOpen("end_time", &str[0], 19);
163 putAttr("units", "ISO8601");
164 close();
165
166 saveChar("title", m_isisRaw->r_title, 80);
167 saveInt("good_frames", &m_isisRaw->rpb.r_goodfrm);
168
169 std::string experiment_identifier = std::to_string(m_isisRaw->rpb.r_prop);
170 saveChar("experiment_identifier", &experiment_identifier[0], static_cast<int>(experiment_identifier.size()));
171 int tmp_int(0);
172 saveInt("measurement_first_run", &tmp_int);
173 saveString("measurement_id", " ");
174 saveString("measurement_label", " ");
175 saveString("measurement_subid", " ");
176 saveString("measurement_type", " ");
177
178 saveCharOpen("name", &m_isisRaw->i_inst, 8);
179 putAttr("short_name", m_isisRaw->hdr.inst_abrv, 3);
180 close();
181
182 logNotes();
183
184 saveString("program_name", "isisicp");
185
186 saveFloatOpen("proton_charge", &m_isisRaw->rpb.r_gd_prtn_chrg, 1);
187 putAttr("units", "uamp.hour");
188 close();
189
190 saveFloatOpen("proton_charge_raw", &m_isisRaw->rpb.r_tot_prtn_chrg, 1);
191 putAttr("units", "uamp.hour");
192 close();
193
194 saveInt("raw_frames", &m_isisRaw->rpb.r_rawfrm);
195
196 run_cycle();
197
198 saveInt("run_number", &m_isisRaw->r_number);
199
200 // script_name
201 // seci_config
202
203 instrument();
204
206
208
209 user();
210
211 sample();
212
213 runlog();
214
215 selog();
216
217 NXclosegroup(handle); // raw_data_1
218 NXclose(&handle);
219}
220
227void SaveISISNexus::saveInt(const char *name, void *data, int size) {
228 saveIntOpen(name, data, size);
229 close();
230}
231
238void SaveISISNexus::saveChar(const char *name, void *data, int size) {
239 saveCharOpen(name, data, size);
240 close();
241}
242
249void SaveISISNexus::saveFloat(const char *name, void *data, int size) {
250 saveFloatOpen(name, data, size);
251 close();
252}
253
260void SaveISISNexus::saveIntOpen(const char *name, void *data, int size) {
261 int dim[1];
262 dim[0] = size;
263 // If we aren't going to anything with the status, then don't bother asking
264 // for it! (NXstatus status = NXblah())
265 NXmakedata(handle, name, NX_INT32, 1, dim);
266 NXopendata(handle, name);
267 NXputdata(handle, data);
268}
269
276void SaveISISNexus::saveCharOpen(const char *name, void *data, int size) {
277 int dim[1];
278 dim[0] = size;
279 // If we aren't going to anything with the status, then don't bother asking
280 // for it! (NXstatus status = NXblah())
281 NXmakedata(handle, name, NX_CHAR, 1, dim);
282 NXopendata(handle, name);
283 NXputdata(handle, data);
284}
285
292void SaveISISNexus::saveFloatOpen(const char *name, void *data, int size) {
293 int dim[1];
294 dim[0] = size;
295 // If we aren't going to anything with the status, then don't bother asking
296 // for it! (NXstatus status = NXblah())
297 NXmakedata(handle, name, NX_FLOAT32, 1, dim);
298 NXopendata(handle, name);
299 NXputdata(handle, data);
300}
301
309int SaveISISNexus::saveStringVectorOpen(const char *name, const std::vector<std::string> &str_vec, int max_str_size) {
310 if (str_vec.empty()) {
311 saveStringOpen(name, " ");
312 return 0;
313 }
314 int buff_size = max_str_size;
315 if (buff_size <= 0)
316 for (const auto &str : str_vec) {
317 buff_size = std::max(buff_size, int(str.size()));
318 }
319 if (buff_size <= 0)
320 buff_size = 1;
321 auto buff = new char[buff_size];
322 int dim[2];
323 dim[0] = static_cast<int>(str_vec.size());
324 dim[1] = buff_size;
325 NXmakedata(handle, name, NX_CHAR, 2, dim);
326 NXopendata(handle, name);
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);
335 }
336 delete[] buff;
337 return buff_size;
338}
339
345void SaveISISNexus::saveString(const char *name, const std::string &str) {
346 if (str.empty())
347 return;
348 std::string buff(str);
349 saveChar(name, &buff[0], static_cast<int>(buff.size()));
350}
351
357void SaveISISNexus::saveStringOpen(const char *name, const std::string &str) {
358 if (str.empty())
359 return;
360 std::string buff(str);
361 saveCharOpen(name, &buff[0], static_cast<int>(buff.size()));
362}
363
364void SaveISISNexus::putAttr(const char *name, const std::string &value) {
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);
368}
369
370void SaveISISNexus::putAttr(const char *name, char *value, int size) { NXputattr(handle, name, value, size, NX_CHAR); }
371
372void SaveISISNexus::putAttr(const char *name, int value, int size) { NXputattr(handle, name, &value, size, NX_INT32); }
373
374void SaveISISNexus::toISO8601(std::string &str) {
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);
381 str = iso8601;
382}
383
386 NXmakegroup(handle, "isis_vms_compat", "IXvms");
387 NXopengroup(handle, "isis_vms_compat", "IXvms");
388 int ndet = m_isisRaw->i_det;
389 int nmon = m_isisRaw->i_mon;
390
391 saveInt("ADD", &m_isisRaw->add, 9);
392 saveInt("CODE", m_isisRaw->code, ndet);
393 saveInt("CRAT", m_isisRaw->crat, ndet);
394
395 write_rpb();
396 write_spb();
397 write_vpb();
398 saveInt("DAEP", &m_isisRaw->daep, 64);
399 saveInt("DELT", m_isisRaw->delt, ndet);
400 saveInt("FORM", &m_isisRaw->data_format);
401 saveChar("HDR", &m_isisRaw->hdr, 80);
402 saveFloat("LEN2", m_isisRaw->len2, ndet);
403 saveInt("MDET", m_isisRaw->mdet, nmon);
404 saveInt("MODN", m_isisRaw->modn, ndet);
405 saveInt("MONP", m_isisRaw->monp, nmon);
406 saveInt("MPOS", m_isisRaw->mpos, ndet);
407 saveChar("NAME", m_isisRaw->i_inst, 8);
408 saveInt("NDET", &ndet);
409 saveInt("NFPP", &m_isisRaw->t_nfpp);
410 saveInt("NMON", &nmon);
411 saveInt("NPER", &m_isisRaw->t_nper);
412 saveInt("NSER", &m_isisRaw->e_nse);
413 saveInt("NSP1", &m_isisRaw->t_nsp1);
414 saveInt("NTC1", &m_isisRaw->t_ntc1);
415 saveInt("NTRG", &m_isisRaw->t_ntrg);
416 saveInt("NUSE", &m_isisRaw->i_use);
417 saveInt("PMAP", &m_isisRaw->t_pmap, 256);
418 saveInt("PRE1", &m_isisRaw->t_pre1);
419 saveInt("RUN", &m_isisRaw->r_number);
420 saveInt("SPEC", m_isisRaw->spec, ndet);
421 saveInt("TCM1", &m_isisRaw->t_tcm1);
422 saveFloat("TCP1", m_isisRaw->t_tcp1, 20);
423 saveInt("TIMR", m_isisRaw->timr, ndet);
424 saveChar("TITL", m_isisRaw->r_title, 80);
425 saveFloat("TTHE", m_isisRaw->tthe, ndet);
426 saveInt("UDET", m_isisRaw->udet, ndet);
427 saveInt("ULEN", &m_isisRaw->u_len);
428 std::string user_info(160, ' ');
429 if (m_isisRaw->u_len > 0) {
430 std::copy(reinterpret_cast<char *>(&m_isisRaw->user), reinterpret_cast<char *>(&m_isisRaw->user) + m_isisRaw->u_len,
431 user_info.begin());
432 }
433 saveString("USER", user_info);
434 saveInt("VER1", &m_isisRaw->frmt_ver_no);
435 saveInt("VER2", &m_isisRaw->ver2);
436 saveInt("VER3", &m_isisRaw->ver3);
437 saveInt("VER4", &m_isisRaw->ver4);
438 saveInt("VER5", &m_isisRaw->ver5);
439 saveInt("VER6", &m_isisRaw->ver6);
440 saveInt("VER7", &m_isisRaw->ver7);
441 saveInt("VER8", &m_isisRaw->ver8);
442 int tmp_int(0);
443 saveInt("VER9", &tmp_int);
444
445 int n = m_isisRaw->logsect.nlines;
446 log_notes.resize(n);
447 for (int i = 0; i < n; ++i) {
448 log_notes[i].assign(m_isisRaw->logsect.lines[i].data, m_isisRaw->logsect.lines[i].len);
449 }
450 int ll = saveStringVectorOpen("NOTE", log_notes);
451 saveInt("NTNL", &n);
452 saveInt("NTLL", &ll);
453
454 NXclosegroup(handle); // isis_vms_compat
455}
456
458 NXmakegroup(handle, "instrument", "NXinstrument");
459 NXopengroup(handle, "instrument", "NXinstrument");
460 saveCharOpen("name", &m_isisRaw->i_inst, 8);
461 putAttr("short_name", m_isisRaw->hdr.inst_abrv, 3);
462 close();
463 dae();
464 detector_1();
465 moderator();
466 source();
467 NXclosegroup(handle);
468}
469
471 NXmakegroup(handle, "detector_1", "NXdata");
472 NXopengroup(handle, "detector_1", "NXdata");
473
474 for (int i = 0; i < nmon; ++i) {
475 auto si =
476 int(std::distance(m_isisRaw->spec, std::find(m_isisRaw->spec, m_isisRaw->spec + nsp, m_isisRaw->mdet[i])));
477 monitor_index[si] = i;
478 }
479
480 // write counts
481 int dim[3];
482 dim[0] = nper;
483 dim[1] = nsp - nmon;
484 dim[2] = ntc;
485 NXmakedata(handle, "counts", NX_INT32, 3, dim);
486 NXopendata(handle, "counts");
487 putAttr("units", "counts");
488 putAttr("signal", 1);
489 putAttr("axes", "period_index,spectrum_index,time_of_flight");
490
491 int size[] = {1, 1, ntc};
492 int index = 0;
493 for (int p = 0; p < nper; ++p) {
494 int ispec = 0;
495 m_isisRaw->skipData(rawFile, index++);
496 for (int si = 0; si < nsp; ++si) {
497 if (monitor_index.find(si) != monitor_index.end()) {
498 m_isisRaw->readData(rawFile, index);
499 monitorData.insert(monitorData.end(), m_isisRaw->dat1 + 1, m_isisRaw->dat1 + ntc + 1);
500 } else {
501 m_isisRaw->readData(rawFile, index);
502 int start[] = {p, ispec, 0};
503 NXputslab(handle, m_isisRaw->dat1 + 1, start, size);
504 ++ispec;
505 }
506 ++index;
507 }
508 }
509 NXgetdataID(handle, &counts_link);
510 NXclosedata(handle);
511
512 NXmakelink(handle, &period_index_link);
513
514 std::vector<int> spec_minus_monitors(nsp - nmon);
515 std::generate(spec_minus_monitors.begin(), spec_minus_monitors.end(), getWithoutMonitors<int>(this, m_isisRaw->spec));
516 saveIntOpen("spectrum_index", &spec_minus_monitors[0], nsp - nmon);
517 NXgetdataID(handle, &spectrum_index_link);
518 close();
519
520 NXmakelink(handle, &time_of_flight_link);
521 NXmakelink(handle, &time_of_flight_raw_link);
522
523 std::vector<float> float_vec(ndet - nmon);
524 std::generate(float_vec.begin(), float_vec.end(), getWithoutMonitors<float>(this, m_isisRaw->delt));
525 saveFloat("delt", &float_vec[0], ndet - nmon);
526
527 saveFloat("source_detector_distance", &m_isisRaw->ivpb.i_sddist, 1);
528
529 // using the same float_vec, size unchanged ndet-nmon
530 std::generate(float_vec.begin(), float_vec.end(), getWithoutMonitors<float>(this, m_isisRaw->len2));
531 saveFloatOpen("distance", &float_vec[0], ndet - nmon);
532 putAttr("units", "metre");
533 close();
534
535 // using the same float_vec, size unchanged ndet-nmon
536 std::generate(float_vec.begin(), float_vec.end(), getWithoutMonitors<float>(this, m_isisRaw->tthe));
537 saveFloatOpen("polar_angle", &float_vec[0], ndet - nmon);
538 putAttr("units", "degree");
539 close();
540
541 NXclosegroup(handle);
542}
543
548 NXmakegroup(handle, "moderator", "NXmoderator");
549 NXopengroup(handle, "moderator", "NXmoderator");
550
551 float l1 = -m_isisRaw->ivpb.i_l1;
552 saveFloatOpen("distance", &l1, 1);
553 putAttr("units", "metre");
554
555 NXclosegroup(handle);
556}
557
562 NXmakegroup(handle, "source", "NXsource");
563 NXopengroup(handle, "source", "NXsource");
564
565 saveString("name", "ISIS");
566 saveString("probe", "neutrons");
567 saveString("type", "Pulsed Neutron Source");
568
569 NXclosegroup(handle);
570}
571
577 NXmakegroup(handle, "detector_1", "NXdata");
578 NXopengroup(handle, "detector_1", "NXdata");
579
580 NXmakelink(handle, &counts_link);
581 NXmakelink(handle, &period_index_link);
582 NXmakelink(handle, &spectrum_index_link);
583 NXmakelink(handle, &time_of_flight_link);
584
585 NXclosegroup(handle);
586}
587
593int *SaveISISNexus::getMonitorData(int period, int imon) {
594 return &monitorData[period * m_isisRaw->i_mon * m_isisRaw->t_ntc1 + imon * m_isisRaw->t_ntc1];
595}
596
598 int nmon = m_isisRaw->i_mon;
599 for (int i = 0; i < nmon; ++i) {
600 monitor_i(i);
601 }
602}
603
609 int nper = m_isisRaw->t_nper; // number of periods
610 int ntc = m_isisRaw->t_ntc1; // number of time channels
611 int dim[] = {nper, 1, ntc};
612 int size[] = {1, 1, ntc};
613 std::ostringstream ostr;
614 int mon_num = i + 1;
615 ostr << "monitor_" << mon_num;
616 NXmakegroup(handle, ostr.str().c_str(), "NXmonitor");
617 NXopengroup(handle, ostr.str().c_str(), "NXmonitor");
618
619 // int imon = m_isisRaw->mdet[i]; // spectrum number
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};
624 NXputslab(handle, getMonitorData(p, i), start, size);
625 }
626 putAttr("units", "counts");
627 putAttr("signal", 1);
628 putAttr("axes", "period_index,spectrum_index,time_of_flight");
629 NXclosedata(handle);
630
631 saveInt("monitor_number", &mon_num);
632 NXmakelink(handle, &period_index_link);
633 saveInt("spectrum_index", &m_isisRaw->mdet[i]);
634 NXmakelink(handle, &time_of_flight_link);
635
636 NXclosegroup(handle);
637}
638
640 NXmakegroup(handle, "dae", "IXdae");
641 NXopengroup(handle, "dae", "IXdae");
642
643 saveString("detector_table_file", " ");
644 saveString("spectra_table_file", " ");
645 saveString("wiring_table_file", " ");
646
647 saveIntOpen("period_index", m_isisRaw->t_pmap, nper);
648 NXgetdataID(handle, &period_index_link);
649 close();
650
651 NXmakegroup(handle, "time_channels_1", "IXtime_channels");
652 NXopengroup(handle, "time_channels_1", "IXtime_channels");
653
654 boost::scoped_array<float> timeChannels(new float[ntc + 1]);
655 m_isisRaw->getTimeChannels(timeChannels.get(), ntc + 1);
656 saveFloatOpen("time_of_flight", timeChannels.get(), ntc + 1);
657 putAttr("axis", 1);
658 putAttr("primary", 1);
659 putAttr("units", "microseconds");
660 NXgetdataID(handle, &time_of_flight_link);
661 close();
662
663 saveIntOpen("time_of_flight_raw", m_isisRaw->t_tcb1, ntc + 1);
664 putAttr("units", "pulses");
665 putAttr("frequency", "32 MHz");
666 NXgetdataID(handle, &time_of_flight_raw_link);
667 close();
668
669 NXclosegroup(handle); // time_channels_1
670
671 NXclosegroup(handle); // dae
672}
673
675 NXmakegroup(handle, "user_1", "NXuser");
676 NXopengroup(handle, "user_1", "NXuser");
677
678 saveChar("name", m_isisRaw->user.r_user, 20);
679 saveChar("affiliation", m_isisRaw->user.r_instit, 20);
680
681 NXclosegroup(handle); // user_1
682}
683
685 NXmakegroup(handle, "sample", "NXsample");
686 NXopengroup(handle, "sample", "NXsample");
687
688 saveChar("name", m_isisRaw->spb.e_name, 40);
689 saveFloat("height", &m_isisRaw->spb.e_height, 1);
690 saveFloat("width", &m_isisRaw->spb.e_width, 1);
691 saveFloat("thickness", &m_isisRaw->spb.e_thick, 1);
692 saveString("id", " ");
693 float tmp(0.0);
694 saveFloat("distance", &tmp, 1);
695 std::string shape[] = {"cylinder", "flat plate", "HRPD slab", "unknown"};
696 int i = m_isisRaw->spb.e_geom - 1;
697 if (i < 0 || i > 3)
698 i = 3;
699 saveString("shape", shape[i]);
700 std::string type[] = {"sample+can", "empty can", "vanadium", "absorber", "nothing", "sample, no can", "unknown"};
701 i = m_isisRaw->spb.e_type - 1;
702 if (i < 0 || i > 6)
703 i = 6;
704 saveString("type", type[i]);
705
706 NXclosegroup(handle); // sample
707}
708
713 progress(0);
714 std::string ICPstatus_filename = inputFilename;
715 std::string ICPevent_filename;
716 std::string::size_type i = ICPstatus_filename.find_last_of('.');
717 if (i != std::string::npos) // remove the file extension
718 {
719 ICPstatus_filename.erase(i);
720 }
721 ICPevent_filename = ICPstatus_filename + "_ICPevent.txt";
722 ICPstatus_filename += "_ICPstatus.txt";
723
724 std::ifstream fil(ICPstatus_filename.c_str());
725 if (!fil) {
726 g_log.warning("Cannot find the ICPstatus file. Skipping runlog");
727 progress(0.5);
728 return;
729 }
730
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;
745
746 start_time_str[10] = ' '; // make it compatible with boost::posix_time::ptime
747 boost::posix_time::ptime start_time(boost::posix_time::time_from_string(start_time_str));
748 start_time_str[10] = 'T'; // revert
749 std::string line;
750 std::getline(fil, line); // skip the first line
751 while (std::getline(fil, line)) {
752 std::string date_time_str;
753 int period;
754 int is_running;
755 int is_waiting;
756 int good_frames;
757 int raw_frames;
758 int monitor_sum_1;
759 int total_counts;
760 float proton_charge;
761 float proton_charge_raw;
762 float dae_beam_current;
763 float count_rate;
764 float np_ratio;
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);
784 }
785 fil.close();
786
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));
791
792 NXmakegroup(handle, "runlog", "IXrunlog");
793 NXopengroup(handle, "runlog", "IXrunlog");
794
795 auto time_vec_size = static_cast<int>(time_vec.size());
796
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");
809
810 write_runlog("run_status", &time_vec[0], &run_status_vec[0], NX_INT32, time_vec_size, "none");
811
812 // read in ICPevent file and create icp_event log
813 std::ifstream icpevent_fil(ICPevent_filename.c_str());
814 if (!icpevent_fil) {
815 g_log.warning("Cannot find the ICPevent file");
816 progress(0.5);
817 return;
818 }
819
820 time_vec.clear();
821 std::vector<std::string> event_vec;
822 while (std::getline(icpevent_fil, line)) {
823 if (line.empty())
824 continue;
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));
831 }
832 icpevent_fil.close();
833
834 NXmakegroup(handle, "icp_event", "NXlog");
835 NXopengroup(handle, "icp_event", "NXlog");
836
837 saveFloatOpen("time", &time_vec[0], static_cast<int>(time_vec.size()));
838 putAttr("start", start_time_str);
839 putAttr("units", "seconds");
840 close();
841
842 saveStringVectorOpen("value", event_vec, 72);
843 putAttr("units", " ");
844 close();
845 NXclosegroup(handle); // icp_event
846
847 NXclosegroup(handle); // runlog
848 progress(0.5);
849}
850
860void SaveISISNexus::write_runlog(const char *name, void *times, void *data, int type, int size,
861 const std::string &units) {
862 write_logOpen(name, times, data, type, size, units);
863 closegroup();
864}
865
875void SaveISISNexus::write_logOpen(const char *name, void *times, void *data, int type, int size,
876 const std::string &units) {
877 NXmakegroup(handle, name, "NXlog");
878 NXopengroup(handle, name, "NXlog");
879
880 saveFloatOpen("time", times, size);
881 putAttr("start", start_time_str);
882 putAttr("units", "seconds");
883 close();
884
885 if (type == NX_INT32) {
886 saveIntOpen("value", data, size);
887 } else if (type == NX_FLOAT32) {
888 saveFloatOpen("value", data, size);
889 }
890 putAttr("units", units);
891 close();
892}
893
895 // find log files with names <RawFilenameWithoutExt>_LogName.txt and save them
896 // in potentialLogFiles
897 std::vector<std::string> potentialLogFiles;
898 Poco::File l_path(inputFilename);
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) // remove the file extension
902 {
903 l_filenamePart.erase(i);
904 }
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())
910 continue;
911
912 l_filenamePart = Poco::Path(dir_itr->path()).getFileName();
913
914 if (boost::regex_match(l_filenamePart, regex)) {
915 potentialLogFiles.emplace_back(dir_itr->path());
916 }
917 }
918
919 Progress prog(this, 0.5, 1.0, potentialLogFiles.size());
920
921 NXmakegroup(handle, "selog", "IXselog");
922 NXopengroup(handle, "selog", "IXselog");
923
924 // create a log for each of the found log files
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);
933 if (icp == "ICP")
934 continue;
935 }
936
937 std::ifstream fil(potentialLogFile.c_str());
938 if (!fil) {
939 g_log.warning("Cannot open log file " + potentialLogFile);
940 continue;
941 }
942
943 start_time_str[10] = ' '; // make it compatible with boost::posix_time::ptime
944 boost::posix_time::ptime start_time(boost::posix_time::time_from_string(start_time_str));
945 start_time_str[10] = 'T'; // revert
946 std::vector<float> time_vec;
947 std::vector<std::string> str_vec;
948 std::vector<float> flt_vec;
949 std::string line;
950 bool isNotNumeric = false;
951 while (std::getline(fil, line)) {
952 if (line.empty())
953 continue;
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));
960 // check if the data are numeric then save them in flt_vec
961 if (!isNotNumeric) {
962 float flt;
963 istr >> flt;
964 if (istr.bad() || istr.fail()) {
965 isNotNumeric = true;
966 } else {
967 flt_vec.emplace_back(flt);
968 }
969 }
970 str_vec.emplace_back(istr.str());
971 }
972 fil.close();
973 NXmakegroup(handle, &logName[0], "IXseblock");
974 NXopengroup(handle, &logName[0], "IXseblock");
975
976 {
977 saveString("vi_name", " ");
978 saveString("set_control", " ");
979 saveString("read_control", " ");
980 float tmp = 0.0;
981 saveFloatOpen("setpoint", &tmp, 1);
982 putAttr("units", "mV");
983 close();
984 }
985
986 NXmakegroup(handle, "value_log", "NXlog");
987 NXopengroup(handle, "value_log", "NXlog");
988
989 saveFloatOpen("time", &time_vec[0], static_cast<int>(time_vec.size()));
990 putAttr("start", start_time_str);
991 putAttr("units", "seconds");
992 close();
993
994 if (flt_vec.size() == str_vec.size()) {
995 saveFloatOpen("value", &flt_vec[0], static_cast<int>(flt_vec.size()));
996 } else {
997 saveStringVectorOpen("value", str_vec);
998 }
999 putAttr("units", " ");
1000 close();
1001
1002 saveString("name", " ");
1003
1004 NXclosegroup(handle); // value_log
1005
1006 NXclosegroup(handle); // logName
1007
1008 prog.report();
1009 }
1010
1011 NXclosegroup(handle); // selog
1012
1013 progress(1);
1014}
1015
1018 close();
1019}
1020
1021void SaveISISNexus::run_cycle() { saveString("run_cycle", " "); }
1022
1024 int dim[] = {32, 4};
1025 NXmakedata(handle, "CRPB", NX_CHAR, 2, dim);
1026 NXopendata(handle, "CRPB");
1027 NXputdata(handle, &m_isisRaw->rpb);
1028 NXclosedata(handle);
1029
1030 saveInt("IRPB", &m_isisRaw->rpb, 32);
1031 saveFloat("RRPB", &m_isisRaw->rpb, 32);
1032}
1033
1035 int dim[] = {64, 4};
1036 NXmakedata(handle, "CSPB", NX_CHAR, 2, dim);
1037 NXopendata(handle, "CSPB");
1038 NXputdata(handle, &m_isisRaw->spb);
1039 NXclosedata(handle);
1040
1041 saveInt("SPB", &m_isisRaw->spb, 64);
1042 saveInt("ISPB", &m_isisRaw->spb, 64);
1043 saveFloat("RSPB", &m_isisRaw->spb, 64);
1044}
1045
1047 saveInt("IVPB", &m_isisRaw->ivpb, 64);
1048 saveFloat("RVPB", &m_isisRaw->ivpb, 64);
1049}
1050
1051} // namespace Mantid::DataHandling
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
gsl_vector * tmp
double value
The value of the point.
Definition: FitMW.cpp:51
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
isis raw file.
Definition: isisraw2.h:13
Base class from which all concrete algorithm classes should be derived.
Definition: Algorithm.h:85
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
Definition: Algorithm.cpp:1913
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
Definition: Algorithm.cpp:2026
Kernel::Logger & g_log
Definition: Algorithm.h:451
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
Definition: Algorithm.cpp:231
@ Save
to specify a file to write to, the file may or may not exist
Definition: FileProperty.h:49
@ Load
allowed here which will be passed to the algorithm
Definition: FileProperty.h:52
Helper class for reporting progress from algorithms.
Definition: Progress.h:25
The SaveISISNexus algorithm will convert a RAW file to a NeXus file.
Definition: SaveISISNexus.h:32
void instrument()
Write instrument.
std::unique_ptr< ISISRAW2 > m_isisRaw
Definition: SaveISISNexus.h:57
void exec() override
Overwrites Algorithm method.
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.
Definition: SaveISISNexus.h:89
SaveISISNexus()
Default constructor.
void init() override
Overwrites Algorithm method.
void saveFloat(const char *name, void *data, int size)
Save float data.
void close()
close an open dataset.
Definition: SaveISISNexus.h:88
void moderator()
Write instrument/moderator.
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
Definition: SaveISISNexus.h:66
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
Definition: SaveISISNexus.h:70
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.
Definition: SaveISISNexus.h:37
void saveString(const char *name, const std::string &str)
Save a string in a dataset.
void saveFloatOpen(const char *name, void *data, int size)
Save float data ald leave the dataset open.
void monitor_i(int i)
Write single monitor.
void putAttr(const char *name, const std::string &value)
std::map< int, int > monitor_index
<spectrum_index,monitor_index>.
Definition: SaveISISNexus.h:63
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
getWithoutMonitors(SaveISISNexus *alg, T *data)
Constructor.
Records the filename and the description of failure.
Definition: Exception.h:98
void warning(const std::string &msg)
Logs at warning level.
Definition: Logger.cpp:86
void report()
Increments the loop counter by 1, then sends the progress notification on behalf of its algorithm.
Definition: ProgressBase.h:51
STL namespace.
std::string to_string(const wide_integer< Bits, Signed > &n)