diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadNexusProcessed.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadNexusProcessed.h index 025f41a0b37d308a43020d7628282e13ded9e667..076d62d044f89941819089354bd2dd064ea1b1d2 100644 --- a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadNexusProcessed.h +++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadNexusProcessed.h @@ -9,7 +9,10 @@ #include "MantidAPI/MatrixWorkspace.h" #include "MantidNexus/NexusClasses.h" -#include <nexus/NeXusFile.hpp> + +namespace NeXus { + class File; +} namespace Mantid { @@ -129,6 +132,13 @@ private: Mantid::NeXus::NXDouble &xbins, const double &progressStart, const double &progressRange); + API::MatrixWorkspace_sptr loadNonEventEntry(Mantid::NeXus::NXData &wksp_cls, + Mantid::NeXus::NXDouble &xbins, + const double &progressStart, + const double &progressRange, + const Mantid::NeXus::NXEntry &mtd_entry, + const int xlength, + std::string &workspaceType); /// Read the data from the sample group void readSampleGroup(Mantid::NeXus::NXEntry &mtd_entry, @@ -182,7 +192,8 @@ private: void checkOptionalProperties(const std::size_t numberofspectra); /// calculates the workspace size - std::size_t calculateWorkspacesize(const std::size_t numberofspectra); + std::size_t calculateWorkspaceSize(const std::size_t numberofspectra, + bool gen_filtered_list=false); /// Accellerated multiperiod loading Mantid::API::Workspace_sptr doAccelleratedMultiPeriodLoading( @@ -201,13 +212,18 @@ private: bool m_list; /// Flag set if interval of spectra to write is set bool m_interval; - /// The value of the spectrum_list property - std::vector<int64_t> m_spec_list; + /// The value of the spectrum_min property int64_t m_spec_min; /// The value of the spectrum_max property int64_t m_spec_max; + /// The value of the spectrum_list property + std::vector<int64_t> m_spec_list; + /// list of spectra filtered by min/max/list, currently + /// used only when loading data into event_workspace + std::vector<int64_t> m_filtered_spec_idxs; + // C++ interface to the NXS file ::NeXus::File *m_cppFile; }; diff --git a/Code/Mantid/Framework/DataHandling/src/LoadNexusProcessed.cpp b/Code/Mantid/Framework/DataHandling/src/LoadNexusProcessed.cpp index e644f6846fa28ecb6de6a4ea5c9f3a1f6e6b2a11..2c6f5e9efd3646f8fe89ffc75cfcc23e527e8590 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadNexusProcessed.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadNexusProcessed.cpp @@ -12,27 +12,25 @@ #include "MantidDataHandling/LoadNexusProcessed.h" #include "MantidDataObjects/EventWorkspace.h" #include "MantidDataObjects/RebinnedOutput.h" +#include "MantidDataObjects/PeaksWorkspace.h" +#include "MantidDataObjects/PeakNoShapeFactory.h" +#include "MantidDataObjects/PeakShapeSphericalFactory.h" #include "MantidKernel/ArrayProperty.h" #include "MantidKernel/ConfigService.h" #include "MantidKernel/DateAndTime.h" #include "MantidKernel/UnitFactory.h" #include "MantidKernel/BoundedValidator.h" +#include "MantidKernel/MultiThreaded.h" #include "MantidNexus/NexusClasses.h" #include "MantidNexus/NexusFileIO.h" -#include <nexus/NeXusFile.hpp> + #include <boost/shared_ptr.hpp> #include <boost/regex.hpp> #include <boost/lexical_cast.hpp> #include <boost/shared_array.hpp> #include <cmath> -#include <Poco/DateTimeParser.h> #include <Poco/Path.h> #include <Poco/StringTokenizer.h> -#include "MantidDataObjects/PeaksWorkspace.h" -#include "MantidKernel/MultiThreaded.h" -#include "MantidDataObjects/PeakNoShapeFactory.h" -#include "MantidDataObjects/PeakShapeSphericalFactory.h" -#include "MantidDataObjects/PeakShape.h" namespace Mantid { namespace DataHandling { @@ -193,8 +191,8 @@ bool isMultiPeriodFile(int nWorkspaceEntries, Workspace_sptr sampleWS, /// Default constructor LoadNexusProcessed::LoadNexusProcessed() : m_shared_bins(false), m_xbins(), m_axis1vals(), m_list(false), - m_interval(false), m_spec_list(), m_spec_min(0), - m_spec_max(Mantid::EMPTY_INT()), m_cppFile(NULL) {} + m_interval(false), m_spec_min(0), m_spec_max(Mantid::EMPTY_INT()), + m_spec_list(), m_filtered_spec_idxs(), m_cppFile(NULL) {} /// Delete NexusFileIO in destructor LoadNexusProcessed::~LoadNexusProcessed() { delete m_cppFile; } @@ -438,7 +436,6 @@ void LoadNexusProcessed::exec() { base_name += "_"; const std::string prop_name = "OutputWorkspace_"; - double nWorkspaceEntries_d = static_cast<double>(nWorkspaceEntries); MatrixWorkspace_sptr tempMatrixWorkspace = boost::dynamic_pointer_cast<Workspace2D>(tempWS); @@ -482,6 +479,8 @@ void LoadNexusProcessed::exec() { p); } else // Fall-back for generic loading { + const double nWorkspaceEntries_d = + static_cast<double>(nWorkspaceEntries); local_workspace = loadEntry(root, basename + os.str(), static_cast<double>(p - 1) / nWorkspaceEntries_d, @@ -625,13 +624,15 @@ LoadNexusProcessed::loadWorkspaceName(NXRoot &root, } //------------------------------------------------------------------------------------------------- -/** Load the event_workspace field +/** + * Load an event_workspace field * - * @param wksp_cls - * @param xbins - * @param progressStart - * @param progressRange - * @return + * @param wksp_cls Nexus data for "event_workspace" + * @param xbins bins on the "X" axis + * @param progressStart algorithm progress (from 0) + * @param progressRange progress made after loading an entry + * + * @return event_workspace object with data */ API::MatrixWorkspace_sptr LoadNexusProcessed::loadEventEntry(NXData &wksp_cls, NXDouble &xbins, @@ -640,8 +641,13 @@ LoadNexusProcessed::loadEventEntry(NXData &wksp_cls, NXDouble &xbins, NXDataSetTyped<int64_t> indices_data = wksp_cls.openNXDataSet<int64_t>("indices"); indices_data.load(); - boost::shared_array<int64_t> indices = indices_data.sharedBuffer(); - int numspec = indices_data.dim0() - 1; + size_t numspec = indices_data.dim0() - 1; + + // process optional spectrum parameters, if set + checkOptionalProperties(numspec); + // Actual number of spectra in output workspace (if only a user-specified + // range and/or list was going to be loaded) + numspec = calculateWorkspaceSize(numspec, true); int num_xbins = xbins.dim0(); if (num_xbins < 2) @@ -699,14 +705,17 @@ LoadNexusProcessed::loadEventEntry(NXData &wksp_cls, NXDouble &xbins, else throw std::runtime_error("Could not figure out the type of event list!"); + // indices of events + boost::shared_array<int64_t> indices = indices_data.sharedBuffer(); // Create all the event lists PARALLEL_FOR_NO_WSP_CHECK() - for (int wi = 0; wi < numspec; wi++) { + for (int64_t j = 0; j < static_cast<int64_t>(m_filtered_spec_idxs.size()); j++) { PARALLEL_START_INTERUPT_REGION + size_t wi = m_filtered_spec_idxs[j] - 1; int64_t index_start = indices[wi]; int64_t index_end = indices[wi + 1]; if (index_end >= index_start) { - EventList &el = ws->getEventList(wi); + EventList &el = ws->getEventList(j); el.switchTo(type); // Allocate all the required memory @@ -735,12 +744,13 @@ LoadNexusProcessed::loadEventEntry(NXData &wksp_cls, NXDouble &xbins, MantidVec x; x.resize(xbins.dim0()); for (int i = 0; i < xbins.dim0(); i++) - x[i] = xbins(wi, i); + x[i] = xbins(static_cast<int>(wi), i); el.setX(x); } } - progress(progressStart + progressRange * (1.0 / numspec)); + progress(progressStart + progressRange * + (1.0 / static_cast<double>(numspec))); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION @@ -1152,7 +1162,205 @@ return boost::static_pointer_cast<API::Workspace>(peakWS); //------------------------------------------------------------------------------------------------- /** - * Load a single entry into a workspace + * Load a Workspace2D + * + * @param wksp_cls Nexus data for "Workspace2D" (or "offsets_workspace") + * @param xbins bins on the "X" axis + * @param progressStart algorithm progress (from 0) + * @param progressRange progress made after loading an entry + * @param mtd_entry Nexus entry for "mantid_workspace_..." + * @param xlength bins in the "X" axis (xbins) + * @param workspaceType Takes values like "Workspace2D", "RebinnedOutput", etc. + * + * @return workspace object containing loaded data + */ +API::MatrixWorkspace_sptr +LoadNexusProcessed::loadNonEventEntry(NXData &wksp_cls, + NXDouble &xbins, + const double &progressStart, + const double &progressRange, + const NXEntry &mtd_entry, + const int xlength, + std::string &workspaceType) { + // Filter the list of spectra to process, applying min/max/list options + NXDataSetTyped<double> data = wksp_cls.openDoubleData(); + int64_t nchannels = data.dim1(); + size_t nspectra = data.dim0(); + // process optional spectrum parameters, if set + checkOptionalProperties(nspectra); + // Actual number of spectra in output workspace (if only a range was going + // to be loaded) + size_t total_specs = calculateWorkspaceSize(nspectra); + + //// Create the 2D workspace for the output + bool hasFracArea = false; + if (wksp_cls.isValid("frac_area")) { + // frac_area entry is the signal for a RebinnedOutput workspace + hasFracArea = true; + workspaceType.clear(); + workspaceType = "RebinnedOutput"; + } + + API::MatrixWorkspace_sptr local_workspace = + boost::dynamic_pointer_cast<API::MatrixWorkspace>( + WorkspaceFactory::Instance().create(workspaceType, total_specs, xlength, + nchannels)); + try { + local_workspace->setTitle(mtd_entry.getString("title")); + } catch (std::runtime_error &) { + g_log.debug() << "No title was found in the input file, " + << getPropertyValue("Filename") << std::endl; + } + + // Set the YUnit label + local_workspace->setYUnit(data.attributes("units")); + std::string unitLabel = data.attributes("unit_label"); + if (unitLabel.empty()) + unitLabel = data.attributes("units"); + local_workspace->setYUnitLabel(unitLabel); + + readBinMasking(wksp_cls, local_workspace); + NXDataSetTyped<double> errors = wksp_cls.openNXDouble("errors"); + NXDataSetTyped<double> fracarea = errors; + if (hasFracArea) { + fracarea = wksp_cls.openNXDouble("frac_area"); + } + + int64_t blocksize(8); + // const int fullblocks = nspectra / blocksize; + // size of the workspace + int64_t fullblocks = total_specs / blocksize; + int64_t read_stop = (fullblocks * blocksize); + const double progressBegin = progressStart + 0.25 * progressRange; + const double progressScaler = 0.75 * progressRange; + int64_t hist_index = 0; + int64_t wsIndex = 0; + if (m_shared_bins) { + // if spectrum min,max,list properties are set + if (m_interval || m_list) { + // if spectrum max,min properties are set read the data as a + // block(multiple of 8) and + // then read the remaining data as finalblock + if (m_interval) { + // specs at the min-max interval + int interval_specs = static_cast<int>(m_spec_max - m_spec_min); + fullblocks = (interval_specs) / blocksize; + read_stop = (fullblocks * blocksize) + m_spec_min - 1; + + if (interval_specs < blocksize) { + blocksize = total_specs; + read_stop = m_spec_max - 1; + } + hist_index = m_spec_min - 1; + + for (; hist_index < read_stop;) { + progress(progressBegin + + progressScaler * static_cast<double>(hist_index) / + static_cast<double>(read_stop), + "Reading workspace data..."); + loadBlock(data, errors, fracarea, hasFracArea, blocksize, nchannels, + hist_index, wsIndex, local_workspace); + } + int64_t finalblock = m_spec_max - 1 - read_stop; + if (finalblock > 0) { + loadBlock(data, errors, fracarea, hasFracArea, finalblock, + nchannels, hist_index, wsIndex, local_workspace); + } + } + // if spectrum list property is set read each spectrum separately by + // setting blocksize=1 + if (m_list) { + std::vector<int64_t>::iterator itr = m_spec_list.begin(); + for (; itr != m_spec_list.end(); ++itr) { + int64_t specIndex = (*itr) - 1; + progress(progressBegin + + progressScaler * static_cast<double>(specIndex) / + static_cast<double>(m_spec_list.size()), + "Reading workspace data..."); + loadBlock(data, errors, fracarea, hasFracArea, + static_cast<int64_t>(1), nchannels, specIndex, wsIndex, + local_workspace); + } + } + } else { + for (; hist_index < read_stop;) { + progress(progressBegin + + progressScaler * static_cast<double>(hist_index) / + static_cast<double>(read_stop), + "Reading workspace data..."); + loadBlock(data, errors, fracarea, hasFracArea, blocksize, nchannels, + hist_index, wsIndex, local_workspace); + } + int64_t finalblock = total_specs - read_stop; + if (finalblock > 0) { + loadBlock(data, errors, fracarea, hasFracArea, finalblock, nchannels, + hist_index, wsIndex, local_workspace); + } + } + + } else { + if (m_interval || m_list) { + if (m_interval) { + int64_t interval_specs = m_spec_max - m_spec_min; + fullblocks = (interval_specs) / blocksize; + read_stop = (fullblocks * blocksize) + m_spec_min - 1; + + if (interval_specs < blocksize) { + blocksize = interval_specs; + read_stop = m_spec_max - 1; + } + hist_index = m_spec_min - 1; + + for (; hist_index < read_stop;) { + progress(progressBegin + + progressScaler * static_cast<double>(hist_index) / + static_cast<double>(read_stop), + "Reading workspace data..."); + loadBlock(data, errors, fracarea, hasFracArea, xbins, blocksize, + nchannels, hist_index, wsIndex, local_workspace); + } + int64_t finalblock = m_spec_max - 1 - read_stop; + if (finalblock > 0) { + loadBlock(data, errors, fracarea, hasFracArea, xbins, finalblock, + nchannels, hist_index, wsIndex, local_workspace); + } + } + // + if (m_list) { + std::vector<int64_t>::iterator itr = m_spec_list.begin(); + for (; itr != m_spec_list.end(); ++itr) { + int64_t specIndex = (*itr) - 1; + progress(progressBegin + + progressScaler * static_cast<double>(specIndex) / + static_cast<double>(read_stop), + "Reading workspace data..."); + loadBlock(data, errors, fracarea, hasFracArea, xbins, 1, nchannels, + specIndex, wsIndex, local_workspace); + } + } + } else { + for (; hist_index < read_stop;) { + progress(progressBegin + + progressScaler * static_cast<double>(hist_index) / + static_cast<double>(read_stop), + "Reading workspace data..."); + loadBlock(data, errors, fracarea, hasFracArea, xbins, blocksize, + nchannels, hist_index, wsIndex, local_workspace); + } + int64_t finalblock = total_specs - read_stop; + if (finalblock > 0) { + loadBlock(data, errors, fracarea, hasFracArea, xbins, finalblock, + nchannels, hist_index, wsIndex, local_workspace); + } + } + } + return local_workspace; +} + +//------------------------------------------------------------------------------------------------- +/** + * Load a single entry into a workspace (event_workspace or workspace2d) + * * @param root :: The opened root node * @param entry_name :: The entry name * @param progressStart :: The percentage value to start the progress reporting @@ -1217,188 +1425,17 @@ API::Workspace_sptr LoadNexusProcessed::loadEntry(NXRoot &root, NXDouble axis2 = wksp_cls.openNXDouble("axis2"); std::string unit2 = axis2.attributes("units"); - // The workspace being worked on + // --- Load workspace (as event_workspace or workspace2d) --- API::MatrixWorkspace_sptr local_workspace; - size_t nspectra; - int64_t nchannels; - - // -------- Process as event ? -------------------- if (isEvent) { local_workspace = loadEventEntry(wksp_cls, xbins, progressStart, progressRange); - nspectra = local_workspace->getNumberHistograms(); - nchannels = local_workspace->blocksize(); } else { - NXDataSetTyped<double> data = wksp_cls.openDoubleData(); - nspectra = data.dim0(); - nchannels = data.dim1(); - //// validate the optional spectrum parameters, if set - checkOptionalProperties(nspectra); - // Actual number of spectra in output workspace (if only a range was going - // to be loaded) - size_t total_specs = calculateWorkspacesize(nspectra); - - //// Create the 2D workspace for the output - bool hasFracArea = false; - if (wksp_cls.isValid("frac_area")) { - // frac_area entry is the signal for a RebinnedOutput workspace - hasFracArea = true; - workspaceType.clear(); - workspaceType = "RebinnedOutput"; - } - local_workspace = boost::dynamic_pointer_cast<API::MatrixWorkspace>( - WorkspaceFactory::Instance().create(workspaceType, total_specs, xlength, - nchannels)); - try { - local_workspace->setTitle(mtd_entry.getString("title")); - } catch (std::runtime_error &) { - g_log.debug() << "No title was found in the input file, " - << getPropertyValue("Filename") << std::endl; - } - - // Set the YUnit label - local_workspace->setYUnit(data.attributes("units")); - std::string unitLabel = data.attributes("unit_label"); - if (unitLabel.empty()) - unitLabel = data.attributes("units"); - local_workspace->setYUnitLabel(unitLabel); - - readBinMasking(wksp_cls, local_workspace); - NXDataSetTyped<double> errors = wksp_cls.openNXDouble("errors"); - NXDataSetTyped<double> fracarea = errors; - if (hasFracArea) { - fracarea = wksp_cls.openNXDouble("frac_area"); - } - - int64_t blocksize(8); - // const int fullblocks = nspectra / blocksize; - // size of the workspace - int64_t fullblocks = total_specs / blocksize; - int64_t read_stop = (fullblocks * blocksize); - const double progressBegin = progressStart + 0.25 * progressRange; - const double progressScaler = 0.75 * progressRange; - int64_t hist_index = 0; - int64_t wsIndex = 0; - if (m_shared_bins) { - // if spectrum min,max,list properties are set - if (m_interval || m_list) { - // if spectrum max,min properties are set read the data as a - // block(multiple of 8) and - // then read the remaining data as finalblock - if (m_interval) { - // specs at the min-max interval - int interval_specs = static_cast<int>(m_spec_max - m_spec_min); - fullblocks = (interval_specs) / blocksize; - read_stop = (fullblocks * blocksize) + m_spec_min - 1; - - if (interval_specs < blocksize) { - blocksize = total_specs; - read_stop = m_spec_max - 1; - } - hist_index = m_spec_min - 1; - - for (; hist_index < read_stop;) { - progress(progressBegin + - progressScaler * static_cast<double>(hist_index) / - static_cast<double>(read_stop), - "Reading workspace data..."); - loadBlock(data, errors, fracarea, hasFracArea, blocksize, nchannels, - hist_index, wsIndex, local_workspace); - } - int64_t finalblock = m_spec_max - 1 - read_stop; - if (finalblock > 0) { - loadBlock(data, errors, fracarea, hasFracArea, finalblock, - nchannels, hist_index, wsIndex, local_workspace); - } - } - // if spectrum list property is set read each spectrum separately by - // setting blocksize=1 - if (m_list) { - std::vector<int64_t>::iterator itr = m_spec_list.begin(); - for (; itr != m_spec_list.end(); ++itr) { - int64_t specIndex = (*itr) - 1; - progress(progressBegin + - progressScaler * static_cast<double>(specIndex) / - static_cast<double>(m_spec_list.size()), - "Reading workspace data..."); - loadBlock(data, errors, fracarea, hasFracArea, - static_cast<int64_t>(1), nchannels, specIndex, wsIndex, - local_workspace); - } - } - } else { - for (; hist_index < read_stop;) { - progress(progressBegin + - progressScaler * static_cast<double>(hist_index) / - static_cast<double>(read_stop), - "Reading workspace data..."); - loadBlock(data, errors, fracarea, hasFracArea, blocksize, nchannels, - hist_index, wsIndex, local_workspace); - } - int64_t finalblock = total_specs - read_stop; - if (finalblock > 0) { - loadBlock(data, errors, fracarea, hasFracArea, finalblock, nchannels, - hist_index, wsIndex, local_workspace); - } - } - - } else { - if (m_interval || m_list) { - if (m_interval) { - int64_t interval_specs = m_spec_max - m_spec_min; - fullblocks = (interval_specs) / blocksize; - read_stop = (fullblocks * blocksize) + m_spec_min - 1; - - if (interval_specs < blocksize) { - blocksize = interval_specs; - read_stop = m_spec_max - 1; - } - hist_index = m_spec_min - 1; - - for (; hist_index < read_stop;) { - progress(progressBegin + - progressScaler * static_cast<double>(hist_index) / - static_cast<double>(read_stop), - "Reading workspace data..."); - loadBlock(data, errors, fracarea, hasFracArea, xbins, blocksize, - nchannels, hist_index, wsIndex, local_workspace); - } - int64_t finalblock = m_spec_max - 1 - read_stop; - if (finalblock > 0) { - loadBlock(data, errors, fracarea, hasFracArea, xbins, finalblock, - nchannels, hist_index, wsIndex, local_workspace); - } - } - // - if (m_list) { - std::vector<int64_t>::iterator itr = m_spec_list.begin(); - for (; itr != m_spec_list.end(); ++itr) { - int64_t specIndex = (*itr) - 1; - progress(progressBegin + - progressScaler * static_cast<double>(specIndex) / - static_cast<double>(read_stop), - "Reading workspace data..."); - loadBlock(data, errors, fracarea, hasFracArea, xbins, 1, nchannels, - specIndex, wsIndex, local_workspace); - } - } - } else { - for (; hist_index < read_stop;) { - progress(progressBegin + - progressScaler * static_cast<double>(hist_index) / - static_cast<double>(read_stop), - "Reading workspace data..."); - loadBlock(data, errors, fracarea, hasFracArea, xbins, blocksize, - nchannels, hist_index, wsIndex, local_workspace); - } - int64_t finalblock = total_specs - read_stop; - if (finalblock > 0) { - loadBlock(data, errors, fracarea, hasFracArea, xbins, finalblock, - nchannels, hist_index, wsIndex, local_workspace); - } - } - } - } // end of NOT an event ------------------------------- + local_workspace = + loadNonEventEntry(wksp_cls, xbins, progressStart, progressRange, + mtd_entry, xlength, workspaceType); + } + size_t nspectra = local_workspace->getNumberHistograms(); // Units bool verticalHistogram(false); @@ -1920,13 +1957,22 @@ LoadNexusProcessed::checkOptionalProperties(const std::size_t numberofspectra) { /** * Calculate the size of a workspace - * @param numberofspectra :: number of spectrums + * + * @param numberofspectra :: count of spectra found in the file being loaded + * + * @param gen_filtered_list :: process SpectrumList and SpectrumMin/Max + * and save resulting explicit list of + * spectra indices into a vector data + * member, presently used only when loading + * into event_workspace + * * @return the size of a workspace */ size_t -LoadNexusProcessed::calculateWorkspacesize(const std::size_t numberofspectra) { +LoadNexusProcessed::calculateWorkspaceSize(const std::size_t numberofspectra, + bool gen_filtered_list) { // Calculate the size of a workspace, given its number of spectra to read - int total_specs; + int64_t total_specs; if (m_interval || m_list) { if (m_interval) { if (m_spec_min != 1 && m_spec_max == 1) { @@ -1934,8 +1980,16 @@ LoadNexusProcessed::calculateWorkspacesize(const std::size_t numberofspectra) { } total_specs = static_cast<int>(m_spec_max - m_spec_min + 1); m_spec_max += 1; - } else + + if (gen_filtered_list) { + m_filtered_spec_idxs.resize(total_specs); + size_t j = 0; + for(int64_t si = m_spec_min; si < m_spec_max; si++, j++) + m_filtered_spec_idxs[j] = si; + } + } else { total_specs = 0; + } if (m_list) { if (m_interval) { @@ -1949,11 +2003,26 @@ LoadNexusProcessed::calculateWorkspacesize(const std::size_t numberofspectra) { if (m_spec_list.size() == 0) m_list = false; total_specs += static_cast<int>(m_spec_list.size()); + + if (gen_filtered_list) { + // range list + spare indices from list + // example: min: 2, max: 8, list: 3,4,5,10,12; + // result: 2,3,...,7,8,10,12 + m_filtered_spec_idxs.insert(m_filtered_spec_idxs.end(), + m_spec_list.begin(), + m_spec_list.end()); + } } } else { total_specs = static_cast<int>(numberofspectra); m_spec_min = 1; m_spec_max = static_cast<int>(numberofspectra) + 1; + + if (gen_filtered_list) { + m_filtered_spec_idxs.resize(total_specs, 0); + for(int64_t j = 0; j < total_specs; j++) + m_filtered_spec_idxs[j] = m_spec_min+j; + } } return total_specs; } diff --git a/Code/Mantid/Framework/DataHandling/test/LoadNexusProcessedTest.h b/Code/Mantid/Framework/DataHandling/test/LoadNexusProcessedTest.h index 50dd783802ae37b042c8269615f00c495952b358..0f5665b673813c0435671360a77bbb627e4b3591 100644 --- a/Code/Mantid/Framework/DataHandling/test/LoadNexusProcessedTest.h +++ b/Code/Mantid/Framework/DataHandling/test/LoadNexusProcessedTest.h @@ -46,15 +46,16 @@ public: delete suite; } - LoadNexusProcessedTest() : - testFile("GEM38370_Focussed_Legacy.nxs"), output_ws("nxstest") + LoadNexusProcessedTest(): + testFile("GEM38370_Focussed_Legacy.nxs"), output_ws("nxstest"), + m_savedTmpEventFile("") { - } ~LoadNexusProcessedTest() { AnalysisDataService::Instance().clear(); + clearTmpEventNexus(); } void testFastMultiPeriodDefault() @@ -407,6 +408,148 @@ public: dotest_LoadAnEventFile(WEIGHTED_NOTIME); } + void test_loadEventNexus_Min() + { + writeTmpEventNexus(); + + LoadNexusProcessed alg; + TS_ASSERT_THROWS_NOTHING(alg.initialize()); + TS_ASSERT( alg.isInitialized()); + + alg.setPropertyValue("Filename", m_savedTmpEventFile); + alg.setPropertyValue("OutputWorkspace", output_ws); + alg.setPropertyValue("SpectrumMin", "3"); + // this should imply 4==ws->getNumberHistograms() + + // expected number of spectra and length of the alg history + doCommonEventLoadChecks(alg, 4, 2); + } + + void test_loadEventNexus_Max() + { + writeTmpEventNexus(); + + LoadNexusProcessed alg; + TS_ASSERT_THROWS_NOTHING(alg.initialize()); + TS_ASSERT( alg.isInitialized()); + + alg.setPropertyValue("Filename", m_savedTmpEventFile); + alg.setPropertyValue("OutputWorkspace", output_ws); + alg.setPropertyValue("SpectrumMax", "2"); + // this should imply 3==ws->getNumberHistograms() + + // expected number of spectra and length of the alg history + doCommonEventLoadChecks(alg, 2, 2); + } + + void test_loadEventNexus_Min_Max() + { + writeTmpEventNexus(); + + LoadNexusProcessed alg; + TS_ASSERT_THROWS_NOTHING(alg.initialize()); + TS_ASSERT( alg.isInitialized()); + + alg.setPropertyValue("Filename", m_savedTmpEventFile); + alg.setPropertyValue("OutputWorkspace", output_ws); + alg.setPropertyValue("SpectrumMin", "2"); + alg.setPropertyValue("SpectrumMax", "4"); + // this should imply 3==ws->getNumberHistograms() + + // expected number of spectra and length of the alg history + // in history, expect: load + LoadInst (child) + doCommonEventLoadChecks(alg, 3, 2); + } + + void test_loadEventNexus_Fail() + { + writeTmpEventNexus(); + + LoadNexusProcessed alg; + TS_ASSERT_THROWS_NOTHING(alg.initialize()); + TS_ASSERT( alg.isInitialized()); + + alg.setPropertyValue("Filename", m_savedTmpEventFile); + alg.setPropertyValue("OutputWorkspace", output_ws); + alg.setPropertyValue("SpectrumList", "1,3,5,89"); + // the 89 should cause trouble, but gracefully... + + TS_ASSERT_THROWS_NOTHING(alg.execute()); + TS_ASSERT(!alg.isExecuted()); + } + + void test_loadEventNexus_List() + { + writeTmpEventNexus(); + + LoadNexusProcessed alg; + TS_ASSERT_THROWS_NOTHING(alg.initialize()); + TS_ASSERT( alg.isInitialized()); + + alg.setPropertyValue("Filename", m_savedTmpEventFile); + alg.setPropertyValue("OutputWorkspace", output_ws); + alg.setPropertyValue("SpectrumList", "1,3,5"); + // this should imply 3==ws->getNumberHistograms() + + // expected number of spectra and length of the alg history + doCommonEventLoadChecks(alg, 3, 2); + } + + void test_loadEventNexus_Min_List() + { + writeTmpEventNexus(); + + LoadNexusProcessed alg; + TS_ASSERT_THROWS_NOTHING(alg.initialize()); + TS_ASSERT( alg.isInitialized()); + + alg.setPropertyValue("Filename", m_savedTmpEventFile); + alg.setPropertyValue("OutputWorkspace", output_ws); + alg.setPropertyValue("SpectrumList", "5"); + alg.setPropertyValue("SpectrumMin", "4"); + // this should imply 2==ws->getNumberHistograms() + + // expected number of spectra and length of the alg history + doCommonEventLoadChecks(alg, 3, 2); + } + + void test_loadEventNexus_Max_List() + { + writeTmpEventNexus(); + + LoadNexusProcessed alg; + TS_ASSERT_THROWS_NOTHING(alg.initialize()); + TS_ASSERT( alg.isInitialized()); + + alg.setPropertyValue("Filename", m_savedTmpEventFile); + alg.setPropertyValue("OutputWorkspace", output_ws); + alg.setPropertyValue("SpectrumMax", "2"); + alg.setPropertyValue("SpectrumList", "3,5"); + // this should imply 4==ws->getNumberHistograms() + + // expected number of spectra and length of the alg history + doCommonEventLoadChecks(alg, 4, 2); + } + + void test_loadEventNexus_Min_Max_List() + { + writeTmpEventNexus(); + + LoadNexusProcessed alg; + TS_ASSERT_THROWS_NOTHING(alg.initialize()); + TS_ASSERT( alg.isInitialized()); + + alg.setPropertyValue("Filename", m_savedTmpEventFile); + alg.setPropertyValue("OutputWorkspace", output_ws); + alg.setPropertyValue("SpectrumMin", "3"); + alg.setPropertyValue("SpectrumMax", "5"); + alg.setPropertyValue("SpectrumList", "1,2,3,5"); + // this should imply 5(all)==ws->getNumberHistograms() + + // expected number of spectra and length of the alg history + doCommonEventLoadChecks(alg, 5, 2); + } + void test_load_saved_workspace_group() { LoadNexusProcessed alg; @@ -705,8 +848,9 @@ public: saveAlg.initialize(); saveAlg.setPropertyValue("InputWorkspace", inTableEntry.name()); saveAlg.setPropertyValue("Filename", savedFileName); - TS_ASSERT_THROWS_NOTHING( saveAlg.execute()); - TS_ASSERT( saveAlg.isExecuted()); + + TS_ASSERT_THROWS_NOTHING(saveAlg.execute()); + TS_ASSERT(saveAlg.isExecuted()); if (!saveAlg.isExecuted()) return; // Nothing to check @@ -810,6 +954,7 @@ public: } private: + void doHistoryTest(MatrixWorkspace_sptr matrix_ws) { const WorkspaceHistory history = matrix_ws->getHistory(); @@ -825,8 +970,87 @@ private: } } - LoadNexusProcessed algToBeTested; + /** + * Do a few standard checks that are repeated in multiple tests of + * partial event data loading + * + * @param alg initialized and parameterized load algorithm + * @param nSpectra expected number of spectra + * @param nHistory expected number of entries in the algorithm + * history + **/ + void doCommonEventLoadChecks(LoadNexusProcessed& alg, size_t nSpectra, + size_t nHistory) + { + TS_ASSERT_THROWS_NOTHING(alg.execute()); + TS_ASSERT( alg.isExecuted()); + + // Test basic props of the ws + Workspace_sptr workspace; + TS_ASSERT_THROWS_NOTHING(workspace = AnalysisDataService::Instance().retrieve(output_ws)); + TS_ASSERT(workspace); + if (!workspace) + return; + TS_ASSERT(workspace.get()); + + EventWorkspace_sptr ews = boost::dynamic_pointer_cast<EventWorkspace>(workspace); + TS_ASSERT(ews); + if (!ews) + return; + TS_ASSERT(ews.get()); + TS_ASSERT_EQUALS(ews->getNumberHistograms(), nSpectra); + + TS_ASSERT_EQUALS(ews->getHistory().size(), nHistory); + } + + void writeTmpEventNexus() + { + //return; + if (!m_savedTmpEventFile.empty() && Poco::File(m_savedTmpEventFile).exists()) + return; + + std::vector< std::vector<int> > groups(6); + groups[0].push_back(9); + groups[0].push_back(12); + groups[1].push_back(5); + groups[1].push_back(10); + groups[2].push_back(20); + groups[2].push_back(21); + groups[3].push_back(10); + groups[4].push_back(50); + groups[5].push_back(15); + groups[5].push_back(20); + + EventWorkspace_sptr ws = WorkspaceCreationHelper::CreateGroupedEventWorkspace(groups, 30, 1.0); + ws->getEventList(4).clear(); + + TS_ASSERT_EQUALS( ws->getNumberHistograms(), groups.size()); + + SaveNexusProcessed alg; + alg.initialize(); + alg.setProperty("InputWorkspace", boost::dynamic_pointer_cast<Workspace>(ws)); + m_savedTmpEventFile = "LoadNexusProcessed_TmpEvent.nxs"; + alg.setPropertyValue("Filename", m_savedTmpEventFile); + alg.setPropertyValue("Title", "Tmp test event workspace as NexusProcessed file"); + + TS_ASSERT_THROWS_NOTHING(alg.execute()); + TS_ASSERT( alg.isExecuted() ); + + // Get absolute path to the saved file + m_savedTmpEventFile = alg.getPropertyValue("Filename"); + } + + void clearTmpEventNexus() + { + // remove saved/re-loaded test event data file + if (!m_savedTmpEventFile.empty() && Poco::File(m_savedTmpEventFile).exists()) + Poco::File(m_savedTmpEventFile).remove(); + } + std::string testFile, output_ws; + /// Saved using SaveNexusProcessed and re-used in several load event tests + std::string m_savedTmpEventFile; + static const EventType m_savedTmpType = TOF; }; //------------------------------------------------------------------------------ diff --git a/Code/Mantid/Framework/DataHandling/test/LoadRawSaveNxsLoadNxsTest.h b/Code/Mantid/Framework/DataHandling/test/LoadRawSaveNxsLoadNxsTest.h index 18e325acb1fe13c11fcd4347a5cbc561171663f2..aa87b5eaf66db16707a9d9d64515b792e64be5d3 100644 --- a/Code/Mantid/Framework/DataHandling/test/LoadRawSaveNxsLoadNxsTest.h +++ b/Code/Mantid/Framework/DataHandling/test/LoadRawSaveNxsLoadNxsTest.h @@ -171,7 +171,6 @@ void testExecOnLoadraw() // obtain the expected log data which was read from the Nexus file (NXlog) - Property *l_property =output->run().getLogData( std::string("height") ); TimeSeriesProperty<double> *l_timeSeriesDouble1 = dynamic_cast<TimeSeriesProperty<double>*>(l_property); std::string timeSeriesString = l_timeSeriesDouble1->value(); @@ -185,22 +184,20 @@ void testExecOnLoadraw() TimeSeriesProperty<std::string> *l_timeSeriesString = dynamic_cast<TimeSeriesProperty<std::string>*>(l_property); timeSeriesString = l_timeSeriesString->value(); -// TODO: Re-enable this particular test. -// // -// // Testing log data - this was failing at one time as internal format of log data changed, but now OK again -// // -// std::cout << timeSeriesString; -// TS_ASSERT_EQUALS( timeSeriesString.substr(0,38), "2008-Jun-17 11:11:13 CHANGE PERIOD 12" ); + // + // Testing log data - this was failing at one time as internal format of log data changed, but now OK again + // It was disabled, with a TODO comment, with this string: "2008-Jun-17 11:11:13 CHANGE PERIOD 12", + // now enabled after changing 12=> 1 (and added one more space character before CHANGE). + std::cout << timeSeriesString; + TS_ASSERT_EQUALS( timeSeriesString.substr(0,38), "2008-Jun-17 11:11:13 CHANGE PERIOD 1" ); remove(outputFile.c_str()); - } private: LoadNexus algToBeTested; - LoadNexus algToBeTested2; std::string inputFile; int entryNumber; diff --git a/Code/Mantid/docs/source/algorithms/LoadNexusProcessed-v1.rst b/Code/Mantid/docs/source/algorithms/LoadNexusProcessed-v1.rst index 1e91ff3dd06bb681defc2b3269918c00fd1e47c5..0fa41c95b394d415ccb107d6ba6f5e142d287cab 100644 --- a/Code/Mantid/docs/source/algorithms/LoadNexusProcessed-v1.rst +++ b/Code/Mantid/docs/source/algorithms/LoadNexusProcessed-v1.rst @@ -9,14 +9,19 @@ Description ----------- -The algorithm LoadNexusProcessed will read a Nexus data file created by -:ref:`algm-SaveNexusProcessed` and place the data into the -named workspace. The file name can be an absolute or relative path and -should have the extension .nxs, .nx5 or .xml. Warning - using XML format -can be extremely slow for large data sets and generate very large files. -The optional parameters can be used to control which spectra are loaded -into the workspace (not yet implemented). If spectrum\_min and -spectrum\_max are given, then only that range to data will be loaded. +The algorithm LoadNexusProcessed will read a Nexus data file created +by :ref:`algm-SaveNexusProcessed` and place the data into the named +workspace. The file name can be an absolute or relative path and +should have the extension .nxs, .nx5 or .xml. Warning - using XML +format can be extremely slow for large data sets and generate very +large files. + +The optional parameters can be used to control which spectra are +loaded into the workspace. If SpectrumMin and SpectrumMax are given, +then only that range to data will be loaded. A specific list of +spectra to load can also be given (SpectrumList). Filtering of spectra +is supported when loading into workspaces of type :ref:`Workspace2Ds +<Workspace2D>` and also :ref:`EventWorkspaces <EventWorkspace>`. A Mantid Nexus file may contain several workspace entries each labelled with an integer starting at 1. By default the highest number workspace