26#include <Poco/DirectoryIterator.h>
28#include <nexus/NeXusFile.hpp>
34using Mantid::HistogramData::HistogramE;
35using Mantid::HistogramData::HistogramX;
36using Mantid::HistogramData::HistogramY;
42struct DataSpaceInformation {
43 DataSpaceInformation(
size_t dimSpectrumAxis = 0,
size_t dimBin = 0)
44 : dimSpectrumAxis(dimSpectrumAxis), dimBin(dimBin) {}
45 size_t dimSpectrumAxis;
49DataSpaceInformation getDataSpaceInfo(H5::DataSet &dataSet) {
50 DataSpaceInformation dataSpaceInfo;
51 auto dataSpace = dataSet.getSpace();
52 const auto rank = dataSpace.getSimpleExtentNdims();
54 std::invalid_argument(
"LoadNXcanSAS: Cannot load a data set "
55 "with more than 2 dimensions.");
58 hsize_t dims[2] = {0, 0};
59 dataSpace.getSimpleExtentDims(dims);
67 dataSpaceInfo.dimSpectrumAxis = dims[0];
68 dataSpaceInfo.dimBin = dims[1];
72std::string getNameOfEntry(H5::H5File &root) {
73 auto numberOfObjects = root.getNumObjs();
74 if (numberOfObjects != 1) {
75 throw std::invalid_argument(
"LoadNXcanSAS: Trying to load multiperiod "
76 "data. This is currently not supported.");
79 auto objectType = root.getObjTypeByIdx(0);
80 if (objectType != H5G_GROUP) {
81 throw std::invalid_argument(
"LoadNXcanSAS: The object below the root is not a H5::Group.");
84 return root.getObjnameByIdx(0);
88 auto dimInfo = getDataSpaceInfo(dataSet);
92 dimInfo.dimBin , dimInfo.dimBin );
96 auto dimInfo = getDataSpaceInfo(dataSet);
100 dimInfo.dimBin + 1 , dimInfo.dimBin );
105void addLogFromGroupIfExists(H5::Group &sasGroup, std::string
const &sasTerm,
Run &run,
106 std::string
const &propertyName) {
108 if (!
value.empty()) {
126 if (!title.empty()) {
132std::string extractIdfFileOnCurrentSystem(
const std::string &idf) {
139 Poco::Path path(idf);
140 const auto &fileName = path.getFileName();
144 Poco::DirectoryIterator end_iter;
145 for (
const auto &directoryName : directoryNames) {
146 for (Poco::DirectoryIterator dir_itr(directoryName); dir_itr != end_iter; ++dir_itr) {
147 if (Poco::File(dir_itr->path()).isFile()) {
148 if (fileName == Poco::Path(dir_itr->path()).getFileName()) {
149 return Poco::Path(dir_itr->path()).absolute().toString();
162 if (instrumentName.empty()) {
168 idf = extractIdfFileOnCurrentSystem(idf);
173 instAlg->initialize();
174 instAlg->setChild(
true);
175 instAlg->setProperty(
"Workspace",
workspace);
176 instAlg->setProperty(
"InstrumentName", instrumentName);
178 instAlg->setProperty(
"Filename", idf);
180 instAlg->setProperty(
"RewriteSpectraMap",
"False");
182 }
catch (std::invalid_argument &) {
184 }
catch (std::runtime_error &) {
185 g_log.
information(
"Unable to successfully run LoadInstrument Child Algorithm.");
192 auto intensity = dataGroup.openDataSet(
sasDataI);
193 auto dataSpaceInfo = getDataSpaceInfo(intensity);
195 if (dataSpaceInfo.dimSpectrumAxis == 1 && dataSpaceInfo.dimBin > 0) {
196 dimensionality = WorkspaceDimensionality::oneD;
197 }
else if (dataSpaceInfo.dimSpectrumAxis > 1 && dataSpaceInfo.dimBin > 0) {
198 dimensionality = WorkspaceDimensionality::twoD;
200 dimensionality = WorkspaceDimensionality::other;
202 return dimensionality;
205std::string getUnit(H5::DataSet &dataSet) {
209bool hasQDev(H5::Group &dataGroup) {
213 }
catch (H5::GroupIException &) {
215 }
catch (H5::FileIException &) {
228 workspace->getAxis(0)->setUnit(
"MomentumTransfer");
233 auto iDataSet = dataGroup.openDataSet(
sasDataI);
234 auto yUnit = getUnit(iDataSet);
241 bool hasQResolution = hasQDev(dataGroup);
242 if (hasQResolution) {
248template <
typename Functor>
250 const H5::DataType &memoryDataType) {
252 auto dimInfo = getDataSpaceInfo(dataSet);
255 auto fileSpace = dataSet.getSpace();
258 const hsize_t rank = 2;
259 hsize_t sizeOfSingleSlab[rank] = {1, dimInfo.dimBin};
260 hsize_t start[rank] = {0, 0};
263 hsize_t memSpaceDimension[1] = {dimInfo.dimBin};
264 H5::DataSpace memSpace(1, memSpaceDimension);
270 fileSpace.selectHyperslab(H5S_SELECT_SET, sizeOfSingleSlab, start);
271 dataSet.read(data.data(), memoryDataType, memSpace, fileSpace);
279 const H5::DataType &memoryDataType) {
283 auto dimInfo = getDataSpaceInfo(dataSet);
286 if (
workspace->getAxis(1)->isSpectra()) {
287 auto newAxis = std::make_unique<Mantid::API::NumericAxis>(dimInfo.dimSpectrumAxis);
288 workspace->replaceAxis(1, std::move(newAxis));
292 auto fileSpace = dataSet.getSpace();
295 const hsize_t rank = 2;
296 hsize_t sizeOfSingleSlab[rank] = {dimInfo.dimSpectrumAxis, 1};
297 hsize_t start[rank] = {0, 0};
300 hsize_t memSpaceDimension[1] = {dimInfo.dimSpectrumAxis};
301 H5::DataSpace memSpace(1, memSpaceDimension);
304 fileSpace.selectHyperslab(H5S_SELECT_SET, sizeOfSingleSlab, start);
308 data.resize(dimInfo.dimSpectrumAxis);
309 dataSet.read(data.data(), memoryDataType, memSpace, fileSpace);
325 auto iDataSet = dataGroup.openDataSet(
sasDataI);
327 return ws->mutableY(
index);
330 read2DWorkspace(iDataSet,
workspace, iExtractor, iDataType);
331 auto yUnit = getUnit(iDataSet);
336 auto eDataSet = dataGroup.openDataSet(
sasDataIdev);
338 return ws->mutableE(
index);
340 read2DWorkspace(eDataSet,
workspace, eExtractor, iDataType);
344 auto qxDataSet = dataGroup.openDataSet(
sasDataQx);
346 return ws->mutableX(
index);
349 read2DWorkspace(qxDataSet,
workspace, qxExtractor, qxDataType);
350 workspace->getAxis(0)->setUnit(
"MomentumTransfer");
354 auto qyDataSet = dataGroup.openDataSet(
sasDataQy);
356 readQyInto2DWorkspace(qyDataSet,
workspace, qyDataType);
361 auto dimensionality = getWorkspaceDimensionality(dataGroup);
362 switch (dimensionality) {
363 case (WorkspaceDimensionality::oneD):
366 case (WorkspaceDimensionality::twoD):
370 throw std::invalid_argument(
"LoadNXcanSAS: Cannot load workspace which not 1D or 2D.");
374bool findDefinition(::NeXus::File &file) {
375 bool foundDefinition =
false;
376 auto entries = file.getEntries();
378 for (
auto &entry : entries) {
380 file.openGroup(entry.first, entry.second);
382 auto definitionFromFile = file.getStrData();
384 foundDefinition =
true;
391 return foundDefinition;
395bool hasTransmissionEntry(H5::Group &entry,
const std::string &name) {
396 bool hasTransmission(
false);
399 hasTransmission =
true;
400 }
catch (H5::GroupIException &) {
401 }
catch (H5::FileIException &) {
403 return hasTransmission;
426#if defined(H5_USE_18_API)
427 const std::string objectName{transmission.getObjName()};
429 const size_t nchars = H5Iget_name(transmission.getId(),
nullptr, 0);
430 std::string objectName;
431 objectName.resize(nchars);
432 H5Iget_name(transmission.getId(), objectName.data(),
435 throw std::runtime_error(
"Unexpected array size for lambda in transmission group '" + objectName +
453 const std::string &extn = descriptor.
extension();
454 if (extn !=
".nxs" && extn !=
".h5") {
460 ::NeXus::File &file = descriptor.
data();
463 bool foundDefinition = findDefinition(file);
464 if (foundDefinition) {
475 const std::vector<std::string> exts{
".nxs",
".h5"};
477 "The name of the NXcanSAS file to read, as a full or relative path.");
480 "The name of the workspace to be created as the output of "
481 "the algorithm. A workspace of this name will be created "
482 "and stored in the Analysis Data Service. For multiperiod "
483 "files, one workspace may be generated for each period. "
484 "Currently only one workspace can be saved at a time so "
485 "multiperiod Mantid files are not generated.");
488 "Load the transmission related data from the file if it is present "
489 "(optional, default False).");
494 const bool loadTransmissions =
getProperty(
"LoadTransmission");
495 H5::H5File file(fileName, H5F_ACC_RDONLY);
498 const int numberOfSteps = loadTransmissions ? 4 : 3;
501 auto entryName = getNameOfEntry(file);
502 auto entry = file.openGroup(entryName);
506 auto intensity = dataGroup.openDataSet(
sasDataI);
514 progress.report(
"Loading instrument.");
515 loadInstrument(entry, ws);
523 if (loadTransmissions) {
524 progress.report(
"Loading transmissions.");
536 if (!hasTransmissionEntry(entry,
name)) {
545 auto workspace = createWorkspaceForHistogram(tDataSet);
550 const std::string transExtension =
"_trans_" +
name;
551 title += transExtension;
558 loadTransmissionData(transmission,
workspace);
562 workspace->setYUnitLabel(
"Transmission");
566 std::string propertyName;
567 if (
name ==
"sample")
568 propertyName =
"TransmissionWorkspace";
570 propertyName =
"TransmissionCanWorkspace";
571 const std::string doc =
"The transmission workspace";
const std::vector< double > * lambda
double value
The value of the point.
IPeaksWorkspace_sptr workspace
std::map< DeltaEMode::Type, std::string > index
#define DECLARE_NEXUS_FILELOADER_ALGORITHM(classname)
DECLARE_NEXUS_FILELOADER_ALGORITHM should be used in place of the standard DECLARE_ALGORITHM macro wh...
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.
@ Load
allowed here which will be passed to the algorithm
void addLogData(Kernel::Property *p)
Add a log entry.
Helper class for reporting progress from algorithms.
This class stores information regarding an experimental run as a series of log entries.
A property class for workspaces.
LoadNXcanSAS : Tries to load an NXcanSAS file type into a Workspace2D.
LoadNXcanSAS()
Constructor.
void init() override
Initialisation code.
const std::string name() const override
function to return a name of the algorithm, must be overridden in all algorithms
void loadTransmission(H5::Group &entry, const std::string &name)
Loads the transmission runs.
int confidence(Kernel::NexusDescriptor &descriptor) const override
Returns a confidence value that this algorithm can load a file.
void exec() override
Execution code.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
The Logger class is in charge of the publishing messages from the framework through various channels.
void information(const std::string &msg)
Logs at information level.
Defines a wrapper around a file whose internal structure can be accessed using the NeXus API.
const std::string & extension() const
Access the file extension.
inline ::NeXus::File & data()
Access the open NeXus File object.
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< T > createWorkspace(InitArgs... args)
Kernel::Logger g_log("ExperimentInfo")
static logger object
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
template MANTID_DATAHANDLING_DLL std::vector< double > readArray1DCoerce< double >(DataSet &dataset)
MANTID_DATAHANDLING_DLL std::string readString(H5::H5File &file, const std::string &path)
std::string readAttributeAsString(LocationType &dataset, const std::string &attributeName)
MANTID_DATAHANDLING_DLL DataType getType< double >()
const std::string sasInstrumentIDF
const std::string sasDataIdev
const std::string sasProcessGroupName
const std::string sasInstrumentName
const std::string sasDataQx
const std::string sasEntryRunInLogs
const std::string sasEntryRun
const std::string sasTransmissionSpectrumNameCanAttrValue
const std::string nxEntryClassAttr
const std::string sasProcessTermUserFile
const std::string sasDataGroupName
const std::string sasTransmissionSpectrumTdev
const std::string sasTransmissionSpectrumT
const std::string sasDataQy
const std::string sasEntryClassAttr
const std::string sasDataQdev
const std::string sasTransmissionSpectrumLambda
const std::string sasDataQ
const std::string sasDataI
const std::string sasEntryDefinition
const std::string sasUnitAttr
const std::string sasTransmissionSpectrumNameSampleAttrValue
const std::string sasProcessUserFileInLogs
const std::string sasEntryDefinitionFormat
const std::string sasProcessBatchFileInLogs
const std::string sasTransmissionSpectrumGroupName
const std::string sasProcessTermBatchFile
const std::string sasEntryTitle
const std::string sasInstrumentGroupName
std::vector< double > MantidVec
typedef for the data storage used in Mantid matrix workspaces
std::string to_string(const wide_integer< Bits, Signed > &n)
@ Input
An input workspace.
@ Output
An output workspace.