24#include <nexus/NeXusFile.hpp>
25#include <nexus/NeXusException.hpp>
32using namespace Kernel;
34using namespace DataObjects;
39 :
API::
Algorithm(), m_includeError(false), m_overwriteFile(false), m_spectraCount(0), m_filename(
"") {}
45 auto wsValidator = std::make_shared<CompositeValidator>();
53 "The name of the workspace(s) to save - this can be the name of a single "
54 "Workspace2D or the name of a WorkspaceGroup in which case all the "
55 "Workspace2Ds included in the group will be saved.");
58 std::make_unique<API::FileProperty>(
"Filename",
"",
FileProperty::Save, std::vector<std::string>(1,
".nxs")),
59 "The name of the NXTomo file to write, as a full or relative path");
62 "Replace any existing file of the same name instead of appending data?");
65 "Write the error values to NXTomo file?");
75 m_workspaces.emplace_back(std::dynamic_pointer_cast<Workspace2D>(
m));
91 for (
int i = 0; i < groupWS->getNumberOfEntries(); ++i) {
92 m_workspaces.emplace_back(std::dynamic_pointer_cast<Workspace2D>(groupWS->getItem(i)));
114 const std::string workspaceID =
workspace->id();
116 if ((workspaceID.find(
"Workspace2D") == std::string::npos) &&
117 (workspaceID.find(
"RebinnedOutput") == std::string::npos))
167 NXstatus status = NXopen(this->
m_filename.c_str(), NXACC_RDWR, &fileHandle);
171 ::NeXus::File nxFile(fileHandle);
176 if (status != NX_ERROR) {
177 ::NeXus::File f(fileHandle);
185 status = NXopen(this->
m_filename.c_str(), NXACC_CREATE5, &fileHandle);
187 if (status == NX_ERROR)
188 throw std::runtime_error(
"Unable to open or create nexus file.");
193 ::NeXus::File nxFile(fileHandle);
196 nxFile.makeGroup(
"entry1",
"NXentry",
true);
199 nxFile.makeGroup(
"log_info",
"NXsubentry",
false);
202 nxFile.makeGroup(
"tomo_entry",
"NXsubentry",
true);
208 nxFile.writeData(
"definition",
"NXtomo");
209 nxFile.openData(
"definition");
214 nxFile.writeData(
"program_name",
"mantid");
215 nxFile.openData(
"program_name");
221 nxFile.makeGroup(
"instrument",
"NXinstrument",
true);
227 nxFile.makeGroup(
"detector",
"NXdetector",
true);
229 std::vector<int64_t> infDim;
230 infDim.emplace_back(NX_UNLIMITED);
232 nxFile.makeData(
"image_key", ::NeXus::FLOAT64, infDim,
false);
242 nxFile.makeGroup(
"sample",
"NXsample",
true);
244 nxFile.makeData(
"rotation_angle", ::NeXus::FLOAT64, infDim,
true);
246 NXlink rotationLink = nxFile.getDataID();
253 nxFile.makeGroup(
"control",
"NXmonitor",
true);
254 nxFile.makeData(
"data", ::NeXus::FLOAT64, infDim,
false);
257 nxFile.makeGroup(
"data",
"NXdata",
true);
258 nxFile.putAttr<
int>(
"NumFiles", 0);
260 nxFile.makeLink(rotationLink);
264 NXlink dataLink = nxFile.getDataID();
273 nxFile.openGroup(
"instrument",
"NXinstrument");
274 nxFile.openGroup(
"detector",
"NXdetector");
275 nxFile.makeLink(dataLink);
292 nxFile.openPath(
"/entry1/tomo_entry/data");
294 throw std::runtime_error(
"Unable to create a valid NXTomo file");
298 nxFile.getAttr<
int>(
"NumFiles", numFiles);
305 std::vector<double> rotValue;
306 rotValue.emplace_back(0);
308 if (
workspace->run().hasProperty(
"Rotation")) {
309 std::string tmpVal =
workspace->run().getLogData(
"Rotation")->value();
311 rotValue[0] = boost::lexical_cast<double>(tmpVal);
317 nxFile.openData(
"rotation_angle");
318 nxFile.putSlab(rotValue, numFiles, 1);
323 nxFile.openData(
"data");
328 bool spectrumPerPixel = (1 ==
workspace->y(0).size());
332 if (spectrumPerPixel) {
344 nxFile.putAttr(
"NumFiles", numFiles + 1);
359 nxFile.openPath(
"/entry1/tomo_entry/instrument/detector");
361 throw std::runtime_error(
"Unable to create a valid NXTomo file");
365 std::vector<double> keyValue;
366 keyValue.emplace_back(0);
368 if (
workspace->run().hasProperty(
"ImageKey")) {
369 std::string tmpVal =
workspace->run().getLogData(
"ImageKey")->value();
371 keyValue[0] = boost::lexical_cast<double>(tmpVal);
377 nxFile.openData(
"image_key");
378 nxFile.putSlab(keyValue, thisFileInd, 1);
390 nxFile.openPath(
"/entry1/log_info");
392 throw std::runtime_error(
"Unable to create a valid NXTomo file");
397 const auto &logVals =
workspace->run().getLogData();
399 for (
const auto &prop : logVals) {
400 if (prop->name() !=
"ImageKey" && prop->name() !=
"Rotation" && prop->name() !=
"Intensity" &&
401 prop->name() !=
"Axis1" && prop->name() !=
"Axis2") {
403 nxFile.openData(prop->name());
404 }
catch (::NeXus::Exception &) {
406 std::vector<int64_t> infDim;
407 infDim.emplace_back(NX_UNLIMITED);
408 infDim.emplace_back(NX_UNLIMITED);
409 nxFile.makeData(prop->name(), ::NeXus::UINT8, infDim,
true);
411 auto valueAsStr = prop->value();
412 size_t strSize = valueAsStr.length();
417 std::vector<int64_t> start = {thisFileInd, 0};
418 std::vector<int64_t> size = {1,
static_cast<int64_t
>(strSize)};
420 nxFile.putSlab(valueAsStr.data(), start, size);
431 nxFile.openPath(
"/entry1/tomo_entry/control");
433 throw std::runtime_error(
"Unable to create a valid NXTomo file");
436 std::vector<double> intensityValue;
437 intensityValue.emplace_back(1);
439 if (
workspace->run().hasProperty(
"Intensity")) {
440 std::string tmpVal =
workspace->run().getLogData(
"Intensity")->value();
442 intensityValue[0] = boost::lexical_cast<double>(tmpVal);
448 nxFile.openData(
"data");
449 nxFile.putSlab(intensityValue, thisFileInd, 1);
#define DECLARE_ALGORITHM(classname)
double value
The value of the point.
IPeaksWorkspace_sptr workspace
std::string getName(const IMDDimension &self)
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.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
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
A validator which checks that a workspace contains histogram data (the default) or point data as requ...
Helper class for reporting progress from algorithms.
Class to hold a set of workspaces.
A property class for workspaces.
void writeImageKeyValue(const DataObjects::Workspace2D_sptr &workspace, ::NeXus::File &nxFile, int thisFileInd)
static const std::string NXTOMO_VER
file format version
bool processGroups() override
Alternative execution code when operating on a WorkspaceGroup.
void writeIntensityValue(const DataObjects::Workspace2D_sptr &workspace, ::NeXus::File &nxFile, int thisFileInd)
::NeXus::File setupFile()
Creates the format for the output file if it doesn't exist.
void processAll()
Main exec routine, called for group or individual workspace processing.
std::vector< DataObjects::Workspace2D_sptr > m_workspaces
void init() override
Initialisation code.
std::vector< int64_t > m_slabSize
void writeSingleWorkspace(const DataObjects::Workspace2D_sptr &workspace, ::NeXus::File &nxFile)
Writes a single workspace into the file.
void exec() override
Execution code : Single workspace.
const std::string name() const override
Algorithm's name for identification overriding a virtual method.
std::vector< int64_t > m_dimensions
std::vector< int64_t > m_slabStart
std::vector< int64_t > m_infDimensions
void writeLogValues(const DataObjects::Workspace2D_sptr &workspace, ::NeXus::File &nxFile, int thisFileInd)
Write various pieces of data from the workspace log with checks on the structure of the nexus file.
std::string m_filename
The filename of the output file.
Marks code as not implemented yet.
static const char * version()
The full version number.
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< WorkspaceGroup > WorkspaceGroup_sptr
shared pointer to Mantid::API::WorkspaceGroup
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::shared_ptr< Workspace2D > Workspace2D_sptr
shared pointer to Mantid::DataObjects::Workspace2D
@ Input
An input workspace.