From fdf6281af77bfb069315c3fae6937bad26e09bab Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Thu, 23 Oct 2014 12:07:32 +0100 Subject: [PATCH] refs #10385. Naming issue root problem. There is a naming issue here, which is actually the root cause of the problem! The query that was being performed retrieved the number of workspace entries, NOT the number of periods. Going forward. If the number of periods exactly matches the number of workspace entries, we have a multiperiod group workspace, and can happily apply the optimisations we want. Next step will be to actually extract the nperiods. To do that we need to try to fetch it out of the logs for The first entry. --- .../DataHandling/src/LoadNexusProcessed.cpp | 2876 +++++++++-------- 1 file changed, 1448 insertions(+), 1428 deletions(-) diff --git a/Code/Mantid/Framework/DataHandling/src/LoadNexusProcessed.cpp b/Code/Mantid/Framework/DataHandling/src/LoadNexusProcessed.cpp index 8348e1355417..4a989069f719 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadNexusProcessed.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadNexusProcessed.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -31,1737 +32,1756 @@ namespace Mantid { -namespace DataHandling -{ + namespace DataHandling + { // Register the algorithm into the algorithm factory -DECLARE_NEXUS_FILELOADER_ALGORITHM(LoadNexusProcessed); - -using namespace Mantid::NeXus; -using namespace DataObjects; -using namespace Kernel; -using namespace API; -using Geometry::Instrument_const_sptr; - -/// 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) -{ -} - -/// Delete NexusFileIO in destructor -LoadNexusProcessed::~LoadNexusProcessed() -{ - delete m_cppFile; -} - -/** - * Return the confidence with with this algorithm can load the file - * @param descriptor A descriptor for the file - * @returns An integer specifying the confidence level. 0 indicates it will not be used - */ -int LoadNexusProcessed::confidence(Kernel::NexusDescriptor & descriptor) const -{ - if(descriptor.pathExists("/mantid_workspace_1")) return 80; - else return 0; -} - -/** Initialisation method. - * - */ -void LoadNexusProcessed::init() -{ - // Declare required input parameters for algorithm - std::vector exts; - exts.push_back(".nxs"); - exts.push_back(".nx5"); - exts.push_back(".xml"); - declareProperty(new FileProperty("Filename", "", FileProperty::Load, exts), - "The name of the Nexus file to read, as a full or relative path." ); - declareProperty(new WorkspaceProperty ("OutputWorkspace", "", - Direction::Output), - "The name of the workspace to be created as the output of the algorithm. A workspace of this name will be created and stored in the Analysis Data Service. For multiperiod files, one workspace may be generated for each period. Currently only one workspace can be saved at a time so multiperiod Mantid files are not generated."); - - - - // optional - auto mustBePositive = boost::make_shared >(); - mustBePositive->setLower(0); - - declareProperty("SpectrumMin", (int64_t)1, mustBePositive, - "Number of first spectrum to read."); - declareProperty("SpectrumMax", (int64_t)Mantid::EMPTY_INT(), mustBePositive, - "Number of last spectrum to read."); - declareProperty(new ArrayProperty ("SpectrumList"), - "List of spectrum numbers to read."); - declareProperty("EntryNumber", (int64_t)0, mustBePositive, - "The particular entry number to read. Default load all workspaces and creates a workspacegroup (default: read all entries)." ); - declareProperty("LoadHistory", true, "If true, the workspace history will be loaded"); -} + DECLARE_NEXUS_FILELOADER_ALGORITHM(LoadNexusProcessed); + using namespace Mantid::NeXus; + using namespace DataObjects; + using namespace Kernel; + using namespace API; + using Geometry::Instrument_const_sptr; -//------------------------------------------------------------------------------------------------- -/** Executes the algorithm. Reading in the file and creating and populating - * the output workspace - * - * @throw runtime_error Thrown if algorithm cannot execute - */ -void LoadNexusProcessed::exec() -{ - progress(0,"Opening file..."); + namespace + { + // Helper typedef + typedef boost::shared_array IntArray_shared; - //Throws an approriate exception if there is a problem with file access - NXRoot root(getPropertyValue("Filename")); + // Struct to contain spectrum information. + struct SpectraInfo + { + // Number of spectra + const int nSpectra; + // Do we have any spectra + const bool hasSpectra; + // Contains spectrum numbers for each workspace index + const IntArray_shared spectraNumbers; + // Index of the detector in the workspace. + const IntArray_shared detectorIndex; + // Number of detectors associated with each spectra + const IntArray_shared detectorCount; + // Detector list contains a list of all of the detector numbers + const IntArray_shared detectorList; + + SpectraInfo() : + nSpectra(0), hasSpectra(false) + { + } - // "Open" the same file but with the C++ interface - m_cppFile = new ::NeXus::File(root.m_fileID); + SpectraInfo(int _nSpectra, bool _hasSpectra, IntArray_shared _spectraNumbers, + IntArray_shared _detectorIndex, IntArray_shared _detectorCount, IntArray_shared _detectorList) : + nSpectra(_nSpectra), hasSpectra(_hasSpectra), spectraNumbers(_spectraNumbers), detectorIndex( + _detectorIndex), detectorCount(_detectorCount), detectorList(_detectorList) + { + } + }; + // Helper typdef. + typedef boost::optional SpectraInfo_optional; + + /** + * Extract ALL the detector, spectrum number and workspace index mapping information. + * @param mtd_entry + * @param logger + * @return + */ + SpectraInfo extractMappingInfo(NXEntry & mtd_entry, Logger& logger) + { + //Instrument information + NXInstrument inst = mtd_entry.openNXInstrument("instrument"); + if (!inst.containsGroup("detector")) + { + logger.information() + << "Detector block not found. The workspace will not contain any detector information.\n"; + return SpectraInfo(); + } - //Find out how many first level entries there are - int64_t nperiods = static_cast(root.groups().size()); + //Populate the spectra-detector map + NXDetector detgroup = inst.openNXDetector("detector"); - // Check for an entry number property - int64_t entrynumber = static_cast(getProperty("EntryNumber")); + //Read necessary arrays from the file + // Detector list contains a list of all of the detector numbers. If it not present then we can't update the spectra + // map + boost::shared_array detectorList; + try + { + NXInt detlist_group = detgroup.openNXInt("detector_list"); + detlist_group.load(); + detectorList = detlist_group.sharedBuffer(); + } catch (std::runtime_error &) + { + logger.information() + << "detector_list block not found. The workspace will not contain any detector information." + << std::endl; + return SpectraInfo(); + } - if( entrynumber > 0 && entrynumber > nperiods ) - { - g_log.error() << "Invalid entry number specified. File only contains " << nperiods << " entries.\n"; - throw std::invalid_argument("Invalid entry number specified."); - } + //Detector count contains the number of detectors associated with each spectra + NXInt det_count = detgroup.openNXInt("detector_count"); + det_count.load(); + boost::shared_array detectorCount = det_count.sharedBuffer(); + //Detector index - contains the index of the detector in the workspace + NXInt det_index = detgroup.openNXInt("detector_index"); + det_index.load(); + int nspectra = det_index.dim0(); + boost::shared_array detectorIndex = det_index.sharedBuffer(); + + //Spectra block - Contains spectrum numbers for each workspace index + // This might not exist so wrap and check. If it doesn't exist create a default mapping + bool have_spectra(true); + boost::shared_array spectra; + try + { + NXInt spectra_block = detgroup.openNXInt("spectra"); + spectra_block.load(); + spectra = spectra_block.sharedBuffer(); + } catch (std::runtime_error &) + { + have_spectra = false; + } + return SpectraInfo(nspectra, have_spectra, spectra, detectorIndex, detectorCount, detectorList); - const std::string basename = "mantid_workspace_"; - if( nperiods == 1 || entrynumber > 0 ) - { // Load one first level entry, specified if there are several - if( entrynumber == 0 ) ++entrynumber; - std::ostringstream os; - os << entrynumber; - API::Workspace_sptr workspace = loadEntry(root, basename + os.str(), 0, 1); - //API::Workspace_sptr workspace = boost::static_pointer_cast(local_workspace); - setProperty("OutputWorkspace", workspace); - } - else - { // Load all first level entries - WorkspaceGroup_sptr wksp_group(new WorkspaceGroup); - //This forms the name of the group - std::string base_name = getPropertyValue("OutputWorkspace"); - // First member of group should be the group itself, for some reason! - - //load names of each of the workspaces and check for a common stem - std::vector names(nperiods+1); - bool commonStem = checkForCommonNameStem(root, names); - - //remove existing workspace and replace with the one being loaded - bool wsExists = AnalysisDataService::Instance().doesExist(base_name); - if(wsExists) - { - Algorithm_sptr alg = AlgorithmManager::Instance().createUnmanaged("DeleteWorkspace"); - alg->initialize(); - alg->setChild(true); - alg->setProperty("Workspace", base_name); - alg->execute(); + } } - base_name += "_"; - const std::string prop_name = "OutputWorkspace_"; - double nperiods_d = static_cast(nperiods); - for( int64_t p = 1; p <= nperiods; ++p ) +/// 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) { - std::ostringstream os; - os << p; - - //decide what the workspace should be called - std::string wsName = buildWorkspaceName(names[p], base_name, p, commonStem); - - Workspace_sptr local_workspace = loadEntry(root, basename + os.str(), static_cast(p-1)/nperiods_d, 1./nperiods_d); - declareProperty(new WorkspaceProperty(prop_name + os.str(), wsName, - Direction::Output)); - //wksp_group->add(base_name + os.str()); - wksp_group->addWorkspace(local_workspace); - setProperty(prop_name + os.str(), local_workspace); } - // The group is the root property value - setProperty("OutputWorkspace", boost::static_pointer_cast(wksp_group)); - - } - - m_axis1vals.clear(); -} - - -/** - * Decides what to call a child of a group workspace. - * - * This function uses information about if the child workspace has a common stem - * and checks if the file contained a workspace name to decide what it should be called - * - * @param name :: The name loaded from the file (possibly the empty string if none was loaded) - * @param baseName :: The name group workspace - * @param wsIndex :: The current index of this workspace - * @param commonStem :: Whether the workspaces share a common name stem - * - * @return The name of the workspace - */ -std::string LoadNexusProcessed::buildWorkspaceName(const std::string& name, const std::string& baseName, int64_t wsIndex, bool commonStem) -{ - std::string wsName; - std::string index = boost::lexical_cast(wsIndex); - - //if we don't have a common stem then use name tag - if(!commonStem) - { - if(!name.empty()) +/// Delete NexusFileIO in destructor + LoadNexusProcessed::~LoadNexusProcessed() { - //use name loaded from file there's no common stem - wsName = name; + delete m_cppFile; } - else + + /** + * Return the confidence with with this algorithm can load the file + * @param descriptor A descriptor for the file + * @returns An integer specifying the confidence level. 0 indicates it will not be used + */ + int LoadNexusProcessed::confidence(Kernel::NexusDescriptor & descriptor) const { - //if the name property wasn't defined just use _n - wsName = baseName + index; + if (descriptor.pathExists("/mantid_workspace_1")) + return 80; + else + return 0; } - } - else - { - //we have a common stem so rename accordingly - boost::smatch results; - const boost::regex exp(".*_(\\d+$)"); - //if we have a common name stem then name is _n - if(boost::regex_search(name, results, exp)) + + /** Initialisation method. + * + */ + void LoadNexusProcessed::init() { - wsName = baseName + std::string(results[1].first, results[1].second); + // Declare required input parameters for algorithm + std::vector exts; + exts.push_back(".nxs"); + exts.push_back(".nx5"); + exts.push_back(".xml"); + declareProperty(new FileProperty("Filename", "", FileProperty::Load, exts), + "The name of the Nexus file to read, as a full or relative path."); + declareProperty(new WorkspaceProperty("OutputWorkspace", "", Direction::Output), + "The name of the workspace to be created as the output of the algorithm. A workspace of this name will be created and stored in the Analysis Data Service. For multiperiod files, one workspace may be generated for each period. Currently only one workspace can be saved at a time so multiperiod Mantid files are not generated."); + + // optional + auto mustBePositive = boost::make_shared >(); + mustBePositive->setLower(0); + + declareProperty("SpectrumMin", (int64_t) 1, mustBePositive, "Number of first spectrum to read."); + declareProperty("SpectrumMax", (int64_t) Mantid::EMPTY_INT(), mustBePositive, + "Number of last spectrum to read."); + declareProperty(new ArrayProperty("SpectrumList"), "List of spectrum numbers to read."); + declareProperty("EntryNumber", (int64_t) 0, mustBePositive, + "The particular entry number to read. Default load all workspaces and creates a workspacegroup (default: read all entries)."); + declareProperty("LoadHistory", true, "If true, the workspace history will be loaded"); } - else + +//------------------------------------------------------------------------------------------------- + /** Executes the algorithm. Reading in the file and creating and populating + * the output workspace + * + * @throw runtime_error Thrown if algorithm cannot execute + */ + void LoadNexusProcessed::exec() { - //use default name if we couldn't match for some reason - wsName = baseName + index; - } - } + progress(0, "Opening file..."); - correctForWorkspaceNameClash(wsName); + //Throws an approriate exception if there is a problem with file access + NXRoot root(getPropertyValue("Filename")); - return wsName; -} + // "Open" the same file but with the C++ interface + m_cppFile = new ::NeXus::File(root.m_fileID); -/** - * Append an index to the name if it already exists in the AnalysisDataService - * - * @param wsName :: Name to call the workspace - */ -void LoadNexusProcessed::correctForWorkspaceNameClash(std::string& wsName) -{ - bool noClash(false); + //Find out how many first level entries there are + int64_t nWorkspaceEntries = static_cast(root.groups().size()); - for (int i =0; !noClash; ++i ) - { - std::string wsIndex = ""; //dont use an index if there is no other workspace - if(i > 0) - { - wsIndex = "_" + boost::lexical_cast(i); + // Check for an entry number property + int64_t entrynumber = static_cast(getProperty("EntryNumber")); + + if (entrynumber > 0 && entrynumber > nWorkspaceEntries) + { + g_log.error() << "Invalid entry number specified. File only contains " << nWorkspaceEntries + << " entries.\n"; + throw std::invalid_argument("Invalid entry number specified."); + } + + const std::string basename = "mantid_workspace_"; + if (nWorkspaceEntries == 1 || entrynumber > 0) + { // Load one first level entry, specified if there are several + if (entrynumber == 0) + ++entrynumber; + std::ostringstream os; + os << entrynumber; + API::Workspace_sptr workspace = loadEntry(root, basename + os.str(), 0, 1); + //API::Workspace_sptr workspace = boost::static_pointer_cast(local_workspace); + setProperty("OutputWorkspace", workspace); + } + else + { // Load all first level entries + WorkspaceGroup_sptr wksp_group(new WorkspaceGroup); + //This forms the name of the group + std::string base_name = getPropertyValue("OutputWorkspace"); + // First member of group should be the group itself, for some reason! + + //load names of each of the workspaces and check for a common stem + std::vector names(nWorkspaceEntries + 1); + bool commonStem = checkForCommonNameStem(root, names); + + //remove existing workspace and replace with the one being loaded + bool wsExists = AnalysisDataService::Instance().doesExist(base_name); + if (wsExists) + { + Algorithm_sptr alg = AlgorithmManager::Instance().createUnmanaged("DeleteWorkspace"); + alg->initialize(); + alg->setChild(true); + alg->setProperty("Workspace", base_name); + alg->execute(); + } + + base_name += "_"; + const std::string prop_name = "OutputWorkspace_"; + double nWorkspaceEntries_d = static_cast(nWorkspaceEntries); + for (int64_t p = 1; p <= nWorkspaceEntries; ++p) + { + std::ostringstream os; + os << p; + + //decide what the workspace should be called + std::string wsName = buildWorkspaceName(names[p], base_name, p, commonStem); + + Workspace_sptr local_workspace = loadEntry(root, basename + os.str(), + static_cast(p - 1) / nWorkspaceEntries_d, 1. / nWorkspaceEntries_d); + declareProperty( + new WorkspaceProperty(prop_name + os.str(), wsName, Direction::Output)); + //wksp_group->add(base_name + os.str()); + wksp_group->addWorkspace(local_workspace); + setProperty(prop_name + os.str(), local_workspace); + } + + // The group is the root property value + setProperty("OutputWorkspace", boost::static_pointer_cast(wksp_group)); + + } + + m_axis1vals.clear(); } - bool wsExists = AnalysisDataService::Instance().doesExist(wsName+wsIndex); - if(!wsExists) + /** + * Decides what to call a child of a group workspace. + * + * This function uses information about if the child workspace has a common stem + * and checks if the file contained a workspace name to decide what it should be called + * + * @param name :: The name loaded from the file (possibly the empty string if none was loaded) + * @param baseName :: The name group workspace + * @param wsIndex :: The current index of this workspace + * @param commonStem :: Whether the workspaces share a common name stem + * + * @return The name of the workspace + */ + std::string LoadNexusProcessed::buildWorkspaceName(const std::string& name, + const std::string& baseName, int64_t wsIndex, bool commonStem) { - wsName += wsIndex; - noClash = true; - } - } -} - -/** - * Check if the workspace name contains a common stem and load the workspace names - * - * @param root :: the root for the NeXus document - * @param names :: vector to store the names to be loaded. - * @return Whether there was a common stem. - */ -bool LoadNexusProcessed::checkForCommonNameStem(NXRoot & root, std::vector& names) -{ - bool success(true); - int64_t nperiods = static_cast(root.groups().size()); - for( int64_t p = 1; p <= nperiods; ++p ) - { - std::ostringstream os; - os << p; + std::string wsName; + std::string index = boost::lexical_cast(wsIndex); - names[p] = loadWorkspaceName(root, "mantid_workspace_" + os.str()); + //if we don't have a common stem then use name tag + if (!commonStem) + { + if (!name.empty()) + { + //use name loaded from file there's no common stem + wsName = name; + } + else + { + //if the name property wasn't defined just use _n + wsName = baseName + index; + } + } + else + { + //we have a common stem so rename accordingly + boost::smatch results; + const boost::regex exp(".*_(\\d+$)"); + //if we have a common name stem then name is _n + if (boost::regex_search(name, results, exp)) + { + wsName = baseName + std::string(results[1].first, results[1].second); + } + else + { + //use default name if we couldn't match for some reason + wsName = baseName + index; + } + } - boost::smatch results; - const boost::regex exp(".*_\\d+$"); + correctForWorkspaceNameClash(wsName); - //check if the workspace name has an index on the end - if (!boost::regex_match(names[p], results, exp)) + return wsName; + } + + /** + * Append an index to the name if it already exists in the AnalysisDataService + * + * @param wsName :: Name to call the workspace + */ + void LoadNexusProcessed::correctForWorkspaceNameClash(std::string& wsName) { - success = false; + bool noClash(false); + + for (int i = 0; !noClash; ++i) + { + std::string wsIndex = ""; //dont use an index if there is no other workspace + if (i > 0) + { + wsIndex = "_" + boost::lexical_cast(i); + } + + bool wsExists = AnalysisDataService::Instance().doesExist(wsName + wsIndex); + if (!wsExists) + { + wsName += wsIndex; + noClash = true; + } + } } - } - return success; -} - -/** - * Load the workspace name, if the attribute exists - * - * @param root :: Root of NeXus file - * @param entry_name :: Entry in NeXus file to look at - * @return The workspace name. If none found an empty string is returned. - */ -std::string LoadNexusProcessed::loadWorkspaceName(NXRoot & root, const std::string& entry_name) -{ - NXEntry mtd_entry = root.openEntry(entry_name); - try - { - return mtd_entry.getString("workspace_name"); - } - catch (std::runtime_error&) - { - return std::string(); - } -} + /** + * Check if the workspace name contains a common stem and load the workspace names + * + * @param root :: the root for the NeXus document + * @param names :: vector to store the names to be loaded. + * @return Whether there was a common stem. + */ + bool LoadNexusProcessed::checkForCommonNameStem(NXRoot & root, std::vector& names) + { + bool success(true); + int64_t nWorkspaceEntries = static_cast(root.groups().size()); + for (int64_t p = 1; p <= nWorkspaceEntries; ++p) + { + std::ostringstream os; + os << p; + names[p] = loadWorkspaceName(root, "mantid_workspace_" + os.str()); -//------------------------------------------------------------------------------------------------- -/** Load the event_workspace field - * - * @param wksp_cls - * @param xbins - * @param progressStart - * @param progressRange - * @return - */ -API::MatrixWorkspace_sptr LoadNexusProcessed::loadEventEntry(NXData & wksp_cls, NXDouble & xbins, - const double& progressStart, const double& progressRange) -{ - NXDataSetTyped indices_data = wksp_cls.openNXDataSet("indices"); - indices_data.load(); - boost::shared_array indices = indices_data.sharedBuffer(); - int numspec = indices_data.dim0()-1; - - int num_xbins = xbins.dim0(); - if (num_xbins < 2) num_xbins = 2; - EventWorkspace_sptr ws = boost::dynamic_pointer_cast - (WorkspaceFactory::Instance().create("EventWorkspace", numspec, num_xbins, num_xbins-1)); - - // Set the YUnit label - ws->setYUnit(indices_data.attributes("units")); - std::string unitLabel = indices_data.attributes("unit_label"); - if (unitLabel.empty()) unitLabel = indices_data.attributes("units"); - ws->setYUnitLabel(unitLabel); - - //Handle optional fields. - // TODO: Handle inconsistent sizes - boost::shared_array pulsetimes; - if (wksp_cls.isValid("pulsetime")) - { - NXDataSetTyped pulsetime = wksp_cls.openNXDataSet("pulsetime"); - pulsetime.load(); - pulsetimes = pulsetime.sharedBuffer(); - } + boost::smatch results; + const boost::regex exp(".*_\\d+$"); - boost::shared_array tofs; - if (wksp_cls.isValid("tof")) - { - NXDouble tof = wksp_cls.openNXDouble("tof"); - tof.load(); - tofs = tof.sharedBuffer(); - } + //check if the workspace name has an index on the end + if (!boost::regex_match(names[p], results, exp)) + { + success = false; + } + } - boost::shared_array error_squareds; - if (wksp_cls.isValid("error_squared")) - { - NXFloat error_squared = wksp_cls.openNXFloat("error_squared"); - error_squared.load(); - error_squareds = error_squared.sharedBuffer(); - } + return success; + } - boost::shared_array weights; - if (wksp_cls.isValid("weight")) - { - NXFloat weight = wksp_cls.openNXFloat("weight"); - weight.load(); - weights = weight.sharedBuffer(); - } + /** + * Load the workspace name, if the attribute exists + * + * @param root :: Root of NeXus file + * @param entry_name :: Entry in NeXus file to look at + * @return The workspace name. If none found an empty string is returned. + */ + std::string LoadNexusProcessed::loadWorkspaceName(NXRoot & root, const std::string& entry_name) + { + NXEntry mtd_entry = root.openEntry(entry_name); + try + { + return mtd_entry.getString("workspace_name"); + } catch (std::runtime_error&) + { + return std::string(); + } + } - // What type of event lists? - EventType type = TOF; - if (tofs && pulsetimes && weights && error_squareds) - type = WEIGHTED; - else if ((tofs && weights && error_squareds)) - type = WEIGHTED_NOTIME; - else if (pulsetimes && tofs) - type = TOF; - else - throw std::runtime_error("Could not figure out the type of event list!"); - - // Create all the event lists - PARALLEL_FOR_NO_WSP_CHECK() - for (int wi=0; wi < numspec; wi++) - { - PARALLEL_START_INTERUPT_REGION - int64_t index_start = indices[wi]; - int64_t index_end = indices[wi+1]; - if (index_end >= index_start) +//------------------------------------------------------------------------------------------------- + /** Load the event_workspace field + * + * @param wksp_cls + * @param xbins + * @param progressStart + * @param progressRange + * @return + */ + API::MatrixWorkspace_sptr LoadNexusProcessed::loadEventEntry(NXData & wksp_cls, NXDouble & xbins, + const double& progressStart, const double& progressRange) { - EventList & el = ws->getEventList(wi); - el.switchTo(type); + NXDataSetTyped indices_data = wksp_cls.openNXDataSet("indices"); + indices_data.load(); + boost::shared_array indices = indices_data.sharedBuffer(); + int numspec = indices_data.dim0() - 1; + + int num_xbins = xbins.dim0(); + if (num_xbins < 2) + num_xbins = 2; + EventWorkspace_sptr ws = boost::dynamic_pointer_cast( + WorkspaceFactory::Instance().create("EventWorkspace", numspec, num_xbins, num_xbins - 1)); + + // Set the YUnit label + ws->setYUnit(indices_data.attributes("units")); + std::string unitLabel = indices_data.attributes("unit_label"); + if (unitLabel.empty()) + unitLabel = indices_data.attributes("units"); + ws->setYUnitLabel(unitLabel); + + //Handle optional fields. + // TODO: Handle inconsistent sizes + boost::shared_array pulsetimes; + if (wksp_cls.isValid("pulsetime")) + { + NXDataSetTyped pulsetime = wksp_cls.openNXDataSet("pulsetime"); + pulsetime.load(); + pulsetimes = pulsetime.sharedBuffer(); + } - // Allocate all the required memory - el.reserve(index_end - index_start); - el.clearDetectorIDs(); + boost::shared_array tofs; + if (wksp_cls.isValid("tof")) + { + NXDouble tof = wksp_cls.openNXDouble("tof"); + tof.load(); + tofs = tof.sharedBuffer(); + } - for (int64_t i=index_start; i error_squareds; + if (wksp_cls.isValid("error_squared")) { - case TOF: - el.addEventQuickly( TofEvent( tofs[i], DateAndTime(pulsetimes[i])) ); - break; - case WEIGHTED: - el.addEventQuickly( WeightedEvent( tofs[i], DateAndTime(pulsetimes[i]), weights[i], error_squareds[i]) ); - break; - case WEIGHTED_NOTIME: - el.addEventQuickly( WeightedEventNoTime( tofs[i], weights[i], error_squareds[i]) ); - break; + NXFloat error_squared = wksp_cls.openNXFloat("error_squared"); + error_squared.load(); + error_squareds = error_squared.sharedBuffer(); } - // Set the X axis - if (this->m_shared_bins) - el.setX(this->m_xbins); - else + boost::shared_array weights; + if (wksp_cls.isValid("weight")) { - MantidVec x; - x.resize(xbins.dim0()); - for (int i=0; i < xbins.dim0(); i++) - x[i] = xbins(wi, i); - el.setX(x); + NXFloat weight = wksp_cls.openNXFloat("weight"); + weight.load(); + weights = weight.sharedBuffer(); } - } - progress(progressStart + progressRange*(1.0/numspec)); - PARALLEL_END_INTERUPT_REGION - } - PARALLEL_CHECK_INTERUPT_REGION + // What type of event lists? + EventType type = TOF; + if (tofs && pulsetimes && weights && error_squareds) + type = WEIGHTED; + else if ((tofs && weights && error_squareds)) + type = WEIGHTED_NOTIME; + else if (pulsetimes && tofs) + type = TOF; + else + throw std::runtime_error("Could not figure out the type of event list!"); + // Create all the event lists + PARALLEL_FOR_NO_WSP_CHECK() + for (int wi = 0; wi < numspec; wi++) + { + PARALLEL_START_INTERUPT_REGION + int64_t index_start = indices[wi]; + int64_t index_end = indices[wi + 1]; + if (index_end >= index_start) + { + EventList & el = ws->getEventList(wi); + el.switchTo(type); + + // Allocate all the required memory + el.reserve(index_end - index_start); + el.clearDetectorIDs(); + + for (int64_t i = index_start; i < index_end; i++) + switch (type) + { + case TOF: + el.addEventQuickly(TofEvent(tofs[i], DateAndTime(pulsetimes[i]))); + break; + case WEIGHTED: + el.addEventQuickly( + WeightedEvent(tofs[i], DateAndTime(pulsetimes[i]), weights[i], error_squareds[i])); + break; + case WEIGHTED_NOTIME: + el.addEventQuickly(WeightedEventNoTime(tofs[i], weights[i], error_squareds[i])); + break; + } + + // Set the X axis + if (this->m_shared_bins) + el.setX(this->m_xbins); + else + { + MantidVec x; + x.resize(xbins.dim0()); + for (int i = 0; i < xbins.dim0(); i++) + x[i] = xbins(wi, i); + el.setX(x); + } + } - return ws; -} + progress(progressStart + progressRange * (1.0 / numspec)); + PARALLEL_END_INTERUPT_REGION + } + PARALLEL_CHECK_INTERUPT_REGION + return ws; + } //------------------------------------------------------------------------------------------------- -/** - * Load a table - */ -API::Workspace_sptr LoadNexusProcessed::loadTableEntry(NXEntry & entry) -{ - API::ITableWorkspace_sptr workspace; - workspace = Mantid::API::WorkspaceFactory::Instance().createTable("TableWorkspace"); + /** + * Load a table + */ + API::Workspace_sptr LoadNexusProcessed::loadTableEntry(NXEntry & entry) + { + API::ITableWorkspace_sptr workspace; + workspace = Mantid::API::WorkspaceFactory::Instance().createTable("TableWorkspace"); - NXData nx_tw = entry.openNXData("table_workspace"); + NXData nx_tw = entry.openNXData("table_workspace"); - bool hasNumberOfRowBeenSet = false; - //int numberOfRows = 0; + bool hasNumberOfRowBeenSet = false; + //int numberOfRows = 0; - int columnNumber = 1; - do - { - std::string str = "column_" + boost::lexical_cast(columnNumber); - - NXInfo info = nx_tw.getDataSetInfo(str.c_str()); - if (info.stat == NX_ERROR) + int columnNumber = 1; + do { - // Assume we done last column of table - break; - } + std::string str = "column_" + boost::lexical_cast(columnNumber); - if ( info.rank == 1 ) - { - if ( info.type == NX_FLOAT64 ) + NXInfo info = nx_tw.getDataSetInfo(str.c_str()); + if (info.stat == NX_ERROR) { - NXDouble nxDouble = nx_tw.openNXDouble(str.c_str()); - std::string columnTitle = nxDouble.attributes("name"); - if (!columnTitle.empty()) + // Assume we done last column of table + break; + } + + if (info.rank == 1) + { + if (info.type == NX_FLOAT64) { - workspace->addColumn("double", columnTitle); - nxDouble.load(); - int length = nxDouble.dim0(); - if ( !hasNumberOfRowBeenSet ) + NXDouble nxDouble = nx_tw.openNXDouble(str.c_str()); + std::string columnTitle = nxDouble.attributes("name"); + if (!columnTitle.empty()) { - workspace->setRowCount(length); - hasNumberOfRowBeenSet = true; + workspace->addColumn("double", columnTitle); + nxDouble.load(); + int length = nxDouble.dim0(); + if (!hasNumberOfRowBeenSet) + { + workspace->setRowCount(length); + hasNumberOfRowBeenSet = true; + } + for (int i = 0; i < length; i++) + workspace->cell(i, columnNumber - 1) = *(nxDouble() + i); } - for (int i = 0; i < length; i++) - workspace->cell(i,columnNumber-1) = *(nxDouble() + i); } - } - else if ( info.type == NX_INT32 ) - { - NXInt nxInt = nx_tw.openNXInt(str.c_str()); - std::string columnTitle = nxInt.attributes("name"); - if (!columnTitle.empty()) + else if (info.type == NX_INT32) { - workspace->addColumn("int", columnTitle); - nxInt.load(); - int length = nxInt.dim0(); - if ( !hasNumberOfRowBeenSet ) + NXInt nxInt = nx_tw.openNXInt(str.c_str()); + std::string columnTitle = nxInt.attributes("name"); + if (!columnTitle.empty()) { - workspace->setRowCount(length); - hasNumberOfRowBeenSet = true; + workspace->addColumn("int", columnTitle); + nxInt.load(); + int length = nxInt.dim0(); + if (!hasNumberOfRowBeenSet) + { + workspace->setRowCount(length); + hasNumberOfRowBeenSet = true; + } + for (int i = 0; i < length; i++) + workspace->cell(i, columnNumber - 1) = *(nxInt() + i); } - for (int i = 0; i < length; i++) - workspace->cell(i,columnNumber-1) = *(nxInt() + i); } } - } - else if ( info.rank == 2 ) - { - if ( info.type == NX_CHAR ) + else if (info.rank == 2) { - NXChar data = nx_tw.openNXChar(str.c_str()); - std::string columnTitle = data.attributes("name"); - if (!columnTitle.empty()) + if (info.type == NX_CHAR) { - workspace->addColumn("str", columnTitle); - int nRows = info.dims[0]; - if ( !hasNumberOfRowBeenSet ) + NXChar data = nx_tw.openNXChar(str.c_str()); + std::string columnTitle = data.attributes("name"); + if (!columnTitle.empty()) { - workspace->setRowCount(nRows); - hasNumberOfRowBeenSet = true; - } - - const int maxStr = info.dims[1]; - data.load(); - for (int iR = 0; iR < nRows; ++iR) - { - auto& cellContents = workspace->cell(iR,columnNumber-1); - auto startPoint = data() + maxStr*iR; - cellContents.assign(startPoint,startPoint+maxStr); - boost::trim_right(cellContents); + workspace->addColumn("str", columnTitle); + int nRows = info.dims[0]; + if (!hasNumberOfRowBeenSet) + { + workspace->setRowCount(nRows); + hasNumberOfRowBeenSet = true; + } + + const int maxStr = info.dims[1]; + data.load(); + for (int iR = 0; iR < nRows; ++iR) + { + auto& cellContents = workspace->cell(iR, columnNumber - 1); + auto startPoint = data() + maxStr * iR; + cellContents.assign(startPoint, startPoint + maxStr); + boost::trim_right(cellContents); + } } } - } - #define IF_VECTOR_COLUMN(Type, ColumnTypeName, NexusType) \ +#define IF_VECTOR_COLUMN(Type, ColumnTypeName, NexusType) \ else if ( info.type == NexusType ) \ { \ loadVectorColumn(nx_tw, str, workspace, #ColumnTypeName); \ } - IF_VECTOR_COLUMN(int, vector_int, NX_INT32) - IF_VECTOR_COLUMN(double, vector_double, NX_FLOAT64) - - } + IF_VECTOR_COLUMN(int, vector_int, NX_INT32) + IF_VECTOR_COLUMN(double, vector_double, NX_FLOAT64) - columnNumber++; - - } while ( 1 ); - - return boost::static_pointer_cast(workspace); -} - -/** - * Loads a vector column to the TableWorkspace. - * @param tableData :: Table data to load from - * @param dataSetName :: Name of the data set to use to get column data - * @param tableWs :: Workspace to add column to - * @param columnType :: Name of the column type to create - */ -template -void LoadNexusProcessed::loadVectorColumn(const NXData& tableData, - const std::string& dataSetName, - const ITableWorkspace_sptr& tableWs, - const std::string& columnType) -{ - NXDataSetTyped data = tableData.openNXDataSet(dataSetName.c_str()); - std::string columnTitle = data.attributes("name"); - if ( ! columnTitle.empty() ) - { - tableWs->addColumn(columnType, columnTitle); + } - NXInfo info = tableData.getDataSetInfo(dataSetName.c_str()); - const size_t rowCount = info.dims[0]; - const size_t blockSize = info.dims[1]; + columnNumber++; - // This might've been done already, but doing it twice should't do any harm - tableWs->setRowCount(rowCount); + } while (1); - data.load(); + return boost::static_pointer_cast(workspace); + } - for ( size_t i = 0; i < rowCount; ++i ) + /** + * Loads a vector column to the TableWorkspace. + * @param tableData :: Table data to load from + * @param dataSetName :: Name of the data set to use to get column data + * @param tableWs :: Workspace to add column to + * @param columnType :: Name of the column type to create + */ + template + void LoadNexusProcessed::loadVectorColumn(const NXData& tableData, const std::string& dataSetName, + const ITableWorkspace_sptr& tableWs, const std::string& columnType) + { + NXDataSetTyped data = tableData.openNXDataSet(dataSetName.c_str()); + std::string columnTitle = data.attributes("name"); + if (!columnTitle.empty()) { - auto& cell = tableWs->cell< std::vector >(i, tableWs->columnCount() - 1); + tableWs->addColumn(columnType, columnTitle); - Type* from = data() + blockSize * i; + NXInfo info = tableData.getDataSetInfo(dataSetName.c_str()); + const size_t rowCount = info.dims[0]; + const size_t blockSize = info.dims[1]; - cell.assign(from, from + blockSize); + // This might've been done already, but doing it twice should't do any harm + tableWs->setRowCount(rowCount); - std::ostringstream rowSizeAttrName; rowSizeAttrName << "row_size_" << i; + data.load(); - // This is ugly, but I can only get attribute as a string using the API - std::istringstream rowSizeStr( data.attributes(rowSizeAttrName.str()) ); + for (size_t i = 0; i < rowCount; ++i) + { + auto& cell = tableWs->cell >(i, tableWs->columnCount() - 1); - int rowSize; rowSizeStr >> rowSize; + Type* from = data() + blockSize * i; - cell.resize(rowSize); - } - } -} + cell.assign(from, from + blockSize); -//------------------------------------------------------------------------------------------------- -/** - * Load peaks - */ -API::Workspace_sptr LoadNexusProcessed::loadPeaksEntry(NXEntry & entry) -{ - //API::IPeaksWorkspace_sptr workspace; - API::ITableWorkspace_sptr tWorkspace; - //PeaksWorkspace_sptr workspace; - tWorkspace = Mantid::API::WorkspaceFactory::Instance().createTable("PeaksWorkspace"); + std::ostringstream rowSizeAttrName; + rowSizeAttrName << "row_size_" << i; - PeaksWorkspace_sptr peakWS = boost::dynamic_pointer_cast(tWorkspace); + // This is ugly, but I can only get attribute as a string using the API + std::istringstream rowSizeStr(data.attributes(rowSizeAttrName.str())); - NXData nx_tw = entry.openNXData("peaks_workspace"); + int rowSize; + rowSizeStr >> rowSize; + cell.resize(rowSize); + } + } + } - int columnNumber = 1; - int numberPeaks = 0; - std::vector columnNames; - do +//------------------------------------------------------------------------------------------------- + /** + * Load peaks + */ + API::Workspace_sptr LoadNexusProcessed::loadPeaksEntry(NXEntry & entry) { - std::string str = "column_" + boost::lexical_cast(columnNumber); - - NXInfo info = nx_tw.getDataSetInfo(str.c_str()); - if (info.stat == NX_ERROR) - { - // Assume we done last column of table - break; - } + //API::IPeaksWorkspace_sptr workspace; + API::ITableWorkspace_sptr tWorkspace; + //PeaksWorkspace_sptr workspace; + tWorkspace = Mantid::API::WorkspaceFactory::Instance().createTable("PeaksWorkspace"); - // store column names - columnNames.push_back(str); + PeaksWorkspace_sptr peakWS = boost::dynamic_pointer_cast(tWorkspace); + NXData nx_tw = entry.openNXData("peaks_workspace"); - // determine number of peaks - // here we assume that a peaks_table has always one column of doubles - - if ( info.type == NX_FLOAT64 ) + int columnNumber = 1; + int numberPeaks = 0; + std::vector columnNames; + do { - NXDouble nxDouble = nx_tw.openNXDouble(str.c_str()); - std::string columnTitle = nxDouble.attributes("name"); - if (!columnTitle.empty() && numberPeaks==0) + std::string str = "column_" + boost::lexical_cast(columnNumber); + + NXInfo info = nx_tw.getDataSetInfo(str.c_str()); + if (info.stat == NX_ERROR) { - numberPeaks = nxDouble.dim0(); + // Assume we done last column of table + break; } - } - - columnNumber++; - } while ( 1 ); + // store column names + columnNames.push_back(str); + // determine number of peaks + // here we assume that a peaks_table has always one column of doubles - //Get information from all but data group - std::string parameterStr; - // Hop to the right point - m_cppFile->openPath(entry.path()); - try - { - // This loads logs, sample, and instrument. - peakWS->loadExperimentInfoNexus(m_cppFile, parameterStr); - } - catch (std::exception & e) - { - g_log.information("Error loading Instrument section of nxs file"); - g_log.information(e.what()); - } - - - // std::vector p; - for (int r = 0; r < numberPeaks; r++) - { - Kernel::V3D v3d; - v3d[2] = 1.0; - API::IPeak* p; - p = peakWS->createPeak(v3d); - peakWS->addPeak(*p); - } + if (info.type == NX_FLOAT64) + { + NXDouble nxDouble = nx_tw.openNXDouble(str.c_str()); + std::string columnTitle = nxDouble.attributes("name"); + if (!columnTitle.empty() && numberPeaks == 0) + { + numberPeaks = nxDouble.dim0(); + } + } + columnNumber++; + } while (1); - for (size_t i = 0; i < columnNames.size(); i++) - { - const std::string str = columnNames[i]; - if ( !str.compare("column_1") ) + //Get information from all but data group + std::string parameterStr; + // Hop to the right point + m_cppFile->openPath(entry.path()); + try { - NXInt nxInt = nx_tw.openNXInt(str.c_str()); - nxInt.load(); - - for (int r = 0; r < numberPeaks; r++) { - int ival = nxInt[r]; - if( ival != -1) peakWS->getPeak(r).setDetectorID( ival ); - } - } - - if ( !str.compare("column_2") ) + // This loads logs, sample, and instrument. + peakWS->loadExperimentInfoNexus(m_cppFile, parameterStr); + } catch (std::exception & e) { - NXDouble nxDouble = nx_tw.openNXDouble(str.c_str()); - nxDouble.load(); - - for (int r = 0; r < numberPeaks; r++) { - double val = nxDouble[r]; - peakWS->getPeak(r).setH( val ); - } + g_log.information("Error loading Instrument section of nxs file"); + g_log.information(e.what()); } - if ( !str.compare("column_3") ) + // std::vector p; + for (int r = 0; r < numberPeaks; r++) { - NXDouble nxDouble = nx_tw.openNXDouble(str.c_str()); - nxDouble.load(); - - for (int r = 0; r < numberPeaks; r++) { - double val = nxDouble[r]; - peakWS->getPeak(r).setK( val ); - } + Kernel::V3D v3d; + v3d[2] = 1.0; + API::IPeak* p; + p = peakWS->createPeak(v3d); + peakWS->addPeak(*p); } - if ( !str.compare("column_4") ) + for (size_t i = 0; i < columnNames.size(); i++) { - NXDouble nxDouble = nx_tw.openNXDouble(str.c_str()); - nxDouble.load(); + const std::string str = columnNames[i]; + if (!str.compare("column_1")) + { + NXInt nxInt = nx_tw.openNXInt(str.c_str()); + nxInt.load(); - for (int r = 0; r < numberPeaks; r++) { - double val = nxDouble[r]; - peakWS->getPeak(r).setL( val ); + for (int r = 0; r < numberPeaks; r++) + { + int ival = nxInt[r]; + if (ival != -1) + peakWS->getPeak(r).setDetectorID(ival); + } } - } - if ( !str.compare("column_5") ) - { - NXDouble nxDouble = nx_tw.openNXDouble(str.c_str()); - nxDouble.load(); + if (!str.compare("column_2")) + { + NXDouble nxDouble = nx_tw.openNXDouble(str.c_str()); + nxDouble.load(); - for (int r = 0; r < numberPeaks; r++) { - double val = nxDouble[r]; - peakWS->getPeak(r).setIntensity( val ); + for (int r = 0; r < numberPeaks; r++) + { + double val = nxDouble[r]; + peakWS->getPeak(r).setH(val); + } } - } - if ( !str.compare("column_6") ) - { - NXDouble nxDouble = nx_tw.openNXDouble(str.c_str()); - nxDouble.load(); + if (!str.compare("column_3")) + { + NXDouble nxDouble = nx_tw.openNXDouble(str.c_str()); + nxDouble.load(); - for (int r = 0; r < numberPeaks; r++) { - double val = nxDouble[r]; - peakWS->getPeak(r).setSigmaIntensity( val ); + for (int r = 0; r < numberPeaks; r++) + { + double val = nxDouble[r]; + peakWS->getPeak(r).setK(val); + } } - } + if (!str.compare("column_4")) + { + NXDouble nxDouble = nx_tw.openNXDouble(str.c_str()); + nxDouble.load(); + for (int r = 0; r < numberPeaks; r++) + { + double val = nxDouble[r]; + peakWS->getPeak(r).setL(val); + } + } - if ( !str.compare("column_7") ) - { - NXDouble nxDouble = nx_tw.openNXDouble(str.c_str()); - nxDouble.load(); + if (!str.compare("column_5")) + { + NXDouble nxDouble = nx_tw.openNXDouble(str.c_str()); + nxDouble.load(); - for (int r = 0; r < numberPeaks; r++) { - double val = nxDouble[r]; - peakWS->getPeak(r).setBinCount( val ); + for (int r = 0; r < numberPeaks; r++) + { + double val = nxDouble[r]; + peakWS->getPeak(r).setIntensity(val); + } } - } + if (!str.compare("column_6")) + { + NXDouble nxDouble = nx_tw.openNXDouble(str.c_str()); + nxDouble.load(); - if ( !str.compare("column_10") ) - { - NXDouble nxDouble = nx_tw.openNXDouble(str.c_str()); - nxDouble.load(); - - for (int r = 0; r < numberPeaks; r++) { - double val = nxDouble[r]; - peakWS->getPeak(r).setWavelength( val ); + for (int r = 0; r < numberPeaks; r++) + { + double val = nxDouble[r]; + peakWS->getPeak(r).setSigmaIntensity(val); + } } - } - if ( !str.compare("column_14") ) - { - NXInt nxInt = nx_tw.openNXInt(str.c_str()); - nxInt.load(); + if (!str.compare("column_7")) + { + NXDouble nxDouble = nx_tw.openNXDouble(str.c_str()); + nxDouble.load(); - for (int r = 0; r < numberPeaks; r++) { - int ival = nxInt[r]; - if( ival != -1) peakWS->getPeak(r).setRunNumber( ival ); + for (int r = 0; r < numberPeaks; r++) + { + double val = nxDouble[r]; + peakWS->getPeak(r).setBinCount(val); + } } - } - if ( !str.compare("column_15") ) - { - NXDouble nxDouble = nx_tw.openNXDouble(str.c_str()); - nxDouble.load(); - Kernel::Matrix gm(3, 3, false); - int k = 0; - for (int r = 0; r < numberPeaks; r++) { - for (int j = 0; j < 9; j++) - { - double val = nxDouble[k]; - k++; - gm[j%3][j/3] = val; - } - peakWS->getPeak(r).setGoniometerMatrix( gm ); + if (!str.compare("column_10")) + { + NXDouble nxDouble = nx_tw.openNXDouble(str.c_str()); + nxDouble.load(); + + for (int r = 0; r < numberPeaks; r++) + { + double val = nxDouble[r]; + peakWS->getPeak(r).setWavelength(val); + } } - } - } + if (!str.compare("column_14")) + { + NXInt nxInt = nx_tw.openNXInt(str.c_str()); + nxInt.load(); - return boost::static_pointer_cast(peakWS); -} + for (int r = 0; r < numberPeaks; r++) + { + int ival = nxInt[r]; + if (ival != -1) + peakWS->getPeak(r).setRunNumber(ival); + } + } -//------------------------------------------------------------------------------------------------- -/** - * Load a single entry into a workspace - * @param root :: The opened root node - * @param entry_name :: The entry name - * @param progressStart :: The percentage value to start the progress reporting for this entry - * @param progressRange :: The percentage range that the progress reporting should cover - * @returns A 2D workspace containing the loaded data - */ -API::Workspace_sptr LoadNexusProcessed::loadEntry(NXRoot & root, const std::string & entry_name, - const double& progressStart, const double& progressRange) -{ - progress(progressStart,"Opening entry " + entry_name + "..."); + if (!str.compare("column_15")) + { + NXDouble nxDouble = nx_tw.openNXDouble(str.c_str()); + nxDouble.load(); + Kernel::Matrix gm(3, 3, false); + int k = 0; + for (int r = 0; r < numberPeaks; r++) + { + for (int j = 0; j < 9; j++) + { + double val = nxDouble[k]; + k++; + gm[j % 3][j / 3] = val; + } + peakWS->getPeak(r).setGoniometerMatrix(gm); + } + } - NXEntry mtd_entry = root.openEntry(entry_name); + } - if (mtd_entry.containsGroup("table_workspace")) - { - return loadTableEntry(mtd_entry); - } + return boost::static_pointer_cast(peakWS); + } - if (mtd_entry.containsGroup("peaks_workspace")) +//------------------------------------------------------------------------------------------------- + /** + * Load a single entry into a workspace + * @param root :: The opened root node + * @param entry_name :: The entry name + * @param progressStart :: The percentage value to start the progress reporting for this entry + * @param progressRange :: The percentage range that the progress reporting should cover + * @returns A 2D workspace containing the loaded data + */ + API::Workspace_sptr LoadNexusProcessed::loadEntry(NXRoot & root, const std::string & entry_name, + const double& progressStart, const double& progressRange) { - return loadPeaksEntry(mtd_entry); - } + progress(progressStart, "Opening entry " + entry_name + "..."); + NXEntry mtd_entry = root.openEntry(entry_name); - // Determine workspace type and name of group containing workspace characteristics - bool isEvent = false; - std::string workspaceType = "Workspace2D"; - std::string group_name = "workspace"; - if (mtd_entry.containsGroup("event_workspace")) - { - isEvent = true; - group_name = "event_workspace"; - } - else if (mtd_entry.containsGroup("offsets_workspace")) - { - workspaceType = "OffsetsWorkspace"; - group_name = "offsets_workspace"; - } + if (mtd_entry.containsGroup("table_workspace")) + { + return loadTableEntry(mtd_entry); + } - // Get workspace characteristics - NXData wksp_cls = mtd_entry.openNXData(group_name); - - // Axis information - // "X" axis - NXDouble xbins = wksp_cls.openNXDouble("axis1"); - xbins.load(); - std::string unit1 = xbins.attributes("units"); - // Non-uniform x bins get saved as a 2D 'axis1' dataset - int xlength(-1); - if( xbins.rank() == 2 ) - { - xlength = xbins.dim1(); - m_shared_bins = false; - } - else if( xbins.rank() == 1 ) - { - xlength = xbins.dim0(); - m_shared_bins = true; - xbins.load(); - m_xbins.access().assign(xbins(), xbins() + xlength); - } - else - { - throw std::runtime_error("Unknown axis1 dimension encountered."); - } + if (mtd_entry.containsGroup("peaks_workspace")) + { + return loadPeaksEntry(mtd_entry); + } - // MatrixWorkspace axis 1 - NXDouble axis2 = wksp_cls.openNXDouble("axis2"); - std::string unit2 = axis2.attributes("units"); + // Determine workspace type and name of group containing workspace characteristics + bool isEvent = false; + std::string workspaceType = "Workspace2D"; + std::string group_name = "workspace"; + if (mtd_entry.containsGroup("event_workspace")) + { + isEvent = true; + group_name = "event_workspace"; + } + else if (mtd_entry.containsGroup("offsets_workspace")) + { + workspaceType = "OffsetsWorkspace"; + group_name = "offsets_workspace"; + } - // The workspace being worked on - API::MatrixWorkspace_sptr local_workspace; - size_t nspectra; - int64_t nchannels; + // Get workspace characteristics + NXData wksp_cls = mtd_entry.openNXData(group_name); - // -------- Process as event ? -------------------- - if (isEvent) - { - local_workspace = loadEventEntry(wksp_cls, xbins, progressStart, progressRange); - nspectra = local_workspace->getNumberHistograms(); - nchannels = local_workspace->blocksize(); - } - else - { - NXDataSetTyped 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")) + // Axis information + // "X" axis + NXDouble xbins = wksp_cls.openNXDouble("axis1"); + xbins.load(); + std::string unit1 = xbins.attributes("units"); + // Non-uniform x bins get saved as a 2D 'axis1' dataset + int xlength(-1); + if (xbins.rank() == 2) { - // frac_area entry is the signal for a RebinnedOutput workspace - hasFracArea = true; - workspaceType.clear(); - workspaceType = "RebinnedOutput"; + xlength = xbins.dim1(); + m_shared_bins = false; } - local_workspace = boost::dynamic_pointer_cast - (WorkspaceFactory::Instance().create(workspaceType, total_specs, xlength, nchannels)); - try + else if (xbins.rank() == 1) { - local_workspace->setTitle(mtd_entry.getString("title")); + xlength = xbins.dim0(); + m_shared_bins = true; + xbins.load(); + m_xbins.access().assign(xbins(), xbins() + xlength); } - catch (std::runtime_error&) + else { - g_log.debug() << "No title was found in the input file, " << getPropertyValue("Filename") << std::endl; + throw std::runtime_error("Unknown axis1 dimension encountered."); } - // 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 errors = wksp_cls.openNXDouble("errors"); - NXDataSetTyped fracarea = wksp_cls.openNXDouble("errors"); - if (hasFracArea) + // MatrixWorkspace axis 1 + NXDouble axis2 = wksp_cls.openNXDouble("axis2"); + std::string unit2 = axis2.attributes("units"); + + // The workspace being worked on + API::MatrixWorkspace_sptr local_workspace; + size_t nspectra; + int64_t nchannels; + + // -------- Process as event ? -------------------- + if (isEvent) { - fracarea = wksp_cls.openNXDouble("frac_area"); + local_workspace = loadEventEntry(wksp_cls, xbins, progressStart, progressRange); + nspectra = local_workspace->getNumberHistograms(); + nchannels = local_workspace->blocksize(); } - - 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 ) + else { - //if spectrum min,max,list properties are set - if(m_interval||m_list) + NXDataSetTyped 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")) { - //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(m_spec_max-m_spec_min); - fullblocks=(interval_specs)/blocksize; - read_stop = (fullblocks * blocksize)+m_spec_min-1; + // frac_area entry is the signal for a RebinnedOutput workspace + hasFracArea = true; + workspaceType.clear(); + workspaceType = "RebinnedOutput"; + } + local_workspace = boost::dynamic_pointer_cast( + 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; + } - if(interval_specssetYUnit(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 errors = wksp_cls.openNXDouble("errors"); + NXDataSetTyped fracarea = wksp_cls.openNXDouble("errors"); + if (hasFracArea) + { + fracarea = wksp_cls.openNXDouble("frac_area"); + } - for( ; hist_index < read_stop; ) + 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) { - progress(progressBegin+progressScaler*static_cast(hist_index)/static_cast(read_stop),"Reading workspace data..."); - loadBlock(data, errors, fracarea, hasFracArea, blocksize, nchannels, hist_index,wsIndex, local_workspace); + //specs at the min-max interval + int interval_specs = static_cast(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(hist_index) + / static_cast(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); + } } - int64_t finalblock = m_spec_max-1 - read_stop; - if( finalblock > 0 ) + // if spectrum list property is set read each spectrum separately by setting blocksize=1 + if (m_list) { - loadBlock(data, errors, fracarea, hasFracArea, finalblock, nchannels, hist_index,wsIndex,local_workspace); + std::vector::iterator itr = m_spec_list.begin(); + for (; itr != m_spec_list.end(); ++itr) + { + int64_t specIndex = (*itr) - 1; + progress( + progressBegin + + progressScaler * static_cast(specIndex) + / static_cast(m_spec_list.size()), "Reading workspace data..."); + loadBlock(data, errors, fracarea, hasFracArea, static_cast(1), nchannels, + specIndex, wsIndex, local_workspace); + } + } } - // if spectrum list property is set read each spectrum separately by setting blocksize=1 - if(m_list) + else { - std::vector::iterator itr=m_spec_list.begin(); - for(;itr!=m_spec_list.end();++itr) + for (; hist_index < read_stop;) { - int64_t specIndex=(*itr)-1; - progress(progressBegin+progressScaler*static_cast(specIndex)/static_cast(m_spec_list.size()),"Reading workspace data..."); - loadBlock(data, errors, fracarea, hasFracArea, static_cast(1), nchannels, specIndex,wsIndex, local_workspace); + progress( + progressBegin + + progressScaler * static_cast(hist_index) / static_cast(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 { - for( ; hist_index < read_stop; ) - { - progress(progressBegin+progressScaler*static_cast(hist_index)/static_cast(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) + if (m_interval || m_list) { - 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(hist_index)/static_cast(read_stop),"Reading workspace data..."); - loadBlock(data, errors, fracarea, hasFracArea, xbins, blocksize, nchannels, hist_index,wsIndex,local_workspace); + 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(hist_index) + / static_cast(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); + } } - int64_t finalblock = m_spec_max-1 - read_stop; - if( finalblock > 0 ) + // + if (m_list) { - loadBlock(data, errors, fracarea, hasFracArea, xbins, finalblock, nchannels, hist_index,wsIndex, local_workspace); + std::vector::iterator itr = m_spec_list.begin(); + for (; itr != m_spec_list.end(); ++itr) + { + int64_t specIndex = (*itr) - 1; + progress( + progressBegin + + progressScaler * static_cast(specIndex) / static_cast(read_stop), + "Reading workspace data..."); + loadBlock(data, errors, fracarea, hasFracArea, xbins, 1, nchannels, specIndex, wsIndex, + local_workspace); + } + } } - // - if(m_list) + else { - std::vector::iterator itr=m_spec_list.begin(); - for(;itr!=m_spec_list.end();++itr) + for (; hist_index < read_stop;) { - int64_t specIndex=(*itr)-1; - progress(progressBegin+progressScaler*static_cast(specIndex)/static_cast(read_stop),"Reading workspace data..."); - loadBlock(data, errors, fracarea, hasFracArea, xbins, 1, nchannels, specIndex,wsIndex,local_workspace); + progress( + progressBegin + + progressScaler * static_cast(hist_index) / static_cast(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); } - } } - else + } //end of NOT an event ------------------------------- + + //Units + bool verticalHistogram(false); + try + { + local_workspace->getAxis(0)->unit() = UnitFactory::Instance().create(unit1); + if (unit1 == "Label") { - for( ; hist_index < read_stop; ) - { - progress(progressBegin+progressScaler*static_cast(hist_index)/static_cast(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); - } + auto label = boost::dynamic_pointer_cast( + local_workspace->getAxis(0)->unit()); + auto ax = wksp_cls.openNXDouble("axis1"); + label->setLabel(ax.attributes("caption"), ax.attributes("label")); } - } - } //end of NOT an event ------------------------------- - - - //Units - bool verticalHistogram(false); - try - { - local_workspace->getAxis(0)->unit() = UnitFactory::Instance().create(unit1); - if(unit1 == "Label") + //If this doesn't throw then it is a numeric access so grab the data so we can set it later + axis2.load(); + if (static_cast(axis2.size()) == nspectra + 1) + verticalHistogram = true; + m_axis1vals = MantidVec(axis2(), axis2() + axis2.dim0()); + } catch (std::runtime_error &) { - auto label = boost::dynamic_pointer_cast(local_workspace->getAxis(0)->unit()); - auto ax = wksp_cls.openNXDouble("axis1"); - label->setLabel(ax.attributes("caption"), ax.attributes("label")); + g_log.information() << "Axis 0 set to unitless quantity \"" << unit1 << "\"\n"; } - //If this doesn't throw then it is a numeric access so grab the data so we can set it later - axis2.load(); - if(static_cast(axis2.size()) == nspectra + 1) verticalHistogram = true; - m_axis1vals = MantidVec(axis2(), axis2() + axis2.dim0()); - } - catch( std::runtime_error & ) - { - g_log.information() << "Axis 0 set to unitless quantity \"" << unit1 << "\"\n"; - } - - // Setting a unit onto a TextAxis makes no sense. - if ( unit2 == "TextAxis" ) - { - Mantid::API::TextAxis* newAxis = new Mantid::API::TextAxis(nspectra); - local_workspace->replaceAxis(1, newAxis); - } - else if ( unit2 != "spectraNumber" ) - { - try + // Setting a unit onto a TextAxis makes no sense. + if (unit2 == "TextAxis") { - auto* newAxis = (verticalHistogram) ? new API::BinEdgeAxis(nspectra+1) : new API::NumericAxis(nspectra); + Mantid::API::TextAxis* newAxis = new Mantid::API::TextAxis(nspectra); local_workspace->replaceAxis(1, newAxis); - newAxis->unit() = UnitFactory::Instance().create(unit2); - if(unit2 == "Label") + } + else if (unit2 != "spectraNumber") + { + try { - auto label = boost::dynamic_pointer_cast(newAxis->unit()); - auto ax = wksp_cls.openNXDouble("axis2"); - label->setLabel(ax.attributes("caption"), ax.attributes("label")); + auto* newAxis = + (verticalHistogram) ? new API::BinEdgeAxis(nspectra + 1) : new API::NumericAxis(nspectra); + local_workspace->replaceAxis(1, newAxis); + newAxis->unit() = UnitFactory::Instance().create(unit2); + if (unit2 == "Label") + { + auto label = boost::dynamic_pointer_cast(newAxis->unit()); + auto ax = wksp_cls.openNXDouble("axis2"); + label->setLabel(ax.attributes("caption"), ax.attributes("label")); + } + } catch (std::runtime_error &) + { + g_log.information() << "Axis 1 set to unitless quantity \"" << unit2 << "\"\n"; } } - catch( std::runtime_error & ) + + //Are we a distribution + std::string dist = xbins.attributes("distribution"); + if (dist == "1") { - g_log.information() << "Axis 1 set to unitless quantity \"" << unit2 << "\"\n"; + local_workspace->isDistribution(true); } - } - - - //Are we a distribution - std::string dist = xbins.attributes("distribution"); - if( dist == "1" ) - { - local_workspace->isDistribution(true); - } - else - { - local_workspace->isDistribution(false); - } - - //Get information from all but data group - std::string parameterStr; - - progress(progressStart+0.05*progressRange,"Reading the sample details..."); - - // Hop to the right point - m_cppFile->openPath(mtd_entry.path()); - try - { - // This loads logs, sample, and instrument. - local_workspace->loadExperimentInfoNexus(m_cppFile, parameterStr); - } - catch (std::exception & e) - { - g_log.information("Error loading Instrument section of nxs file"); - g_log.information(e.what()); - } - - // Now assign the spectra-detector map - readInstrumentGroup(mtd_entry, local_workspace); - - // Parameter map parsing - progress(progressStart+0.11*progressRange,"Reading the parameter maps..."); - local_workspace->readParameterMap(parameterStr); - - - if ( ! local_workspace->getAxis(1)->isSpectra() ) - { // If not a spectra axis, load the axis data into the workspace. (MW 25/11/10) - loadNonSpectraAxis(local_workspace, wksp_cls); - } - - progress(progressStart+0.15*progressRange,"Reading the workspace history..."); - m_cppFile->openPath(mtd_entry.path()); - try - { - bool load_history = getProperty("LoadHistory"); - if (load_history) local_workspace->history().loadNexus(m_cppFile); - } - catch (std::out_of_range&) - { - g_log.warning() << "Error in the workspaces algorithm list, its processing history is incomplete\n"; - } - - progress(progressStart+0.2*progressRange,"Reading the workspace history..."); - - return boost::static_pointer_cast(local_workspace); -} - -typedef boost::shared_array IntArray_shared; -struct SpectraInfo -{ - // Number of spectra - const int nSpectra; - // Do we have any spectra - const bool hasSpectra; - // Contains spectrum numbers for each workspace index - const IntArray_shared spectraNumbers; - // Index of the detector in the workspace. - const IntArray_shared detectorIndex; - // Number of detectors associated with each spectra - const IntArray_shared detectorCount; - // Detector list contains a list of all of the detector numbers - const IntArray_shared detectorList; - - SpectraInfo() : - nSpectra(0), hasSpectra(false) - { - } - - SpectraInfo(int _nSpectra, bool _hasSpectra, IntArray_shared _spectraNumbers - , IntArray_shared _detectorIndex - , IntArray_shared _detectorCount - , IntArray_shared _detectorList) - : - nSpectra(_nSpectra), hasSpectra(_hasSpectra), - spectraNumbers(_spectraNumbers), detectorIndex(_detectorIndex), - detectorCount(_detectorCount), detectorList(_detectorList) - { - } -}; - - -SpectraInfo doReadInstrumentGroup(NXEntry & mtd_entry, Logger& logger) -{ - //Instrument information - NXInstrument inst = mtd_entry.openNXInstrument("instrument"); - if ( ! inst.containsGroup("detector") ) + else { - logger.information() << "Detector block not found. The workspace will not contain any detector information.\n"; - return SpectraInfo(); + local_workspace->isDistribution(false); } - //Populate the spectra-detector map - NXDetector detgroup = inst.openNXDetector("detector"); + //Get information from all but data group + std::string parameterStr; + + progress(progressStart + 0.05 * progressRange, "Reading the sample details..."); - //Read necessary arrays from the file - // Detector list contains a list of all of the detector numbers. If it not present then we can't update the spectra - // map - boost::shared_array detectorList; + // Hop to the right point + m_cppFile->openPath(mtd_entry.path()); try { - NXInt detlist_group = detgroup.openNXInt("detector_list"); - detlist_group.load(); - detectorList = detlist_group.sharedBuffer(); - } - catch(std::runtime_error &) + // This loads logs, sample, and instrument. + local_workspace->loadExperimentInfoNexus(m_cppFile, parameterStr); + } catch (std::exception & e) { - logger.information() << "detector_list block not found. The workspace will not contain any detector information." - << std::endl; - return SpectraInfo(); + g_log.information("Error loading Instrument section of nxs file"); + g_log.information(e.what()); + } + + // Now assign the spectra-detector map + readInstrumentGroup(mtd_entry, local_workspace); + + // Parameter map parsing + progress(progressStart + 0.11 * progressRange, "Reading the parameter maps..."); + local_workspace->readParameterMap(parameterStr); + + if (!local_workspace->getAxis(1)->isSpectra()) + { // If not a spectra axis, load the axis data into the workspace. (MW 25/11/10) + loadNonSpectraAxis(local_workspace, wksp_cls); } - //Detector count contains the number of detectors associated with each spectra - NXInt det_count = detgroup.openNXInt("detector_count"); - det_count.load(); - boost::shared_array detectorCount = det_count.sharedBuffer(); - //Detector index - contains the index of the detector in the workspace - NXInt det_index = detgroup.openNXInt("detector_index"); - det_index.load(); - int nspectra = det_index.dim0(); - boost::shared_array detectorIndex = det_index.sharedBuffer(); - - //Spectra block - Contains spectrum numbers for each workspace index - // This might not exist so wrap and check. If it doesn't exist create a default mapping - bool have_spectra(true); - boost::shared_array spectra; + progress(progressStart + 0.15 * progressRange, "Reading the workspace history..."); + m_cppFile->openPath(mtd_entry.path()); try { - NXInt spectra_block = detgroup.openNXInt("spectra"); - spectra_block.load(); - spectra = spectra_block.sharedBuffer(); - } - catch(std::runtime_error &) + bool load_history = getProperty("LoadHistory"); + if (load_history) + local_workspace->history().loadNexus(m_cppFile); + } catch (std::out_of_range&) { - have_spectra = false; + g_log.warning() + << "Error in the workspaces algorithm list, its processing history is incomplete\n"; } - return SpectraInfo(nspectra, have_spectra, spectra, detectorIndex, detectorCount, detectorList); - -}; + progress(progressStart + 0.2 * progressRange, "Reading the workspace history..."); + return boost::static_pointer_cast(local_workspace); + } //------------------------------------------------------------------------------------------------- -/** - * Read the instrument group - * @param mtd_entry :: The node for the current workspace - * @param local_workspace :: The workspace to attach the instrument - */ -void LoadNexusProcessed::readInstrumentGroup(NXEntry & mtd_entry, API::MatrixWorkspace_sptr local_workspace) -{ - // Get spectrum information for the current entry. - SpectraInfo spectraInfo = doReadInstrumentGroup(mtd_entry, this->g_log); + /** + * Read the instrument group + * @param mtd_entry :: The node for the current workspace + * @param local_workspace :: The workspace to attach the instrument + */ + void LoadNexusProcessed::readInstrumentGroup(NXEntry & mtd_entry, + API::MatrixWorkspace_sptr local_workspace) + { + // Get spectrum information for the current entry. + SpectraInfo spectraInfo = extractMappingInfo(mtd_entry, this->g_log); - //Now build the spectra list - int index=0; + //Now build the spectra list + int index = 0; - for(int i = 1; i <= spectraInfo.nSpectra; ++i) - { + for (int i = 1; i <= spectraInfo.nSpectra; ++i) + { int spectrum(-1); - if( spectraInfo.hasSpectra ) + if (spectraInfo.hasSpectra) { - spectrum = spectraInfo.spectraNumbers[i-1]; + spectrum = spectraInfo.spectraNumbers[i - 1]; } else { - spectrum = i+1; + spectrum = i + 1; } - if ((i >= m_spec_min && i < m_spec_max )||(m_list && find(m_spec_list.begin(), m_spec_list.end(), - i) != m_spec_list.end())) + if ((i >= m_spec_min && i < m_spec_max) + || (m_list && find(m_spec_list.begin(), m_spec_list.end(), i) != m_spec_list.end())) { ISpectrum * spec = local_workspace->getSpectrum(index); - if( m_axis1vals.empty() ) + if (m_axis1vals.empty()) { spec->setSpectrumNo(spectrum); } else { - spec->setSpectrumNo(static_cast(m_axis1vals[i-1])); + spec->setSpectrumNo(static_cast(m_axis1vals[i - 1])); } ++index; - int start = spectraInfo.detectorIndex[i-1]; - int end = start + spectraInfo.detectorCount[i-1]; - spec->setDetectorIDs(std::set(spectraInfo.detectorList.get()+start,spectraInfo.detectorList.get()+end)); + int start = spectraInfo.detectorIndex[i - 1]; + int end = start + spectraInfo.detectorCount[i - 1]; + spec->setDetectorIDs( + std::set(spectraInfo.detectorList.get() + start, + spectraInfo.detectorList.get() + end)); } + } } -} - - //------------------------------------------------------------------------------------------------- -/** -* Loads the information contained in non-Spectra (ie, Text or Numeric) axis in the Nexus -* file into the workspace. -* @param local_workspace :: pointer to workspace object -* @param data :: reference to the NeXuS data for the axis -*/ -void LoadNexusProcessed::loadNonSpectraAxis(API::MatrixWorkspace_sptr local_workspace, NXData & data) -{ - Axis* axis = local_workspace->getAxis(1); - - if ( axis->isNumeric() ) + /** + * Loads the information contained in non-Spectra (ie, Text or Numeric) axis in the Nexus + * file into the workspace. + * @param local_workspace :: pointer to workspace object + * @param data :: reference to the NeXuS data for the axis + */ + void LoadNexusProcessed::loadNonSpectraAxis(API::MatrixWorkspace_sptr local_workspace, NXData & data) { - NXDouble axisData = data.openNXDouble("axis2"); - axisData.load(); - for ( int i = 0; i < static_cast(axis->length()); i++ ) + Axis* axis = local_workspace->getAxis(1); + + if (axis->isNumeric()) { - axis->setValue(i, axisData[i]); + NXDouble axisData = data.openNXDouble("axis2"); + axisData.load(); + for (int i = 0; i < static_cast(axis->length()); i++) + { + axis->setValue(i, axisData[i]); + } } - } - else if ( axis->isText() ) - { - NXChar axisData = data.openNXChar("axis2"); - axisData.load(); - std::string axisLabels = axisData(); - // Use boost::tokenizer to split up the input - boost::char_separator sep("\n"); - boost::tokenizer > tokenizer(axisLabels, sep); - // We must cast the axis object to TextAxis so we may use ->setLabel - TextAxis* textAxis = static_cast(axis); - int i = 0; - for ( auto tokIter = tokenizer.begin(); tokIter != tokenizer.end(); ++tokIter, ++i ) + else if (axis->isText()) { - textAxis->setLabel(i, *tokIter); + NXChar axisData = data.openNXChar("axis2"); + axisData.load(); + std::string axisLabels = axisData(); + // Use boost::tokenizer to split up the input + boost::char_separator sep("\n"); + boost::tokenizer > tokenizer(axisLabels, sep); + // We must cast the axis object to TextAxis so we may use ->setLabel + TextAxis* textAxis = static_cast(axis); + int i = 0; + for (auto tokIter = tokenizer.begin(); tokIter != tokenizer.end(); ++tokIter, ++i) + { + textAxis->setLabel(i, *tokIter); + } } } -} - - - -/** - * Binary predicate function object to sort the AlgorithmHistory vector by execution order - * @param elem1 :: first element in the vector - * @param elem2 :: second element in the vecor - */ -bool UDlesserExecCount(NXClassInfo elem1,NXClassInfo elem2) -{ - std::string::size_type index1, index2; - std::string num1,num2; - //find the number after "_" in algorithm name ( eg:MantidAlogorthm_1) - index1=elem1.nxname.find("_"); - if ( index1 != std::string::npos ) - { - num1=elem1.nxname.substr(index1+1,elem1.nxname.length()-index1); - } - index2=elem2.nxname.find("_"); - if ( index2 != std::string::npos ) + /** + * Binary predicate function object to sort the AlgorithmHistory vector by execution order + * @param elem1 :: first element in the vector + * @param elem2 :: second element in the vecor + */ + bool UDlesserExecCount(NXClassInfo elem1, NXClassInfo elem2) { - num2=elem2.nxname.substr(index2+1,elem2.nxname.length()-index2); - } - std::stringstream is1,is2; - is1<>execNum1; - is2>>execNum2; + int execNum1 = -1; + int execNum2 = -1; + is1 >> execNum1; + is2 >> execNum2; - if(execNum1flagMasked(si,bins[j],weights[j]); + int si = spec(i, 0); + int j0 = spec(i, 1); + int j1 = i < n1 ? spec(i + 1, 1) : bins.dim0(); + for (int j = j0; j < j1; ++j) + { + local_workspace->flagMasked(si, bins[j], weights[j]); + } } } -} - - - - - -/** - * Perform a call to nxgetslab, via the NexusClasses wrapped methods for a given blocksize. This assumes that the - * xbins have alread been cached - * @param data :: The NXDataSet object of y values - * @param errors :: The NXDataSet object of error values - * @param farea :: The NXDataSet object of fraction area values - * @param hasFArea :: Flag to signal a RebinnedOutput workspace is in use - * @param blocksize :: The blocksize to use - * @param nchannels :: The number of channels for the block - * @param hist :: The workspace index to start reading into - * @param local_workspace :: A pointer to the workspace - */ -void LoadNexusProcessed::loadBlock(NXDataSetTyped & data, - NXDataSetTyped & errors, - NXDataSetTyped & farea, - bool hasFArea, - int64_t blocksize, - int64_t nchannels, int64_t &hist, - API::MatrixWorkspace_sptr local_workspace) -{ - data.load(static_cast(blocksize),static_cast(hist)); - errors.load(static_cast(blocksize),static_cast(hist)); - double *data_start = data(); - double *data_end = data_start + nchannels; - double *err_start = errors(); - double *err_end = err_start + nchannels; - double *farea_start = NULL; - double *farea_end = NULL; - RebinnedOutput_sptr rb_workspace; - if (hasFArea) - { - farea.load(static_cast(blocksize),static_cast(hist)); - farea_start = farea(); - farea_end = farea_start + nchannels; - rb_workspace = boost::dynamic_pointer_cast(local_workspace); - } - int64_t final(hist + blocksize); - while( hist < final ) + /** + * Perform a call to nxgetslab, via the NexusClasses wrapped methods for a given blocksize. This assumes that the + * xbins have alread been cached + * @param data :: The NXDataSet object of y values + * @param errors :: The NXDataSet object of error values + * @param farea :: The NXDataSet object of fraction area values + * @param hasFArea :: Flag to signal a RebinnedOutput workspace is in use + * @param blocksize :: The blocksize to use + * @param nchannels :: The number of channels for the block + * @param hist :: The workspace index to start reading into + * @param local_workspace :: A pointer to the workspace + */ + void LoadNexusProcessed::loadBlock(NXDataSetTyped & data, NXDataSetTyped & errors, + NXDataSetTyped & farea, bool hasFArea, int64_t blocksize, int64_t nchannels, int64_t &hist, + API::MatrixWorkspace_sptr local_workspace) { - MantidVec& Y = local_workspace->dataY(hist); - Y.assign(data_start, data_end); - data_start += nchannels; data_end += nchannels; - MantidVec& E = local_workspace->dataE(hist); - E.assign(err_start, err_end); - err_start += nchannels; err_end += nchannels; + data.load(static_cast(blocksize), static_cast(hist)); + errors.load(static_cast(blocksize), static_cast(hist)); + double *data_start = data(); + double *data_end = data_start + nchannels; + double *err_start = errors(); + double *err_end = err_start + nchannels; + double *farea_start = NULL; + double *farea_end = NULL; + RebinnedOutput_sptr rb_workspace; if (hasFArea) { - MantidVec& F = rb_workspace->dataF(hist); - F.assign(farea_start, farea_end); - farea_start += nchannels; - farea_end += nchannels; + farea.load(static_cast(blocksize), static_cast(hist)); + farea_start = farea(); + farea_end = farea_start + nchannels; + rb_workspace = boost::dynamic_pointer_cast(local_workspace); + } + int64_t final(hist + blocksize); + while (hist < final) + { + MantidVec& Y = local_workspace->dataY(hist); + Y.assign(data_start, data_end); + data_start += nchannels; + data_end += nchannels; + MantidVec& E = local_workspace->dataE(hist); + E.assign(err_start, err_end); + err_start += nchannels; + err_end += nchannels; + if (hasFArea) + { + MantidVec& F = rb_workspace->dataF(hist); + F.assign(farea_start, farea_end); + farea_start += nchannels; + farea_end += nchannels; + } + local_workspace->setX(hist, m_xbins); + ++hist; } - local_workspace->setX(hist, m_xbins); - ++hist; - } -} - -/** - * Perform a call to nxgetslab, via the NexusClasses wrapped methods for a given blocksize. This assumes that the - * xbins have alread been cached - * @param data :: The NXDataSet object of y values - * @param errors :: The NXDataSet object of error values - * @param farea :: The NXDataSet object of fraction area values - * @param hasFArea :: Flag to signal a RebinnedOutput workspace is in use - * @param blocksize :: The blocksize to use - * @param nchannels :: The number of channels for the block - * @param hist :: The workspace index to start reading into - * @param wsIndex :: The workspace index to save data into - * @param local_workspace :: A pointer to the workspace - */ - -void LoadNexusProcessed::loadBlock(NXDataSetTyped & data, - NXDataSetTyped & errors, - NXDataSetTyped & farea, - bool hasFArea, - int64_t blocksize, int64_t nchannels, - int64_t &hist,int64_t& wsIndex, - API::MatrixWorkspace_sptr local_workspace) -{ - data.load(static_cast(blocksize),static_cast(hist)); - errors.load(static_cast(blocksize),static_cast(hist)); - double *data_start = data(); - double *data_end = data_start + nchannels; - double *err_start = errors(); - double *err_end = err_start + nchannels; - double *farea_start = NULL; - double *farea_end = NULL; - RebinnedOutput_sptr rb_workspace; - if (hasFArea) - { - farea.load(static_cast(blocksize),static_cast(hist)); - farea_start = farea(); - farea_end = farea_start + nchannels; - rb_workspace = boost::dynamic_pointer_cast(local_workspace); } - int64_t final(hist + blocksize); - while( hist < final ) + + /** + * Perform a call to nxgetslab, via the NexusClasses wrapped methods for a given blocksize. This assumes that the + * xbins have alread been cached + * @param data :: The NXDataSet object of y values + * @param errors :: The NXDataSet object of error values + * @param farea :: The NXDataSet object of fraction area values + * @param hasFArea :: Flag to signal a RebinnedOutput workspace is in use + * @param blocksize :: The blocksize to use + * @param nchannels :: The number of channels for the block + * @param hist :: The workspace index to start reading into + * @param wsIndex :: The workspace index to save data into + * @param local_workspace :: A pointer to the workspace + */ + + void LoadNexusProcessed::loadBlock(NXDataSetTyped & data, NXDataSetTyped & errors, + NXDataSetTyped & farea, bool hasFArea, int64_t blocksize, int64_t nchannels, int64_t &hist, + int64_t& wsIndex, API::MatrixWorkspace_sptr local_workspace) { - MantidVec& Y = local_workspace->dataY(wsIndex); - Y.assign(data_start, data_end); - data_start += nchannels; data_end += nchannels; - MantidVec& E = local_workspace->dataE(wsIndex); - E.assign(err_start, err_end); - err_start += nchannels; err_end += nchannels; + data.load(static_cast(blocksize), static_cast(hist)); + errors.load(static_cast(blocksize), static_cast(hist)); + double *data_start = data(); + double *data_end = data_start + nchannels; + double *err_start = errors(); + double *err_end = err_start + nchannels; + double *farea_start = NULL; + double *farea_end = NULL; + RebinnedOutput_sptr rb_workspace; if (hasFArea) { - MantidVec& F = rb_workspace->dataF(wsIndex); - F.assign(farea_start, farea_end); - farea_start += nchannels; - farea_end += nchannels; + farea.load(static_cast(blocksize), static_cast(hist)); + farea_start = farea(); + farea_end = farea_start + nchannels; + rb_workspace = boost::dynamic_pointer_cast(local_workspace); } - local_workspace->setX(wsIndex, m_xbins); - ++hist; - ++wsIndex; + int64_t final(hist + blocksize); + while (hist < final) + { + MantidVec& Y = local_workspace->dataY(wsIndex); + Y.assign(data_start, data_end); + data_start += nchannels; + data_end += nchannels; + MantidVec& E = local_workspace->dataE(wsIndex); + E.assign(err_start, err_end); + err_start += nchannels; + err_end += nchannels; + if (hasFArea) + { + MantidVec& F = rb_workspace->dataF(wsIndex); + F.assign(farea_start, farea_end); + farea_start += nchannels; + farea_end += nchannels; + } + local_workspace->setX(wsIndex, m_xbins); + ++hist; + ++wsIndex; + } } -} - -/** - * Perform a call to nxgetslab, via the NexusClasses wrapped methods for a given blocksize. The xbins are read along with - * each call to the data/error loading - * @param data :: The NXDataSet object of y values - * @param errors :: The NXDataSet object of error values - * @param farea :: The NXDataSet object of fraction area values - * @param hasFArea :: Flag to signal a RebinnedOutput workspace is in use - * @param xbins :: The xbin NXDataSet - * @param blocksize :: The blocksize to use - * @param nchannels :: The number of channels for the block - * @param hist :: The workspace index to start reading into - * @param wsIndex :: The workspace index to save data into - * @param local_workspace :: A pointer to the workspace - */ -void LoadNexusProcessed::loadBlock(NXDataSetTyped & data, - NXDataSetTyped & errors, - NXDataSetTyped & farea, - bool hasFArea, - NXDouble & xbins, - int64_t blocksize, int64_t nchannels, - int64_t &hist, int64_t& wsIndex, - API::MatrixWorkspace_sptr local_workspace) -{ - data.load(static_cast(blocksize),static_cast(hist)); - double *data_start = data(); - double *data_end = data_start + nchannels; - errors.load(static_cast(blocksize),static_cast(hist)); - double *err_start = errors(); - double *err_end = err_start + nchannels; - double *farea_start = NULL; - double *farea_end = NULL; - RebinnedOutput_sptr rb_workspace; - if (hasFArea) - { - farea.load(static_cast(blocksize),static_cast(hist)); - farea_start = farea(); - farea_end = farea_start + nchannels; - rb_workspace = boost::dynamic_pointer_cast(local_workspace); - } - xbins.load(static_cast(blocksize),static_cast(hist)); - const int64_t nxbins(nchannels + 1); - double *xbin_start = xbins(); - double *xbin_end = xbin_start + nxbins; - int64_t final(hist + blocksize); - while( hist < final ) + + /** + * Perform a call to nxgetslab, via the NexusClasses wrapped methods for a given blocksize. The xbins are read along with + * each call to the data/error loading + * @param data :: The NXDataSet object of y values + * @param errors :: The NXDataSet object of error values + * @param farea :: The NXDataSet object of fraction area values + * @param hasFArea :: Flag to signal a RebinnedOutput workspace is in use + * @param xbins :: The xbin NXDataSet + * @param blocksize :: The blocksize to use + * @param nchannels :: The number of channels for the block + * @param hist :: The workspace index to start reading into + * @param wsIndex :: The workspace index to save data into + * @param local_workspace :: A pointer to the workspace + */ + void LoadNexusProcessed::loadBlock(NXDataSetTyped & data, NXDataSetTyped & errors, + NXDataSetTyped & farea, bool hasFArea, NXDouble & xbins, int64_t blocksize, + int64_t nchannels, int64_t &hist, int64_t& wsIndex, API::MatrixWorkspace_sptr local_workspace) { - MantidVec& Y = local_workspace->dataY(wsIndex); - Y.assign(data_start, data_end); - data_start += nchannels; data_end += nchannels; - MantidVec& E = local_workspace->dataE(wsIndex); - E.assign(err_start, err_end); - err_start += nchannels; err_end += nchannels; + data.load(static_cast(blocksize), static_cast(hist)); + double *data_start = data(); + double *data_end = data_start + nchannels; + errors.load(static_cast(blocksize), static_cast(hist)); + double *err_start = errors(); + double *err_end = err_start + nchannels; + double *farea_start = NULL; + double *farea_end = NULL; + RebinnedOutput_sptr rb_workspace; if (hasFArea) { - MantidVec& F = rb_workspace->dataF(wsIndex); - F.assign(farea_start, farea_end); - farea_start += nchannels; - farea_end += nchannels; + farea.load(static_cast(blocksize), static_cast(hist)); + farea_start = farea(); + farea_end = farea_start + nchannels; + rb_workspace = boost::dynamic_pointer_cast(local_workspace); } - MantidVec& X = local_workspace->dataX(wsIndex); - X.assign(xbin_start, xbin_end); - xbin_start += nxbins; xbin_end += nxbins; - ++hist; - ++wsIndex; - } -} - - -/** - *Validates the optional 'spectra to read' properties, if they have been set - * @param numberofspectra :: number of spectrum - */ -void LoadNexusProcessed::checkOptionalProperties(const std::size_t numberofspectra ) -{ - //read in the settings passed to the algorithm - m_spec_list = getProperty("SpectrumList"); - m_spec_max = getProperty("SpectrumMax"); - m_spec_min = getProperty("SpectrumMin"); - //Are we using a list of spectra or all the spectra in a range? - m_list = !m_spec_list.empty(); - m_interval = (m_spec_max != Mantid::EMPTY_INT()) || (m_spec_min != 1); - if ( m_spec_max == Mantid::EMPTY_INT() ) m_spec_max = 1; - - // Check validity of spectra list property, if set - if (m_list) - { - m_list = true; - const int64_t minlist = *min_element(m_spec_list.begin(), m_spec_list.end()); - const int64_t maxlist = *max_element(m_spec_list.begin(), m_spec_list.end()); - if (maxlist > static_cast(numberofspectra) || minlist == 0) + xbins.load(static_cast(blocksize), static_cast(hist)); + const int64_t nxbins(nchannels + 1); + double *xbin_start = xbins(); + double *xbin_end = xbin_start + nxbins; + int64_t final(hist + blocksize); + while (hist < final) { - g_log.error("Invalid list of spectra"); - throw std::invalid_argument("Inconsistent properties defined"); + MantidVec& Y = local_workspace->dataY(wsIndex); + Y.assign(data_start, data_end); + data_start += nchannels; + data_end += nchannels; + MantidVec& E = local_workspace->dataE(wsIndex); + E.assign(err_start, err_end); + err_start += nchannels; + err_end += nchannels; + if (hasFArea) + { + MantidVec& F = rb_workspace->dataF(wsIndex); + F.assign(farea_start, farea_end); + farea_start += nchannels; + farea_end += nchannels; + } + MantidVec& X = local_workspace->dataX(wsIndex); + X.assign(xbin_start, xbin_end); + xbin_start += nxbins; + xbin_end += nxbins; + ++hist; + ++wsIndex; } } - // Check validity of spectra range, if set - if (m_interval) + /** + *Validates the optional 'spectra to read' properties, if they have been set + * @param numberofspectra :: number of spectrum + */ + void LoadNexusProcessed::checkOptionalProperties(const std::size_t numberofspectra) { - m_interval = true; + //read in the settings passed to the algorithm + m_spec_list = getProperty("SpectrumList"); + m_spec_max = getProperty("SpectrumMax"); m_spec_min = getProperty("SpectrumMin"); - if (m_spec_min != 1 && m_spec_max == 1) - { - m_spec_max = numberofspectra; - } - if (m_spec_max < m_spec_min || m_spec_max > static_cast(numberofspectra)) + //Are we using a list of spectra or all the spectra in a range? + m_list = !m_spec_list.empty(); + m_interval = (m_spec_max != Mantid::EMPTY_INT()) || (m_spec_min != 1); + if (m_spec_max == Mantid::EMPTY_INT()) + m_spec_max = 1; + + // Check validity of spectra list property, if set + if (m_list) { - g_log.error("Invalid Spectrum min/max properties"); - throw std::invalid_argument("Inconsistent properties defined"); + m_list = true; + const int64_t minlist = *min_element(m_spec_list.begin(), m_spec_list.end()); + const int64_t maxlist = *max_element(m_spec_list.begin(), m_spec_list.end()); + if (maxlist > static_cast(numberofspectra) || minlist == 0) + { + g_log.error("Invalid list of spectra"); + throw std::invalid_argument("Inconsistent properties defined"); + } } - } -} - -/** - * Calculate the size of a workspace - * @param numberofspectra :: number of spectrums - * @return the size of a workspace - */ -size_t LoadNexusProcessed::calculateWorkspacesize(const std::size_t numberofspectra) -{ - // Calculate the size of a workspace, given its number of spectra to read - int total_specs; - if( m_interval || m_list) - { + + // Check validity of spectra range, if set if (m_interval) { + m_interval = true; + m_spec_min = getProperty("SpectrumMin"); if (m_spec_min != 1 && m_spec_max == 1) { m_spec_max = numberofspectra; } - total_specs = static_cast(m_spec_max-m_spec_min+1); - m_spec_max += 1; + if (m_spec_max < m_spec_min || m_spec_max > static_cast(numberofspectra)) + { + g_log.error("Invalid Spectrum min/max properties"); + throw std::invalid_argument("Inconsistent properties defined"); + } } - else - total_specs = 0; + } - if (m_list) + /** + * Calculate the size of a workspace + * @param numberofspectra :: number of spectrums + * @return the size of a workspace + */ + size_t LoadNexusProcessed::calculateWorkspacesize(const std::size_t numberofspectra) + { + // Calculate the size of a workspace, given its number of spectra to read + int total_specs; + if (m_interval || m_list) { if (m_interval) { - for(std::vector::iterator it=m_spec_list.begin();it!=m_spec_list.end();) - if (*it >= m_spec_min && *it (m_spec_max - m_spec_min + 1); + m_spec_max += 1; + } + else + total_specs = 0; + + if (m_list) + { + if (m_interval) + { + for (std::vector::iterator it = m_spec_list.begin(); it != m_spec_list.end();) + if (*it >= m_spec_min && *it < m_spec_max) + { + it = m_spec_list.erase(it); + } + else + ++it; + } + if (m_spec_list.size() == 0) + m_list = false; + total_specs += static_cast(m_spec_list.size()); } - if (m_spec_list.size() == 0) m_list = false; - total_specs += static_cast(m_spec_list.size()); } + else + { + total_specs = static_cast(numberofspectra); + m_spec_min = 1; + m_spec_max = static_cast(numberofspectra) + 1; + } + return total_specs; } - else - { - total_specs = static_cast(numberofspectra); - m_spec_min = 1; - m_spec_max = static_cast(numberofspectra) +1; - } - return total_specs; -} } // namespace DataHandling } // namespace Mantid