23#include <boost/scoped_array.hpp>
37using namespace Kernel;
39using namespace DataObjects;
40using namespace Geometry;
44 :
Algorithm(), m_progress(), m_compress(false), links_count(0), inId(), outId() {}
52 std::initializer_list<std::string> exts = {
".nxs"};
55 "The name of the original Nexus file for this data,\n"
56 "as a full or relative path");
59 "Name of the workspace to be saved");
62 "The name of the Nexus file to write, as a full or relative\n"
66 "Will the output NXS file data be compressed?");
93 if (tstr !=
nullptr && !strcmp(path, tstr + 1)) {
96 printf(
"path error\n");
106 int nx_is_definition = 0;
112 if (NXopen(inFile, nx__access, &
inId) != NX_OK) {
113 printf(
"NX_ERROR: Can't open %s\n", inFile);
117 if (NXopen(outFile, nx_write_access, &
outId) != NX_OK) {
118 printf(
"NX_ERROR: Can't open %s\n", outFile);
131 if (NXclose(&
inId) != NX_OK) {
141 if (NXgetdataID(
outId, &link) == NX_OK || NXgetgroupID(
outId, &link) == NX_OK) {
146 if (NXmakelink(
outId, &link) != NX_OK)
158 if (NXclose(&
outId) != NX_OK) {
181 const char *field_name,
const char *errors_field_name,
bool doErrors,
182 bool doBoth,
int is_definition,
const std::string &bank) {
183 int dataRank, dataDimensions[NX_MAXRANK];
184 int slabDimensions[NX_MAXRANK], slabStartIndices[NX_MAXRANK];
189 dataDimensions[0] = det->xpixels();
191 dataDimensions[1] = det->ypixels();
197 slabDimensions[0] = x_pixel_slab;
198 slabDimensions[1] = dataDimensions[1];
199 slabDimensions[2] = dataDimensions[2];
202 slabDimensions[0] = dataDimensions[0];
204 std::cout <<
"RectangularDetector " << det->getName() <<
" being copied. Dimensions : " << dataDimensions[0] <<
", "
205 << dataDimensions[1] <<
", " << dataDimensions[2] <<
".\n";
209 if (NXcompmakedata(
outId, field_name, NX_FLOAT32, dataRank, dataDimensions, NX_COMP_LZW, slabDimensions) != NX_OK)
212 if (NXmakedata(
outId, field_name, NX_FLOAT32, dataRank, dataDimensions) != NX_OK)
215 if (NXopendata(
outId, field_name) != NX_OK)
222 NXname attrName =
"errors";
223 std::string attrBuffer = errors_field_name;
224 if (NXputattr(
outId, attrName, attrBuffer.c_str(),
static_cast<int>(attrBuffer.size()), NX_CHAR) != NX_OK)
230 if (NXclosedata(
outId) != NX_OK)
234 if (NXcompmakedata(
outId, errors_field_name, NX_FLOAT32, dataRank, dataDimensions, NX_COMP_LZW, slabDimensions) !=
238 if (NXmakedata(
outId, errors_field_name, NX_FLOAT32, dataRank, dataDimensions) != NX_OK)
241 if (NXopendata(
outId, errors_field_name) != NX_OK)
255 if (NXclosedata(
outId) != NX_OK)
263 auto data =
new float[slabDimensions[0] * slabDimensions[1] * slabDimensions[2]];
266 float *errors =
nullptr;
268 errors =
new float[slabDimensions[0] * slabDimensions[1] * slabDimensions[2]];
270 for (
int x = 0;
x < det->xpixels();
x++) {
272 int slabnum =
x / x_pixel_slab;
275 int slabx =
x % x_pixel_slab;
278 auto ypixels =
static_cast<int>(det->ypixels());
281 for (
int y = 0;
y < ypixels;
y++) {
286 wi =
m_map.find(det->getAtXY(
x,
y)->getID())->second;
288 std::cout <<
"Error finding " << bank <<
" x " <<
x <<
" y " <<
y <<
"\n";
293 size_t(slabx) * size_t(dataDimensions[1]) * size_t(dataDimensions[2]) + size_t(
y) * size_t(dataDimensions[2]);
298 for (
size_t i = 0; i <
Y.size(); ++i) {
300 data[i +
index] =
static_cast<float>(E[i]);
302 data[i +
index] =
static_cast<float>(
Y[i]);
304 errors[i +
index] =
static_cast<float>(E[i]);
316 if (!doBoth && (
x % x_pixel_slab == x_pixel_slab - 1)) {
320 slabStartIndices[0] = slabnum * x_pixel_slab;
321 slabStartIndices[1] = 0;
322 slabStartIndices[2] = 0;
323 if (NXputslab(
outId, data, slabStartIndices, slabDimensions) != NX_OK)
327 std::ostringstream mess;
328 mess << det->getName() <<
", " << field_name <<
" slab " << slabnum <<
" of " << det->xpixels() / x_pixel_slab;
329 this->
m_progress->reportIncrement(x_pixel_slab * det->ypixels(), mess.str());
335 bool returnerror =
false;
338 if (NXopendata(
outId, field_name) != NX_OK)
340 else if (NXputdata(
outId, data) != NX_OK)
342 else if (NXclosedata(
outId) != NX_OK)
345 this->
m_progress->reportIncrement(det->xpixels() * det->ypixels() * 1, det->getName() +
" data");
347 if (NXopendata(
outId, errors_field_name) != NX_OK)
349 else if (NXputdata(
outId, errors) != NX_OK)
351 else if (NXclosedata(
outId) != NX_OK)
354 this->
m_progress->reportIncrement(det->xpixels() * det->ypixels() * 1, det->getName() +
" errors");
367 if (NXclosedata(
outId) != NX_OK) {
373 std::cout <<
"Filling out " << det->getName() <<
" took " << fillTime <<
" sec.\n";
374 std::cout <<
"Saving " << det->getName() <<
" took " << saveTime <<
" sec.\n";
391 int dataType, dataRank, dataDimensions[NX_MAXRANK];
395 if (NXgetinfo(
inId, &dataRank, dataDimensions, &dataType) != NX_OK)
402 g_log.
information() <<
"Detector '" + bank +
"' not found, or it is not a rectangular detector!\n";
404 if (NXmalloc(&dataBuffer, dataRank, dataDimensions, dataType) != NX_OK)
406 if (NXgetdata(
inId, dataBuffer) != NX_OK)
408 if (NXcompmakedata(
outId,
name, dataType, dataRank, dataDimensions, NX_COMP_LZW, dataDimensions) != NX_OK)
414 if (NXputdata(
outId, dataBuffer) != NX_OK)
416 if (NXfree(&dataBuffer) != NX_OK)
418 if (NXclosedata(
outId) != NX_OK)
424 size_t memory_required =
425 size_t(det->xpixels() * det->ypixels()) * size_t(
m_inputWorkspace->blocksize()) * 2 *
sizeof(float);
428 size_t memory_available = mem.
availMem() * 1024;
430 std::cout <<
"Memory available: " << memory_available / 1024 <<
" kb. ";
431 std::cout <<
"Memory required: " << memory_required / 1024 <<
" kb. ";
434 memory_available = memory_available / 2;
435 if (memory_available >
static_cast<size_t>(5e9))
436 memory_available =
static_cast<size_t>(5e9);
438 if (memory_available < memory_required) {
442 static_cast<int>(memory_available / (det->ypixels() *
m_inputWorkspace->blocksize() * 2 *
sizeof(float)));
447 if ((det->xpixels() % x_slab) == 0)
452 std::cout <<
"Saving in slabs of " << x_slab <<
" X pixels.\n";
453 if (this->
WriteOutDataOrErrors(det, x_slab,
"data",
"data_errors",
false,
false, is_definition, bank) != NX_OK)
455 if (this->
WriteOutDataOrErrors(det, x_slab,
"errors",
"",
true,
false, is_definition, bank) != NX_OK)
458 std::cout <<
"Saving in one block.\n";
459 if (this->
WriteOutDataOrErrors(det, det->xpixels(),
"data",
"data_errors",
false,
true, is_definition, bank) !=
471 int status, dataType, dataRank, dataDimensions[NX_MAXRANK];
472 NXname
name, theClass;
477 status = NXgetnextentry(
inId,
name, theClass, &dataType);
480 if (status == NX_ERROR)
482 if (status == NX_OK) {
483 if (!strncmp(theClass,
"NX", 2)) {
484 if (NXopengroup(
inId,
name, theClass) != NX_OK)
488 if (NXgetgroupID(
inId, &link) != NX_OK)
492 if (NXmakegroup(
outId,
name, theClass) != NX_OK)
494 if (NXopengroup(
outId,
name, theClass) != NX_OK)
507 if (NXclosegroup(
inId) != NX_OK)
510 }
else if (!strncmp(theClass,
"SDS", 3)) {
512 if (NXopendata(
inId,
name) != NX_OK)
514 if (NXgetdataID(
inId, &link) != NX_OK)
517 std::string data_label(
name);
524 size_t a = path.rfind(
'/');
525 if (a != std::string::npos && a > 0) {
526 size_t b = path.rfind(
'/', a - 1);
527 if (b != std::string::npos && (b < a) && (a - b - 1) > 0) {
528 bank = path.substr(b + 1, a - b - 1);
534 if (data_label ==
"data" && (!bank.empty())) {
540 else if (data_label ==
"time_of_flight" && (!bank.empty())) {
542 if (NXgetinfo(
inId, &dataRank, dataDimensions, &dataType) != NX_OK)
548 dataDimensions[0] =
static_cast<int>(
X.size());
550 std::vector<float> tof_data(dataDimensions[0]);
553 std::transform(
X.cbegin(),
X.cend(), tof_data.begin(), [](
double x) { return static_cast<float>(x); });
555 if (NXcompmakedata(
outId,
name, dataType, dataRank, dataDimensions, NX_COMP_LZW, dataDimensions) != NX_OK)
561 if (NXputdata(
outId, tof_data.data()) != NX_OK)
563 if (NXclosedata(
outId) != NX_OK)
571 if (NXgetinfo(
inId, &dataRank, dataDimensions, &dataType) != NX_OK)
573 if (NXmalloc(&dataBuffer, dataRank, dataDimensions, dataType) != NX_OK)
575 if (NXgetdata(
inId, dataBuffer) != NX_OK)
577 if (NXcompmakedata(
outId,
name, dataType, dataRank, dataDimensions, NX_COMP_LZW, dataDimensions) != NX_OK)
583 if (NXputdata(
outId, dataBuffer) != NX_OK)
585 if (NXfree(&dataBuffer) != NX_OK)
587 if (NXclosedata(
outId) != NX_OK)
600 if (NXclosedata(
inId) != NX_OK)
603 }
else if (status == NX_EOD) {
604 if (NXclosegroup(
inId) != NX_OK)
606 if (NXclosegroup(
outId) != NX_OK)
610 }
while (status == NX_OK);
619 int status, attrLen, attrType;
627 std::array<const char *, 6> attrs = {
628 {
"NeXus_version",
"XML_version",
"HDF_version",
"HDF5_Version",
"file_name",
"file_time"}};
632 status = NXgetnextattr(
inId, attrName, &attrLen, &attrType);
634 status = NXgetnextattra(
inId, attrName, &rank, dims, &attrType);
636 if (status == NX_ERROR)
638 if (status == NX_OK) {
644 if (std::none_of(attrs.cbegin(), attrs.cend(),
645 [&attrName](
const char *
name) { return strcmp(attrName, name) == 0; })) {
647 if (NXmalloc(&attrBuffer, 1, &attrLen, attrType) != NX_OK)
649 if (NXgetattr(
inId, attrName, attrBuffer, &attrLen, &attrType) != NX_OK)
651 if (NXputattr(
outId, attrName, attrBuffer, attrLen, attrType) != NX_OK)
653 if (NXfree(&attrBuffer) != NX_OK)
657 }
while (status != NX_EOD);
663 std::cout <<
"Nexus Error: " << text <<
"\n";
673 NXMEnableErrorReporting();
689 if (eventWorkspace) {
697 throw std::runtime_error(
"Nexus error while copying the file.");
#define DECLARE_ALGORITHM(classname)
std::map< DeltaEMode::Type, std::string > index
#define PARALLEL_START_INTERRUPT_REGION
Begins a block to skip processing is the algorithm has been interupted Note the end of the block if n...
#define PARALLEL_END_INTERRUPT_REGION
Ends a block to skip processing is the algorithm has been interupted Note the start of the block if n...
#define PARALLEL_FOR_IF(condition)
Empty definitions - to enable set your complier to enable openMP.
#define PARALLEL_CHECK_INTERRUPT_REGION
Adds a check after a Parallel region to see if it was interupted.
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.
@ 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
A property class for workspaces.
int add_path(const char *path)
Append to current_path.
void init() override
Overwrites Algorithm method.
API::MatrixWorkspace_const_sptr m_inputWorkspace
Pointer to the local workspace.
std::string m_outputFilename
The name and path of the output file.
SaveToSNSHistogramNexus()
Default constructor.
int remove_path(const char *path)
Remove the last part of the path.
int copy_file(const char *inFile, int nx_read_access, const char *outFile, int nx_write_access)
Performs the copying from the input to the output file, while modifying the data and time_of_flight f...
const std::string name() const override
Algorithm's name for identification overriding a virtual method.
void exec() override
Overwrites Algorithm method.
int WriteDataGroup(const std::string &bank, int is_definition)
Write the group labeled "data".
std::string m_inputFilename
The name and path of the input file.
int WriteGroup(int is_definition)
Prints the contents of each group as XML tags and values.
std::unique_ptr< API::Progress > m_progress
int WriteOutDataOrErrors(const Geometry::RectangularDetector_const_sptr &det, int x_pixel_slab, const char *field_name, const char *errors_field_name, bool doErrors, bool doBoth, int is_definition, const std::string &bank)
Utility function to write out the data or errors to a field in the group.
int WriteAttributes(int is_definition)
Copy the attributes from input to output.
struct link_to_make links_to_make[1024]
void information(const std::string &msg)
Logs at information level.
This class is responsible for memory statistics.
void update()
Update the structure with current information, taking into account what is to be ignored.
std::size_t availMem() const
Returns the available memory of the system in kiB.
The concrete, templated class for properties.
A simple class that provides a wall-clock (not processor time) timer.
float elapsed(bool reset=true)
Returns the wall-clock time elapsed in seconds since the Timer object's creation, or the last call to...
void nexus_print_error(void *pD, char *text)
std::shared_ptr< const EventWorkspace > EventWorkspace_const_sptr
shared pointer to a const Workspace2D
std::shared_ptr< const IComponent > IComponent_const_sptr
Typdef of a shared pointer to a const IComponent.
std::shared_ptr< const RectangularDetector > RectangularDetector_const_sptr
std::enable_if< std::is_pointer< Arg >::value, bool >::type threadSafe(Arg workspace)
Thread-safety check Checks the workspace to ensure it is suitable for multithreaded access.
@ Input
An input workspace.