35using namespace Kernel;
37using namespace DataObjects;
41Logger
g_log(
"NexusFileIO");
46 : fileID(), m_filehandle(), m_nexuscompression(NX_COMP_LZW), m_progress(nullptr), m_filename() {}
50 : fileID(), m_filehandle(), m_nexuscompression(NX_COMP_LZW), m_progress(prog), m_filename() {}
81 const bool append_to_file) {
85 NXaccess mode(NXACC_CREATE5);
86 std::string mantidEntryName;
97 if (fileName.find(
".xml") < fileName.size() || fileName.find(
".XML") < fileName.size()) {
98 mode = NXACC_CREATEXML;
101 mantidEntryName =
"mantid_workspace_1";
108 Poco::Path path(fileName);
109 std::string baseName = path.getBaseName();
110 if (baseName.size() > NAME_MAX) {
111 std::string message =
"Filename is too long. Unable to open file: ";
116 NXstatus status = NXopen(fileName.c_str(), mode, &
fileID);
117 if (status == NX_ERROR) {
118 g_log.
error(
"Unable to open file " + fileName);
121 auto file = new ::NeXus::File(
fileID,
true);
133 if (mode == NXACC_RDWR) {
135 if (entryNumber.is_initialized()) {
137 count = entryNumber.get();
144 std::stringstream suffix;
145 suffix << (
count + 1);
146 mantidEntryName =
"mantid_workspace_" + suffix.str();
152 const std::string className =
"NXentry";
178 const std::string className =
"Mantid Processed Workspace";
179 std::vector<std::string> attributes, avalues;
180 attributes.reserve(2);
182 if (!writeNxValue<std::string>(
"title", title, NX_CHAR, attributes, avalues))
186 if (!wsName.empty()) {
187 if (!writeNxValue<std::string>(
"workspace_name", wsName, NX_CHAR, attributes, avalues))
191 attributes.emplace_back(
"URL");
192 avalues.emplace_back(
"http://www.nexusformat.org/instruments/xml/NXprocessed.xml");
193 attributes.emplace_back(
"Version");
194 avalues.emplace_back(
"1.0");
196 if (!writeNxValue<std::string>(
"definition", className, NX_CHAR, attributes, avalues))
199 avalues.emplace_back(
"http://www.isis.rl.ac.uk/xml/IXmantid.xml");
200 avalues.emplace_back(
"1.0");
201 if (!writeNxValue<std::string>(
"definition_local", className, NX_CHAR, attributes, avalues))
211 const std::vector<std::string> &attributes,
212 const std::vector<std::string> &avalues)
const {
215 for (
size_t it = 0; it < attributes.size(); ++it)
225 const std::vector<std::string> &attributes,
226 const std::vector<std::string> &avalues)
const {
228 const auto maxlen = std::max_element(values.cbegin(), values.cend(),
229 [](
const auto &lhs,
const auto &
rhs) { return lhs.size() < rhs.size(); });
230 dimensions[0] =
static_cast<int>(values.size());
231 dimensions[1] =
static_cast<int>(maxlen->size());
232 NXstatus status = NXmakedata(
fileID, name.c_str(), NX_CHAR, 2, dimensions);
233 if (status == NX_ERROR)
235 NXopendata(
fileID, name.c_str());
236 for (
size_t it = 0; it < attributes.size(); ++it)
237 NXputattr(
fileID, attributes[it].c_str(), avalues[it].c_str(),
static_cast<int>(avalues[it].size() + 1), NX_CHAR);
238 auto strs =
new char[values.size() * maxlen->size()];
239 for (
size_t i = 0; i < values.size(); i++) {
240 strncpy(&strs[i * maxlen->size()], values[i].c_str(), maxlen->size());
254 const std::string &description,
const std::string &pairValues)
const {
257 std::vector<std::string> attributes, avalues;
259 attributes.emplace_back(
"date");
260 avalues.emplace_back(date);
262 if (!writeNxValue<std::string>(
"author", author, NX_CHAR, attributes, avalues))
267 if (!writeNxValue<std::string>(
"description", description, NX_CHAR, attributes, avalues))
269 if (!writeNxValue<std::string>(
"data", pairValues, NX_CHAR, attributes, avalues))
281 const bool &uniformSpectra,
const std::vector<int> &indices,
282 const char *group_name,
bool write2Ddata)
const {
286 status = NXmakegroup(
fileID, group_name,
"NXdata");
287 if (status == NX_ERROR)
289 NXopengroup(
fileID, group_name,
"NXdata");
291 const size_t nHist = localworkspace->getNumberHistograms();
294 const size_t nSpectBins = localworkspace->y(0).size();
295 const size_t nSpect = indices.size();
296 int dims_array[2] = {
static_cast<int>(nSpect),
static_cast<int>(nSpectBins)};
301 std::string xLabel, sLabel;
303 xLabel =
"spectraNumber";
306 xLabel = xAxis->
unit()->unitID();
311 sLabel =
"spectraNumber";
314 sLabel = sAxis->
unit()->unitID();
319 std::vector<double> axis2;
321 for (
size_t i = 0; i < nSpect; i++)
322 axis2.emplace_back((*sAxis)(indices[i]));
324 for (
size_t i = 0; i < sAxis->
length(); i++)
325 axis2.emplace_back((*sAxis)(i));
327 int start[2] = {0, 0};
328 int asize[2] = {1, dims_array[1]};
332 std::string name =
"values";
334 NXopendata(
fileID, name.c_str());
335 for (
size_t i = 0; i < nSpect; i++) {
336 NXputslab(
fileID, localworkspace->y(indices[i]).rawData().data(), start, asize);
342 NXputattr(
fileID,
"signal", &signal, 1, NX_INT32);
344 const std::string axesNames =
"axis2,axis1";
345 NXputattr(
fileID,
"axes", axesNames.c_str(),
static_cast<int>(axesNames.size()), NX_CHAR);
346 std::string yUnits = localworkspace->YUnit();
347 std::string yUnitLabel = localworkspace->YUnitLabel();
348 NXputattr(
fileID,
"units", yUnits.c_str(),
static_cast<int>(yUnits.size()), NX_CHAR);
349 NXputattr(
fileID,
"unit_label", yUnitLabel.c_str(),
static_cast<int>(yUnitLabel.size()), NX_CHAR);
355 NXopendata(
fileID, name.c_str());
357 for (
size_t i = 0; i < nSpect; i++) {
358 NXputslab(
fileID, localworkspace->e(indices[i]).rawData().data(), start, asize);
366 if (localworkspace->id() ==
"RebinnedOutput") {
370 NXopendata(
fileID, name.c_str());
372 for (
size_t i = 0; i < nSpect; i++) {
373 NXputslab(
fileID, rebin_workspace->readF(indices[i]).data(), start, asize);
377 std::string finalized = (rebin_workspace->isFinalized()) ?
"1" :
"0";
378 NXputattr(
fileID,
"finalized", finalized.c_str(), 2, NX_CHAR);
379 std::string sqrdErrs = (rebin_workspace->hasSqrdErrors()) ?
"1" :
"0";
380 NXputattr(
fileID,
"sqrd_errors", sqrdErrs.c_str(), 2, NX_CHAR);
387 if (localworkspace->hasDx(0)) {
388 dims_array[0] =
static_cast<int>(nSpect);
389 dims_array[1] =
static_cast<int>(localworkspace->dx(0).size());
390 std::string dxErrorName =
"xerrors";
392 NXopendata(
fileID, dxErrorName.c_str());
394 asize[1] = dims_array[1];
395 for (
size_t i = 0; i < nSpect; i++) {
397 NXputslab(
fileID, localworkspace->dx(indices[i]).rawData().data(), start, asize);
406 if (uniformSpectra) {
407 dims_array[0] =
static_cast<int>(localworkspace->x(0).size());
408 NXmakedata(
fileID,
"axis1", NX_FLOAT64, 1, dims_array);
409 NXopendata(
fileID,
"axis1");
410 NXputdata(
fileID, localworkspace->x(0).rawData().data());
413 dims_array[0] =
static_cast<int>(nSpect);
414 dims_array[1] =
static_cast<int>(localworkspace->x(0).size());
415 NXmakedata(
fileID,
"axis1", NX_FLOAT64, 2, dims_array);
416 NXopendata(
fileID,
"axis1");
418 asize[1] = dims_array[1];
419 for (
size_t i = 0; i < nSpect; i++) {
420 NXputslab(
fileID, localworkspace->x(indices[i]).rawData().data(), start, asize);
425 std::string dist = (localworkspace->isDistribution()) ?
"1" :
"0";
426 NXputattr(
fileID,
"distribution", dist.c_str(), 2, NX_CHAR);
427 NXputattr(
fileID,
"units", xLabel.c_str(),
static_cast<int>(xLabel.size()), NX_CHAR);
429 auto label = std::dynamic_pointer_cast<Mantid::Kernel::Units::Label>(xAxis->
unit());
431 NXputattr(
fileID,
"caption", label->caption().c_str(),
static_cast<int>(label->caption().size()), NX_CHAR);
432 auto unitLbl = label->label();
433 NXputattr(
fileID,
"label", unitLbl.ascii().c_str(),
static_cast<int>(unitLbl.ascii().size()), NX_CHAR);
440 dims_array[0] =
static_cast<int>(axis2.size());
441 NXmakedata(
fileID,
"axis2", NX_FLOAT64, 1, dims_array);
442 NXopendata(
fileID,
"axis2");
443 NXputdata(
fileID, axis2.data());
444 NXputattr(
fileID,
"units", sLabel.c_str(),
static_cast<int>(sLabel.size()), NX_CHAR);
446 auto unitLabel = std::dynamic_pointer_cast<Mantid::Kernel::Units::Label>(sAxis->
unit());
448 NXputattr(
fileID,
"caption", unitLabel->caption().c_str(),
static_cast<int>(unitLabel->caption().size()),
450 auto unitLbl = unitLabel->label();
451 NXputattr(
fileID,
"label", unitLbl.ascii().c_str(),
static_cast<int>(unitLbl.ascii().size()), NX_CHAR);
456 std::string textAxis;
457 for (
size_t i = 0; i < sAxis->
length(); i++) {
458 textAxis += sAxis->
label(i) +
"\n";
460 dims_array[0] =
static_cast<int>(textAxis.size());
461 NXmakedata(
fileID,
"axis2", NX_CHAR, 1, dims_array);
462 NXopendata(
fileID,
"axis2");
463 NXputdata(
fileID, textAxis.c_str());
464 NXputattr(
fileID,
"units",
"TextAxis", 8, NX_CHAR);
466 auto unitLabel = std::dynamic_pointer_cast<Mantid::Kernel::Units::Label>(sAxis->
unit());
468 NXputattr(
fileID,
"caption", unitLabel->caption().c_str(),
static_cast<int>(unitLabel->caption().size()),
470 auto unitLbl = unitLabel->label();
471 NXputattr(
fileID,
"label", unitLbl.ascii().c_str(),
static_cast<int>(unitLbl.ascii().size()), NX_CHAR);
479 status = NXclosegroup(
fileID);
480 return ((status == NX_ERROR) ? 3 : 0);
492template <
typename ColumnT,
typename NexusT>
494 const std::string &columnName)
const {
495 const auto nRows =
static_cast<int>(col.
size());
496 int dims_array[1] = {nRows};
498 auto toNexus =
new NexusT[nRows];
499 for (
int ii = 0; ii < nRows; ii++)
500 toNexus[ii] =
static_cast<NexusT
>(col.
cell<ColumnT>(ii));
501 NXwritedata(columnName.c_str(), type, 1, dims_array, toNexus,
false);
505 NXopendata(
fileID, columnName.c_str());
506 std::string units =
"Not known";
507 NXputattr(
fileID,
"units", units.c_str(),
static_cast<int>(units.size()), NX_CHAR);
508 NXputattr(
fileID,
"interpret_as", interpret_as.c_str(),
static_cast<int>(interpret_as.size()), NX_CHAR);
516template <
typename VecType>
size_t getSizeOf(
const VecType &vec) {
return vec.size(); }
519size_t getSizeOf(
const Kernel::V3D & ) {
return 3; }
529template <
typename VecType,
typename ElemType>
531 const std::string &interpret_as)
const {
533 size_t rowCount = column.
size();
537 for (
size_t i = 0; i < rowCount; ++i) {
538 size_t size = getSizeOf(column[i]);
545 int dims[2]{
static_cast<int>(rowCount),
static_cast<int>(maxSize)};
548 boost::scoped_array<ElemType> data(
new ElemType[rowCount * maxSize]);
550 for (
size_t i = 0; i < rowCount; ++i) {
552 std::vector<ElemType> values = column[i];
555 values.resize(maxSize);
558 for (
size_t j = 0; j < maxSize; ++j)
559 data[i * maxSize + j] = values[j];
563 NXwritedata(columnName.c_str(), nexusType, 2, dims, data.get(),
false);
565 NXopendata(
fileID, columnName.c_str());
570 for (
size_t i = 0; i < rowCount; ++i) {
571 auto size =
static_cast<int>(getSizeOf(column[i]));
573 std::ostringstream rowSizeAttrName;
574 rowSizeAttrName <<
"row_size_" << i;
576 NXputattr(
fileID, rowSizeAttrName.str().c_str(), &size, 1, NX_INT32);
579 std::string units =
"Not known";
582 NXputattr(
fileID,
"units", units.c_str(),
static_cast<int>(units.size()), NX_CHAR);
583 NXputattr(
fileID,
"interpret_as", interpret_as.c_str(),
static_cast<int>(interpret_as.size()), NX_CHAR);
591 const char *group_name)
const {
592 NXstatus status = NX_ERROR;
594 std::shared_ptr<const TableWorkspace> tableworkspace =
595 std::dynamic_pointer_cast<const TableWorkspace>(itableworkspace);
596 std::shared_ptr<const PeaksWorkspace> peakworkspace =
597 std::dynamic_pointer_cast<const PeaksWorkspace>(itableworkspace);
599 if (!tableworkspace && !peakworkspace)
603 status = NXmakegroup(
fileID, group_name,
"NXdata");
604 if (status == NX_ERROR)
606 NXopengroup(
fileID, group_name,
"NXdata");
608 auto nRows =
static_cast<int>(itableworkspace->rowCount());
610 for (
size_t i = 0; i < itableworkspace->columnCount(); i++) {
615 if (col->isType<
double>()) {
616 writeTableColumn<double, double>(NX_FLOAT64,
"", *col, str);
617 }
else if (col->isType<
float>()) {
618 writeTableColumn<float, float>(NX_FLOAT32,
"", *col, str);
619 }
else if (col->isType<
int>()) {
620 writeTableColumn<int, int32_t>(NX_INT32,
"", *col, str);
621 }
else if (col->isType<uint32_t>()) {
622 writeTableColumn<uint32_t, uint32_t>(NX_UINT32,
"", *col, str);
623 }
else if (col->isType<int64_t>()) {
624 writeTableColumn<int64_t, int64_t>(NX_INT64,
"", *col, str);
625 }
else if (col->isType<
size_t>()) {
626 writeTableColumn<size_t, uint64_t>(NX_UINT64,
"", *col, str);
627 }
else if (col->isType<
Boolean>()) {
628 writeTableColumn<bool, bool>(NX_UINT8,
"", *col, str);
629 }
else if (col->isType<std::string>()) {
632 for (
int ii = 0; ii < nRows; ii++) {
633 if (col->cell<std::string>(ii).size() > maxStr)
634 maxStr = col->cell<std::string>(ii).size();
641 int dims_array[2] = {nRows,
static_cast<int>(maxStr)};
642 int asize[2] = {1, dims_array[1]};
644 NXcompmakedata(
fileID, str.c_str(), NX_CHAR, 2, dims_array,
false, asize);
645 NXopendata(
fileID, str.c_str());
646 auto toNexus =
new char[maxStr * nRows];
647 for (
int ii = 0; ii < nRows; ii++) {
648 std::string rowStr = col->cell<std::string>(ii);
649 for (
size_t ic = 0; ic < rowStr.size(); ic++)
650 toNexus[ii * maxStr + ic] = rowStr[ic];
651 for (
size_t ic = rowStr.size(); ic < static_cast<size_t>(maxStr); ic++)
652 toNexus[ii * maxStr + ic] =
' ';
655 NXputdata(
fileID, toNexus);
659 std::string units =
"N/A";
660 std::string interpret_as =
"A string";
661 NXputattr(
fileID,
"units", units.c_str(),
static_cast<int>(units.size()), NX_CHAR);
662 NXputattr(
fileID,
"interpret_as", interpret_as.c_str(),
static_cast<int>(interpret_as.size()), NX_CHAR);
665 }
else if (col->isType<std::vector<int>>()) {
666 writeNexusVectorColumn<std::vector<int>,
int>(col, str, NX_INT32,
"");
667 }
else if (col->isType<std::vector<double>>()) {
668 writeNexusVectorColumn<std::vector<double>,
double>(col, str, NX_FLOAT64,
"");
670 writeNexusVectorColumn<Kernel::V3D, double>(col, str, NX_FLOAT64,
"V3D");
674 NXopendata(
fileID, str.c_str());
675 NXputattr(
fileID,
"name", col->name().c_str(),
static_cast<int>(col->name().size()), NX_CHAR);
679 status = NXclosegroup(
fileID);
680 return ((status == NX_ERROR) ? 3 : 0);
695 std::vector<int64_t> &indices,
double *tofs,
float *weights,
696 float *errorSquareds, int64_t *pulsetimes,
bool compress)
const {
697 NXopengroup(
fileID,
"event_workspace",
"NXdata");
700 int dims_array[1] = {
static_cast<int>(indices.size())};
701 if (!indices.empty()) {
705 NXmakedata(
fileID,
"indices", NX_INT64, 1, dims_array);
706 NXopendata(
fileID,
"indices");
707 NXputdata(
fileID, indices.data());
708 std::string yUnits = ws->YUnit();
709 std::string yUnitLabel = ws->YUnitLabel();
710 NXputattr(
fileID,
"units", yUnits.c_str(),
static_cast<int>(yUnits.size()), NX_CHAR);
711 NXputattr(
fileID,
"unit_label", yUnitLabel.c_str(),
static_cast<int>(yUnitLabel.size()), NX_CHAR);
716 dims_array[0] =
static_cast<int>(indices.back());
718 NXwritedata(
"tof", NX_FLOAT64, 1, dims_array, tofs, compress);
720 NXwritedata(
"pulsetime", NX_INT64, 1, dims_array, pulsetimes, compress);
722 NXwritedata(
"weight", NX_FLOAT32, 1, dims_array, weights, compress);
724 NXwritedata(
"error_squared", NX_FLOAT32, 1, dims_array, errorSquareds, compress);
727 NXstatus status = NXclosegroup(
fileID);
728 return ((status == NX_ERROR) ? 3 : 0);
736 NXstatus status = NXmakegroup(
fileID,
"event_workspace",
"NXdata");
737 if (status == NX_ERROR)
739 NXopengroup(
fileID,
"event_workspace",
"NXdata");
741 for (
size_t wi = 0; wi < ws->getNumberHistograms(); wi++) {
742 std::ostringstream group_name;
743 group_name <<
"event_list_" << wi;
748 status = NXclosegroup(
fileID);
749 return ((status == NX_ERROR) ? 3 : 0);
755 bool compress)
const {
761 NXmakedata(
fileID, name, datatype, rank, dims_array);
779 bool writeError)
const {
784 size_t num = events.size();
785 auto tofs =
new double[num];
786 auto weights =
new double[num];
787 auto errorSquareds =
new double[num];
788 auto pulsetimes =
new int64_t[num];
792 for (
auto it = events.cbegin(); it != events.cend(); ++it) {
796 pulsetimes[i] = it->pulseTime().totalNanoseconds();
798 weights[i] = it->weight();
800 errorSquareds[i] = it->errorSquared();
805 int dims_array[1] = {
static_cast<int>(num)};
808 bool compress =
true;
810 NXwritedata(
"tof", NX_FLOAT64, 1, dims_array, tofs, compress);
812 NXwritedata(
"pulsetime", NX_INT64, 1, dims_array, pulsetimes, compress);
814 NXwritedata(
"weight", NX_FLOAT32, 1, dims_array, weights, compress);
816 NXwritedata(
"error_squared", NX_FLOAT32, 1, dims_array, errorSquareds, compress);
821 delete[] errorSquareds;
832 NXstatus status = NXmakegroup(
fileID, group_name.c_str(),
"NXdata");
833 if (status == NX_ERROR)
835 NXopengroup(
fileID, group_name.c_str(),
"NXdata");
842 std::vector<detid_t> detectorIDs(dets.begin(), dets.end());
844 NXwritedata(
"detector_IDs", NX_INT64, 1, dims_array, detectorIDs.data(),
false);
847 std::string eventType(
"UNKNOWN");
855 eventType =
"WEIGHTED";
859 eventType =
"WEIGHTED_NOTIME";
865 std::string sortType;
868 sortType =
"TOF_SORT";
871 sortType =
"PULSETIME_SORT";
875 sortType =
"UNSORTED";
878 NXputattr(
fileID,
"sort_type", sortType.c_str(),
static_cast<int>(sortType.size()), NX_CHAR);
881 NXputattr(
fileID,
"event_type", eventType.c_str(),
static_cast<int>(eventType.size()), NX_CHAR);
883 NXputattr(
fileID,
"num_events", &num, 1, NX_INT64);
886 status = NXclosegroup(
fileID);
887 return ((status == NX_ERROR) ? 3 : 0);
897 bool &uniformBounds, std::string &axesUnits, std::string &yUnits)
const {
900 status = NXopengroup(
fileID,
"workspace",
"NXdata");
901 if (status == NX_ERROR)
906 status = NXopendata(
fileID, entry.c_str());
911 if (status == NX_ERROR) {
916 int rank, dim[2], type;
917 status = NXgetinfo(
fileID, &rank, dim, &type);
918 if (status == NX_ERROR)
920 numberOfSpectra = dim[0];
921 numberOfChannels = dim[1];
923 char sbuf[NX_MAXNAMELEN];
924 int len = NX_MAXNAMELEN;
927 char unitsAttrName[] =
"units";
929 status = NXgetattr(
fileID, unitsAttrName, sbuf, &len, &type);
930 if (status != NX_ERROR)
936 status = NXopendata(
fileID,
"axis1");
937 if (status == NX_ERROR)
941 NXgetattr(
fileID, unitsAttrName, sbuf, &len, &type);
942 axesUnits = std::string(sbuf, len);
943 NXgetinfo(
fileID, &rank, dim, &type);
946 numberOfXpoints = dim[0];
947 uniformBounds =
true;
949 numberOfXpoints = dim[1];
950 uniformBounds =
false;
953 NXopendata(
fileID,
"axis2");
956 NXgetattr(
fileID, unitsAttrName, sbuf, &len, &type);
957 axesUnits += std::string(
":") + std::string(sbuf, len);
967 const std::vector< ::NeXus::AttrInfo> infos =
m_filehandle->getAttrInfos();
969 return std::any_of(infos.cbegin(), infos.cend(), [&target](
const auto &info) { return info.name == target; });
976 int rank, dim[2], type;
979 NXstatus status = NXopengroup(
fileID,
"workspace",
"NXdata");
980 if (status == NX_ERROR)
983 status = NXopendata(
fileID,
"axis1");
984 if (status == NX_ERROR)
986 NXgetinfo(
fileID, &rank, dim, &type);
988 NXgetdata(
fileID, xValues.data());
990 int start[2] = {spectra, 0};
991 int size[2] = {1, dim[1]};
992 NXgetslab(
fileID, xValues.data(), start, size);
1003 int rank, dim[2], type;
1006 NXstatus status = NXopengroup(
fileID,
"workspace",
"NXdata");
1007 if (status == NX_ERROR)
1011 status = NXopendata(
fileID, entry.c_str());
1016 if (status == NX_ERROR) {
1020 NXgetinfo(
fileID, &rank, dim, &type);
1022 int start[2] = {spectra - 1, 0};
1023 int size[2] = {1, dim[1]};
1024 NXgetslab(
fileID, values.data(), start, size);
1028 status = NXopendata(
fileID,
"errors");
1029 if (status == NX_ERROR)
1031 NXgetinfo(
fileID, &rank, dim, &type);
1034 NXgetslab(
fileID, errors.data(), start, size);
1046 std::map<std::string, std::string> entries =
m_filehandle->getEntries();
1047 for (
auto &entrie : entries) {
1048 if (entrie.second ==
"NXentry") {
1049 if (entrie.first.find(
"mantid_workspace_") == 0)
1059 std::map<std::string, std::string> entries =
m_filehandle->getEntries();
1060 return std::any_of(entries.cbegin(), entries.cend(), [&item](
const auto &entry) { return entry.first == item; });
1066 std::map<std::string, std::string> entries =
m_filehandle->getEntries();
1067 for (
auto &entrie : entries) {
1068 if (entrie.second ==
"SDS") {
1073 entry = entrie.first;
1088 std::vector<int> spectra;
1089 std::vector<std::size_t> bins;
1090 std::vector<double> weights;
1091 int spectra_count = 0;
1093 for (std::size_t i = 0; i < ws->getNumberHistograms(); ++i) {
1094 if (ws->hasMaskedBins(i)) {
1096 spectra.emplace_back(spectra_count);
1097 spectra.emplace_back(offset);
1098 for (
const auto &mask : mList) {
1099 bins.emplace_back(mask.first);
1100 weights.emplace_back(mask.second);
1103 offset +=
static_cast<int>(mList.size());
1107 if (spectra_count == 0)
1113 int dimensions[2]{spectra_count, 2};
1114 status = NXmakedata(
fileID,
"masked_spectra", NX_INT32, 2, dimensions);
1115 if (status == NX_ERROR)
1117 NXopendata(
fileID,
"masked_spectra");
1118 const std::string description =
"spectra index,offset in masked_bins and mask_weights";
1119 NXputattr(
fileID,
"description", description.c_str(),
static_cast<int>(description.size() + 1), NX_CHAR);
1120 NXputdata(
fileID, spectra.data());
1124 dimensions[0] =
static_cast<int>(bins.size());
1125 status = NXmakedata(
fileID,
"masked_bins", NX_UINT64, 1, dimensions);
1126 if (status == NX_ERROR)
1128 NXopendata(
fileID,
"masked_bins");
1129 NXputdata(
fileID, bins.data());
1133 dimensions[0] =
static_cast<int>(bins.size());
1134 status = NXmakedata(
fileID,
"mask_weights", NX_FLOAT64, 1, dimensions);
1135 if (status == NX_ERROR)
1137 NXopendata(
fileID,
"mask_weights");
1138 NXputdata(
fileID, weights.data());
1144template <> std::string NexusFileIO::logValueType<double>()
const {
return "double"; }
1146template <> std::string NexusFileIO::logValueType<int>()
const {
return "int"; }
1148template <> std::string NexusFileIO::logValueType<bool>()
const {
return "bool"; }
1164 std::vector<std::string> &definition) {
1168 NXaccess mode = NXACC_READ;
1169 NXstatus stat = NXopen(fileName.c_str(), mode, &fileH);
1170 if (stat == NX_ERROR)
1175 char *nxname, *nxclass;
1177 nxname =
new char[NX_MAXNAMELEN];
1178 nxclass =
new char[NX_MAXNAMELEN];
1179 int rank, dims[2], type;
1184 std::vector<std::string> entryList;
1185 while ((stat = NXgetnextentry(fileH, nxname, nxclass, &nxdatatype)) == NX_OK) {
1186 std::string nxc(nxclass);
1187 if (nxc ==
"NXentry")
1188 entryList.emplace_back(nxname);
1192 for (
auto &entry : entryList) {
1193 NXopengroup(fileH, entry.c_str(),
"NXentry");
1195 while ((NXgetnextentry(fileH, nxname, nxclass, &nxdatatype)) == NX_OK) {
1196 std::string nxc(nxclass), nxn(nxname);
1200 if (nxn ==
"definition" || nxn ==
"analysis") {
1201 NXopendata(fileH, nxname);
1202 stat = NXgetinfo(fileH, &rank, dims, &type);
1203 if (stat == NX_ERROR)
1205 auto value =
new char[dims[0] + 1];
1206 stat = NXgetdata(fileH,
value);
1207 if (stat == NX_ERROR)
1209 value[dims[0]] =
'\0';
1211 definition.emplace_back(
value);
1212 entryName.emplace_back(entry);
1214 NXclosegroup(fileH);
1215 NXclosegroup(fileH);
1223 return (
static_cast<int>(entryName.size()));
const std::vector< double > & rhs
double value
The value of the point.
Class to represent the axis of a workspace.
virtual std::string label(const std::size_t &index) const =0
Returns a text label of for a value Note that the index here is not the index of a value,...
virtual bool isText() const
Returns true if the axis is Text.
virtual std::size_t length() const =0
Get the length of the axis.
const std::shared_ptr< Kernel::Unit > & unit() const
The unit for this axis.
virtual bool isSpectra() const
Returns true is the axis is a Spectra axis.
Column is the base class for columns of TableWorkspace.
T & cell(size_t index)
Templated method for returning a value. No type checks are done.
virtual size_t size() const =0
Number of individual elements in the column.
ConstColumnVector gives const access to the column elements without alowing its resizing.
size_t size()
Size of the vector.
const std::set< detid_t > & getDetectorIDs() const
Get a const reference to the detector IDs set.
std::map< size_t, double > MaskList
Masked bins for each spectrum are stored as a set of pairs containing <bin index, weight>
Helper class for reporting progress from algorithms.
std::vector< Types::Event::TofEvent > & getEvents()
Return the list of TofEvents contained.
EventSortType getSortType() const
Return the type of sorting used in this event list.
std::size_t getNumberEvents() const override
Return the number of events in the list.
Mantid::API::EventType getEventType() const override
Return the type of Event vector contained within.
std::vector< WeightedEventNoTime > & getWeightedEventsNoTime()
Return the list of WeightedEvent contained.
std::vector< WeightedEvent > & getWeightedEvents()
Return the list of WeightedEvent contained.
Records the filename and the description of failure.
void error(const std::string &msg)
Logs at error level.
void reportIncrement(int inc, const std::string &msg="")
Sends the progress notification and increment the loop counter by more than one.
API::Progress * m_progress
Allow an externally supplied progress object to be used.
boost::optional< size_t > optional_size_t
int writeNexusProcessedDataEventCombined(const DataObjects::EventWorkspace_const_sptr &ws, std::vector< int64_t > &indices, double *tofs, float *weights, float *errorSquareds, int64_t *pulsetimes, bool compress) const
Write out a combined chunk of event data.
void writeNexusVectorColumn(const API::Column_const_sptr &col, const std::string &columnName, int nexusType, const std::string &interpret_as) const
Writes given vector column to the currently open Nexus file.
std::string m_filename
nexus file name
~NexusFileIO()
Destructor.
int writeNexusProcessedHeader(const std::string &title, const std::string &wsName="") const
write the header ifon for the Mantid workspace format
bool checkEntryAtLevelByAttribute(const std::string &attribute, std::string &entry) const
Look for entry with given attribute (eg "signal")
std::shared_ptr< ::NeXus::File > m_filehandle
C++ API file handle.
int writeNexusTableWorkspace(const API::ITableWorkspace_const_sptr &itableworkspace, const char *group_name) const
write table workspace
bool checkAttributeName(const std::string &target) const
check if given attribute name is in currently opened entry
bool writeNexusBinMasking(const API::MatrixWorkspace_const_sptr &ws) const
write bin masking information
int getXValues(MantidVec &xValues, const int &spectra) const
read X values for one (or the generic if uniform) spectra
NexusFileIO()
Default constructor.
int writeNexusProcessedData2D(const API::MatrixWorkspace_const_sptr &localworkspace, const bool &uniformSpectra, const std::vector< int > &indices, const char *group_name, bool write2Ddata) const
write the workspace data
bool checkEntryAtLevel(const std::string &item) const
check if the gievn item exists in the current level
int findMantidWSEntries() const
search for exisiting MantidWorkpace_n entries in opened file
void writeNxFloatArray(const std::string &name, const std::vector< double > &values, const std::vector< std::string > &attributes, const std::vector< std::string > &avalues) const
write a float array along with any defined attributes
int writeNexusProcessedDataEvent(const DataObjects::EventWorkspace_const_sptr &ws)
Write out all of the event lists in the given workspace.
bool writeNxStringArray(const std::string &name, const std::vector< std::string > &values, const std::vector< std::string > &attributes, const std::vector< std::string > &avalues) const
write a char array along with any defined attributes
void resetProgress(Mantid::API::Progress *prog)
Reset the pointer to the progress object.
void openNexusWrite(const std::string &fileName, optional_size_t entryNumber=optional_size_t(), const bool append_to_file=true)
open the nexus file for writing
int getWorkspaceSize(int &numberOfSpectra, int &numberOfChannels, int &numberOfXpoints, bool &uniformBounds, std::string &axesUnits, std::string &yUnits) const
find size of open entry data section
int writeEventList(const DataObjects::EventList &el, const std::string &group_name) const
Write out an event list into an already-opened group.
int m_nexuscompression
Nexus compression method.
void closeNexusFile()
close the nexus file
void NXwritedata(const char *name, int datatype, int rank, int *dims_array, void *data, bool compress=false) const
Write out an array to the open file.
void writeEventListData(std::vector< T > events, bool writeTOF, bool writePulsetime, bool writeWeight, bool writeError) const
Write out the event list data, no matter what the underlying event type is.
void writeTableColumn(int type, const std::string &interpret_as, const API::Column &col, const std::string &columnName) const
Save a numeric columns of a TableWorkspace to currently open nexus file.
NXhandle fileID
Nexus file handle.
void closeGroup()
Close the group.
int getSpectra(MantidVec &values, MantidVec &errors, const int &spectra) const
read values and errors for spectra
bool writeNxNote(const std::string ¬eName, const std::string &author, const std::string &date, const std::string &description, const std::string &pairValues) const
write an NXnote with standard fields (but NX_CHAR rather than NX_BINARY data)
Kernel::Logger g_log("ExperimentInfo")
static logger object
std::shared_ptr< const ITableWorkspace > ITableWorkspace_const_sptr
shared pointer to Mantid::API::ITableWorkspace (const version)
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
std::shared_ptr< const Column > Column_const_sptr
bool exists(::NeXus::File &file, const std::string &name)
Based on the current group in the file, does the named sub-entry exist?
std::shared_ptr< const EventWorkspace > EventWorkspace_const_sptr
shared pointer to a const Workspace2D
std::shared_ptr< const RebinnedOutput > RebinnedOutput_const_sptr
shared pointer to a const RebinnedOutput
MANTID_NEXUS_DLL int getNexusEntryTypes(const std::string &fileName, std::vector< std::string > &entryName, std::vector< std::string > &definition)
Get all the Nexus entry types for a file.
std::vector< double > MantidVec
typedef for the data storage used in Mantid matrix workspaces
std::string to_string(const wide_integer< Bits, Signed > &n)
As TableColumn stores its data in a std::vector bool type cannot be used in the same way as the other...