20#include "MantidNexus/NexusFile.h"
27Kernel::Logger
g_log(
"LoadHelper");
30namespace DataHandling {
31using namespace Kernel;
39 std::string result(
"");
40 std::vector<Mantid::Nexus::NXClassInfo> v = firstEntry.
groups();
41 const auto it = std::find_if(v.cbegin(), v.cend(), [](
const auto &
group) { return group.nxclass ==
"NXinstrument"; });
49 const std::string &nexusAddress) {
50 return firstEntry.
getString(nexusAddress);
54 const std::string &nexusAddress) {
55 return firstEntry.
getFloat(nexusAddress);
63 const std::string &nexusAddress) {
66 timeBinningNexus.
load();
68 size_t numberOfBins =
static_cast<size_t>(timeBinningNexus.
dim0()) + 1;
70 float *timeBinning_p = &timeBinningNexus[0];
71 std::vector<double> timeBinning(numberOfBins);
72 std::copy(timeBinning_p, timeBinning_p + timeBinningNexus.
dim0(), std::begin(timeBinning));
74 timeBinning[numberOfBins - 1] = timeBinning[numberOfBins - 2] + timeBinning[1] - timeBinning[0];
96 if (wavelength <= 0) {
97 throw std::runtime_error(
"Wavelenght is <= 0");
102 return distance / velocity;
111 std::vector<std::string> prop =
workspace->getInstrument()->getStringParameter(s);
115 return boost::lexical_cast<double>(prop[0]);
129 bool useFullAddress) {
133 std::string entryNameActual(entryName);
134 if (entryName.empty()) {
135 entryNameActual = filehandle.getTopLevelEntryName();
139 if (!entryNameActual.empty()) {
140 constexpr int LEVEL_RECURSE{1};
141 filehandle.openGroup(entryNameActual,
"NXentry");
142 const std::string EMPTY_STR;
144 filehandle.closeGroup();
149template <
typename NumericType>
150void addNumericProperty(Nexus::File &filehandle,
const Nexus::Info &nxinfo,
const std::string &property_name,
153 g_log.
warning() <<
"Property " << property_name <<
" was set twice. Please check the Nexus file and your inputs.";
159 if (filehandle.hasAttr(
"units"))
160 filehandle.getAttr(
"units", units);
163 std::vector<NumericType> data_vec;
164 data_vec.reserve(nxinfo.
dims.front());
165 filehandle.getDataCoerce(data_vec);
168 const auto dim1size = data_vec.size();
171 runDetails.
addProperty(property_name, data_vec.front());
173 runDetails.
addProperty(property_name, data_vec.front(), units);
200 const std::string &parent_name,
const std::string &parent_class,
201 int level,
bool useFullAddress) {
202 const std::string SDS(
"SDS");
204 for (
const auto &entry : filehandle.getEntries()) {
205 const auto nxname = entry.first;
206 const auto nxclass = entry.second;
207 if (nxclass == SDS) {
208 if ((parent_class !=
"NXData") && parent_class !=
"NXMonitor" && (nxname !=
"data")) {
209 filehandle.openData(nxname);
210 const auto nxinfo = filehandle.getInfo();
211 const auto rank = nxinfo.
dims.size();
214 bool read_property = (rank == 1);
215 switch (nxinfo.
type) {
221 read_property = (nxinfo.
dims[0] <= 9);
227 read_property = (nxinfo.
dims.front() == 1);
230 read_property =
false;
235 const std::string property_name = (parent_name.empty() ? nxname : parent_name +
"." + nxname);
237 switch (nxinfo.
type) {
239 std::string property_value = filehandle.getStrData();
240 if (property_name.ends_with(
"_time")) {
246 runDetails.
addProperty(property_name, property_value);
249 runDetails.
addProperty(property_name, property_value);
252 <<
" was set twice. Please check the Nexus file and your inputs.\n";
259 addNumericProperty<double>(filehandle, nxinfo, property_name, runDetails);
264 addNumericProperty<int>(filehandle, nxinfo, property_name, runDetails);
267 std::stringstream msg;
268 msg <<
"Encountered unknown type: " << nxinfo.
type;
269 throw std::runtime_error(msg.str());
273 filehandle.closeData();
276 if ((nxclass !=
"ILL_data_scan_vars") && (nxclass !=
"NXill_data_scan_vars")) {
278 filehandle.openGroup(nxname, nxclass);
280 const std::string property_name = (parent_name.empty() ? nxname : parent_name +
"." + nxname);
281 const std::string p_nxname =
282 useFullAddress ? property_name : nxname;
283 const std::string p_nxclass(nxclass);
287 filehandle.closeGroup();
303 namespace bt = boost::posix_time;
307 bt::from_iso_extended_string(dateToParse);
313 const std::locale format = std::locale(std::locale::classic(),
new bt::time_input_facet(
"%d-%b-%y %H:%M:%S"));
316 std::istringstream is(dateToParse);
320 if (pt != bt::ptime()) {
322 std::string s = bt::to_iso_extended_string(pt);
339 throw std::invalid_argument(
"Instrument component " + componentName +
" not found");
341 auto &componentInfo = ws->mutableComponentInfo();
342 const auto componentIndex = componentInfo.indexOf(component->getComponentID());
343 componentInfo.setPosition(componentIndex, newPos);
357 throw std::invalid_argument(
"Instrument component " + componentName +
" not found");
359 auto &componentInfo = ws->mutableComponentInfo();
360 const auto componentIndex = componentInfo.indexOf(component->getComponentID());
361 componentInfo.setRotation(componentIndex, rot);
373 throw std::invalid_argument(
"Instrument component " + componentName +
" not found");
375 V3D pos = component->getPos();
386 const std::string &instrumentPath) {
387 auto loadInst = AlgorithmManager::Instance().create(
"LoadInstrument");
388 loadInst->initialize();
389 loadInst->setChild(
true);
390 loadInst->setPropertyValue(
"InstrumentName", instrumentName);
391 if (!instrumentPath.empty())
392 loadInst->setPropertyValue(
"Filename", instrumentPath);
394 loadInst->setProperty(
"RewriteSpectraMap",
OptionalBool(
true));
413 const std::vector<double> &xAxis, int64_t initialSpectrum,
bool pointData,
414 const std::vector<detid_t> &detectorIDs,
415 const std::set<detid_t> &acceptedDetectorIDs,
416 const std::tuple<short, short, short> &axisOrder) {
418 const bool customDetectorIDs = detectorIDs.
size() != 0;
419 const bool excludeDetectorIDs = acceptedDetectorIDs.size() != 0;
421 std::array dims = {data.
dim0(), data.
dim1(), data.
dim2()};
422 const auto nTubes = dims[std::get<0>(axisOrder)];
423 const auto nPixels = dims[std::get<1>(axisOrder)];
424 const auto nChannels = dims[std::get<2>(axisOrder)];
426 int loadOrder[3] = {0, 1, 2};
429 HistogramData::Points histoPoints;
430 HistogramData::BinEdges binEdges;
432 histoPoints = HistogramData::Points(xAxis);
434 binEdges = HistogramData::BinEdges(xAxis);
437#pragma omp parallel for if (!excludeDetectorIDs && Kernel::threadSafe(*ws))
438 for (
specnum_t tube_no = 0; tube_no < static_cast<specnum_t>(nTubes); ++tube_no) {
439 for (
specnum_t pixel_no = 0; pixel_no < static_cast<specnum_t>(nPixels); ++pixel_no) {
441 static_cast<specnum_t>(initialSpectrum) + tube_no *
static_cast<specnum_t>(nPixels) + pixel_no;
442 if (excludeDetectorIDs != 0 && std::find(acceptedDetectorIDs.cbegin(), acceptedDetectorIDs.cend(),
443 currentSpectrum) == acceptedDetectorIDs.end()) {
447 currentSpectrum -= nSkipped;
449 std::vector<int> spectrum(nChannels);
450 for (
specnum_t channel_no = 0; channel_no < static_cast<specnum_t>(nChannels); ++channel_no) {
451 const int dataIndices[3] = {tube_no, pixel_no, channel_no};
452 spectrum[channel_no] = data(dataIndices[loadOrder[0]], dataIndices[loadOrder[1]], dataIndices[loadOrder[2]]);
454 const HistogramData::Counts counts(spectrum.begin(), spectrum.end());
455 const HistogramData::CountVariances countVariances(spectrum.begin(), spectrum.end());
457 ws->setCounts(currentSpectrum, counts);
458 ws->setCountVariances(currentSpectrum, countVariances);
459 ws->setPoints(currentSpectrum, histoPoints);
461 ws->setHistogram(currentSpectrum, binEdges, counts);
463 const specnum_t detectorID = customDetectorIDs ? detectorIDs[currentSpectrum] : currentSpectrum;
464 ws->getSpectrum(currentSpectrum).setSpectrumNo(detectorID);
475 if (std::get<0>(dataOrder) != 0)
476 dataIndices[0] = std::get<1>(dataOrder) == 0 ? 1 : 2;
477 if (std::get<1>(dataOrder) != 1)
478 dataIndices[1] = std::get<0>(dataOrder) == 1 ? 0 : 2;
479 if (std::get<2>(dataOrder) != 2)
480 dataIndices[2] = std::get<1>(dataOrder) == 2 ? 1 : 0;
496 const std::vector<double> &xAxis, int64_t initialSpectrum,
497 const std::set<detid_t> &acceptedDetectorIDs,
498 const std::vector<detid_t> &customDetectorIDs,
499 const std::tuple<short, short, short> &axisOrder) {
501 const auto useCustomSpectraMap = customDetectorIDs.size() != 0;
502 const auto useAcceptedDetectorIDs = acceptedDetectorIDs.size() != 0;
504 std::array<Nexus::dimsize_t, 3U> dims = {data.
dim0(), data.
dim1(), data.
dim2()};
505 const auto nTubes = dims[std::get<0>(axisOrder)];
506 const auto nPixels = dims[std::get<1>(axisOrder)];
507 const auto nScans = dims[std::get<2>(axisOrder)];
510#pragma omp parallel for if (Kernel::threadSafe(*ws))
511 for (
specnum_t tube_no = 0; tube_no < static_cast<specnum_t>(nTubes); ++tube_no) {
512 for (
specnum_t pixel_no = 0; pixel_no < static_cast<specnum_t>(nPixels); ++pixel_no) {
514 static_cast<specnum_t>(initialSpectrum) + tube_no *
static_cast<specnum_t>(nPixels) + pixel_no;
515 if (useAcceptedDetectorIDs && std::find(acceptedDetectorIDs.cbegin(), acceptedDetectorIDs.cend(),
516 currentDetector) == acceptedDetectorIDs.end()) {
520 currentDetector -= nSkipped;
521 int64_t currentSpectrum;
522 if (useCustomSpectraMap)
523 currentSpectrum = customDetectorIDs[currentDetector - initialSpectrum];
525 currentSpectrum = currentDetector;
526 currentSpectrum *= nScans;
527 for (
specnum_t channel_no = 0; channel_no < static_cast<specnum_t>(nScans); ++channel_no) {
528 auto spectrumValue = data(channel_no, tube_no, pixel_no);
529 ws->mutableY(currentSpectrum) = spectrumValue;
530 ws->mutableE(currentSpectrum) = sqrt(spectrumValue);
531 ws->mutableX(currentSpectrum) = xAxis;
544 for (
size_t spectrum_no = 0; spectrum_no < ws->getNumberHistograms(); ++spectrum_no) {
545 auto &errorAxis = ws->mutableE(spectrum_no);
546 std::transform(errorAxis.begin(), errorAxis.end(), errorAxis.begin(),
547 [zeroCountsError](
const auto &
error) { return error == 0 ? zeroCountsError : error; });
IPeaksWorkspace_sptr workspace
std::map< DeltaEMode::Type, std::string > index
bool hasProperty(const std::string &name) const
Does the property exist on the object.
Kernel::Property * getProperty(const std::string &name) const
Returns the named property as a pointer.
void addProperty(Kernel::Property *prop, bool overwrite=false)
Add data to the object in the form of a property.
This class stores information regarding an experimental run as a series of log entries.
void warning(const std::string &msg)
Logs at warning level.
OptionalBool : Tri-state bool.
virtual std::string setValue(const std::string &)=0
Set the value of the property via a string.
std::size_t size() const noexcept
Number of components in V3D.
float getFloat(const std::string &name) const
Returns a float.
std::string getString(const std::string &name) const
Returns a string.
NXFloat openNXFloat(const std::string &name) const
Creates and opens a float dataset.
std::vector< NXClassInfo > & groups() const
Returns a list of all classes (or groups) in this NXClass.
Templated class implementation of NXDataSet.
void load()
Read all of the datablock in.
dimsize_t dim0() const
Returns the number of elements along the first dimension.
dimsize_t dim2() const
Returns the number of elements along the third dimension.
dimsize_t dim1() const
Returns the number of elements along the second dimension.
NXDouble openDoubleData()
Opens data of double type.
NXInt openIntData()
Opens data of int type.
Implements NXentry Nexus class.
NXData openNXData(const std::string &name) const
Opens a NXData.
static unsigned short constexpr UINT16
static unsigned short constexpr INT16
static unsigned short constexpr CHAR
static unsigned short constexpr INT32
static unsigned short constexpr FLOAT32
static unsigned short constexpr FLOAT64
Kernel::Logger g_log("ExperimentInfo")
static logger object
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::string getStringFromNexusAddress(const Mantid::Nexus::NXEntry &, const std::string &)
void recurseAndAddNexusFieldsToWsRun(Nexus::File &filehandle, API::Run &runDetails, const std::string &parent_name, const std::string &parent_class, int level, bool useFullAddress)
Recursively add properties from a nexus file to the workspace run.
void fillMovingWorkspace(const API::MatrixWorkspace_sptr &, const Mantid::Nexus::NXInt &, const std::vector< double > &xAxis, int64_t initialSpectrum=0, const std::set< detid_t > &acceptedID=std::set< int >(), const std::vector< detid_t > &customID=std::vector< int >(), const std::tuple< short, short, short > &axisOrder=std::tuple< short, short, short >(0, 1, 2))
Fills workspace with histogram data from provided data structure.
double getInstrumentProperty(const API::MatrixWorkspace_sptr &, const std::string &)
void addNexusFieldsToWsRun(Nexus::File &filehandle, API::Run &runDetails, const std::string &entryName="", bool useFullAddress=false)
Add properties from a nexus file to the workspace run.
double calculateEnergy(double)
Calculate Neutron Energy from wavelength: .
void loadingOrder(const std::tuple< short, short, short > &axisOrder, int *dataIndices)
Handles non-standard loading order of the provided data, based on the provided data dimension order.
void rotateComponent(const API::MatrixWorkspace_sptr &ws, const std::string &componentName, const Kernel::Quat &rot)
LoadHelper::rotateComponent.
Nexus::NXInt getIntDataset(const Nexus::NXEntry &, const std::string &)
Fetches NXInt data from the requested group name in the entry provided.
Nexus::NXDouble getDoubleDataset(const Nexus::NXEntry &, const std::string &)
Fetches NXDouble data from the requested group name in the entry provided.
void moveComponent(const API::MatrixWorkspace_sptr &ws, const std::string &componentName, const Kernel::V3D &newPos)
LoadHelper::moveComponent.
double calculateTOF(double, double)
Calculate TOF from distance.
std::vector< double > getTimeBinningFromNexusAddress(const Mantid::Nexus::NXEntry &, const std::string &)
Gets the time binning from a Nexus float array Adds an extra bin at the end.
void fillStaticWorkspace(const API::MatrixWorkspace_sptr &, const Mantid::Nexus::NXInt &, const std::vector< double > &xAxis, int64_t initialSpectrum=0, bool pointData=false, const std::vector< detid_t > &detectorIDs=std::vector< int >(), const std::set< detid_t > &acceptedID=std::set< int >(), const std::tuple< short, short, short > &axisOrder=std::tuple< short, short, short >(0, 1, 2))
Fills workspace with histogram data from provided data structure.
std::string dateTimeInIsoFormat(const std::string &)
Parses the date as formatted at the ILL: 29-Jun-12 11:27:26 and converts it to the ISO format used in...
Kernel::V3D getComponentPosition(const API::MatrixWorkspace_sptr &ws, const std::string &componentName)
LoadHelper::getComponentPosition.
void loadEmptyInstrument(const API::MatrixWorkspace_sptr &ws, const std::string &instrumentName, const std::string &instrumentAddress="")
Loads empty instrument of chosen name into a provided workspace.
double getDoubleFromNexusAddress(const Mantid::Nexus::NXEntry &, const std::string &)
std::string findInstrumentNexusAddress(const Mantid::Nexus::NXEntry &)
Finds the address for the instrument name in the nexus file Usually of the form: entry0/<NXinstrument...
void replaceZeroErrors(const API::MatrixWorkspace_sptr &, double)
Replaces errors of bins with zero counts with provided value.
std::shared_ptr< const IComponent > IComponent_const_sptr
Typdef of a shared pointer to a const IComponent.
static constexpr double NeutronMass
Mass of the neutron in kg.
static constexpr double h
Planck constant in J*s.
static constexpr double meV
1 meV in Joules.
Helper class which provides the Collimation Length for SANS instruments.
int32_t specnum_t
Typedef for a spectrum Number.
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
std::string to_string(const wide_integer< Bits, Signed > &n)
This structure holds the type and dimensions of a primative field/array.
DimVector dims
The dimensions of the file.
NXnumtype type
The primative type for the field.