diff --git a/Framework/DataHandling/src/LoadEventNexus.cpp b/Framework/DataHandling/src/LoadEventNexus.cpp index 836daa31cb45e310a0b67f09f3c45f21dcf105be..1b50f4cdca07dcf290ebbae5fdb3a60d461ee786 100644 --- a/Framework/DataHandling/src/LoadEventNexus.cpp +++ b/Framework/DataHandling/src/LoadEventNexus.cpp @@ -646,12 +646,19 @@ void LoadEventNexus::loadEvents(API::Progress *const prog, if (!m_ws->getInstrument() || !m_instrument_loaded_correctly) { // Load the instrument (if not loaded before) prog->report("Loading instrument"); + // Note that closing an re-opening the file is needed here for loading + // instruments directly from the nexus file containing the event data. + // This may not be needed in the future if both LoadEventNexus and + // LoadInstrument are made to use the same Nexus/HDF5 library + m_file->close(); m_instrument_loaded_correctly = loadInstrument(m_filename, m_ws, m_top_entry_name, this); if (!m_instrument_loaded_correctly) throw std::runtime_error( "Instrument was not initialized correctly! Loading cannot continue."); + // reopen file + safeOpenFile(m_filename); } // top level file information diff --git a/Framework/NexusGeometry/src/NexusGeometryParser.cpp b/Framework/NexusGeometry/src/NexusGeometryParser.cpp index 2e9fb18a27d594cb6108981647d230acda6bd8cd..7288af47fcd6320388aae5425c2fe24255dae614 100644 --- a/Framework/NexusGeometry/src/NexusGeometryParser.cpp +++ b/Framework/NexusGeometry/src/NexusGeometryParser.cpp @@ -154,8 +154,7 @@ std::string get1DStringDataset(const std::string &dataset, const Group &group) { * size 1. */ std::vector<Group> openSubGroups(const Group &parentGroup, - const H5std_string &CLASS_TYPE, - const bool firstEntryOnly = false) { + const H5std_string &CLASS_TYPE) { std::vector<Group> subGroups; // Iterate over children, and determine if a group for (hsize_t i = 0; i < parentGroup.getNumObjs(); ++i) { @@ -178,8 +177,6 @@ std::vector<Group> openSubGroups(const Group &parentGroup, // If group of correct type, append to subGroup vector if (classType == CLASS_TYPE) { subGroups.push_back(childGroup); - if (firstEntryOnly) - return subGroups; } } } @@ -188,11 +185,45 @@ std::vector<Group> openSubGroups(const Group &parentGroup, return subGroups; } +/// Find a single group inside parent (returns first match) +// TODO: refactor most of this and openSubGroups() to avoid duplication +Group findGroup(const Group &parentGroup, const H5std_string &CLASS_TYPE) { + Group childGroup; + // Iterate over children, and determine if a group + for (hsize_t i = 0; i < parentGroup.getNumObjs(); ++i) { + if (parentGroup.getObjTypeByIdx(i) == GROUP_TYPE) { + H5std_string childPath = parentGroup.getObjnameByIdx(i); + // Open the sub group + childGroup = parentGroup.openGroup(childPath); + // Iterate through attributes to find NX_class + for (uint32_t attribute_index = 0; + attribute_index < static_cast<uint32_t>(childGroup.getNumAttrs()); + ++attribute_index) { + // Test attribute at current index for NX_class + Attribute attribute = childGroup.openAttribute(attribute_index); + if (attribute.getName() == NX_CLASS) { + // Get attribute data type + DataType dataType = attribute.getDataType(); + // Get the NX_class type + H5std_string classType; + attribute.read(dataType, classType); + // If group of correct type, return the childGroup + if (classType == CLASS_TYPE) { + return childGroup; + } + } + } + } + } + // TODO: would maybe be better to return boost::optional? + return childGroup; +} + // Get the instrument name std::string instrumentName(const Group &root) { - std::vector<Group> instrumentGroup = openSubGroups( - openSubGroups(root, NX_ENTRY, true)[0], NX_INSTRUMENT, true); - return get1DStringDataset("name", instrumentGroup[0]); + Group entryGroup = findGroup(root, NX_ENTRY); + Group instrumentGroup = findGroup(entryGroup, NX_INSTRUMENT); + return get1DStringDataset("name", instrumentGroup); } // Open all detector groups into a vector @@ -572,12 +603,11 @@ parseNexusShape(const Group &detectorGroup, bool &searchTubes) { void parseAndAddSource(const H5File &file, const Group &root, InstrumentBuilder &builder) { H5std_string sourcePath = "source"; - std::vector<Group> sourceGroup = - openSubGroups(openSubGroups(openSubGroups(root, NX_ENTRY, true)[0], - NX_INSTRUMENT, true)[0], - sourcePath, true); - auto sourceName = get1DStringDataset("name", sourceGroup[0]); - auto sourceTransformations = getTransformations(file, sourceGroup[0]); + Group entryGroup = findGroup(root, NX_ENTRY); + Group instrumentGroup = findGroup(entryGroup, NX_INSTRUMENT); + Group sourceGroup = findGroup(instrumentGroup, sourcePath); + auto sourceName = get1DStringDataset("name", sourceGroup); + auto sourceTransformations = getTransformations(file, sourceGroup); auto defaultPos = Eigen::Vector3d(0.0, 0.0, 0.0); builder.addSource(sourceName, sourceTransformations * defaultPos); } @@ -587,9 +617,9 @@ void parseAndAddSample(const H5File &file, const Group &root, InstrumentBuilder &builder) { std::string sampleName = "sample"; H5std_string samplePath = sampleName; - std::vector<Group> sampleGroup = - openSubGroups(openSubGroups(root, NX_ENTRY, true)[0], samplePath, true); - auto sampleTransforms = getTransformations(file, sampleGroup[0]); + Group entryGroup = findGroup(root, NX_ENTRY); + Group sampleGroup = findGroup(entryGroup, samplePath); + auto sampleTransforms = getTransformations(file, sampleGroup); Eigen::Vector3d samplePos = sampleTransforms * Eigen::Vector3d(0.0, 0.0, 0.0); builder.addSample(sampleName, samplePos); }