diff --git a/CMakeLists.txt b/CMakeLists.txt index 4ad99f6237..e9fd0c7321 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -455,9 +455,11 @@ set(SIMPLNX_HDRS ${SIMPLNX_SOURCE_DIR}/DataStructure/DataStructure.hpp ${SIMPLNX_SOURCE_DIR}/DataStructure/DynamicListArray.hpp ${SIMPLNX_SOURCE_DIR}/DataStructure/EmptyDataStore.hpp + ${SIMPLNX_SOURCE_DIR}/DataStructure/EmptyListStore.hpp ${SIMPLNX_SOURCE_DIR}/DataStructure/IArray.hpp ${SIMPLNX_SOURCE_DIR}/DataStructure/IDataArray.hpp ${SIMPLNX_SOURCE_DIR}/DataStructure/IDataStore.hpp + ${SIMPLNX_SOURCE_DIR}/DataStructure/IListStore.hpp ${SIMPLNX_SOURCE_DIR}/DataStructure/INeighborList.hpp ${SIMPLNX_SOURCE_DIR}/DataStructure/LinkedPath.hpp ${SIMPLNX_SOURCE_DIR}/DataStructure/Metadata.hpp diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/LaplacianSmoothing.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/LaplacianSmoothing.cpp index fae7bf6b27..0e21f80284 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/LaplacianSmoothing.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/LaplacianSmoothing.cpp @@ -30,6 +30,11 @@ Result<> LaplacianSmoothing::edgeBasedSmoothing() { auto& surfaceMesh = m_DataStructure.getDataRefAs(m_InputValues->pTriangleGeometryDataPath); + if(surfaceMesh.getVertices() == nullptr) + { + return MakeErrorResult(-559, "Error finding TriangleGeom vertices."); + } + Float32AbstractDataStore& verts = surfaceMesh.getVertices()->getDataStoreRef(); IGeometry::MeshIndexType nvert = surfaceMesh.getNumberOfVertices(); diff --git a/src/simplnx/DataStructure/AbstractDataStore.hpp b/src/simplnx/DataStructure/AbstractDataStore.hpp index 12f657c93f..1948effc8e 100644 --- a/src/simplnx/DataStructure/AbstractDataStore.hpp +++ b/src/simplnx/DataStructure/AbstractDataStore.hpp @@ -6,7 +6,6 @@ #include "simplnx/Common/TypesUtility.hpp" #include "simplnx/DataStructure/DataObject.hpp" #include "simplnx/DataStructure/IDataStore.hpp" -#include "simplnx/Utilities/Parsing/HDF5/IO/DatasetIO.hpp" #include @@ -18,6 +17,11 @@ namespace nx::core { +namespace HDF5 +{ +class DatasetIO; +} + /** * @class AbstractDataStore * @brief The AbstractDataStore class serves as an interface class for the diff --git a/src/simplnx/DataStructure/AbstractListStore.hpp b/src/simplnx/DataStructure/AbstractListStore.hpp index 1319a04933..517507d9d9 100644 --- a/src/simplnx/DataStructure/AbstractListStore.hpp +++ b/src/simplnx/DataStructure/AbstractListStore.hpp @@ -1,6 +1,7 @@ #pragma once #include "simplnx/Common/Types.hpp" +#include "simplnx/DataStructure/IListStore.hpp" #include #include @@ -11,7 +12,7 @@ namespace nx::core { template -class AbstractListStore +class AbstractListStore : public IListStore { public: ///////////////////////////////// @@ -536,31 +537,10 @@ class AbstractListStore using reference = value_type&; using const_reference = const value_type&; - virtual ~AbstractListStore() = default; + ~AbstractListStore() override = default; virtual std::unique_ptr deepCopy() const = 0; - /** - * @brief This method sets the shape of the dimensions to `tupleShape`. - * - * There are 3 possibilities when using this function: - * [1] The number of tuples of the new shape is *LESS* than the original. In this - * case a memory allocation will take place and the first 'N' elements of data - * will be copied into the new array. The remaining data is *LOST* - * - * [2] The number of tuples of the new shape is *EQUAL* to the original. In this - * case the shape is set and the function returns. - * - * [3] The number of tuples of the new shape is *GREATER* than the original. In - * this case a new array is allocated and all the data from the original array - * is copied into the new array and the remaining elements are initialized to - * the default initialization value. - * - * @param tupleShape The new shape of the data where the dimensions are "C" ordered - * from *slowest* to *fastest*. - */ - virtual void resizeTuples(usize tupleCount) = 0; - /** * @brief addEntry * @param grainId @@ -568,11 +548,6 @@ class AbstractListStore */ virtual void addEntry(int32 grainId, value_type value) = 0; - /** - * @brief Clear All Lists - */ - virtual void clearAllLists() = 0; - /** * @brief setList * @param grainId @@ -594,8 +569,6 @@ class AbstractListStore */ virtual vector_type getList(int32 grainId) const = 0; - virtual usize getListSize(usize grainId) const = 0; - /** * @brief copyOfList * @param grainId @@ -614,17 +587,6 @@ class AbstractListStore virtual void setValue(int32 grainId, usize index, T value) = 0; - /** - * @brief getNumberOfLists - * @return int32 - */ - virtual uint64 getNumberOfLists() const = 0; - - uint64 size() const - { - return getNumberOfLists(); - } - /** * @brief operator [] * @param grainId @@ -683,11 +645,6 @@ class AbstractListStore return const_iterator(*this, size()); } - /** - * @brief Clears the array. - */ - virtual void clear() = 0; - virtual void setData(const std::vector& lists) = 0; virtual void setData(const std::vector& lists) = 0; diff --git a/src/simplnx/DataStructure/DataStore.hpp b/src/simplnx/DataStructure/DataStore.hpp index a130daa7d8..2f5d780d76 100644 --- a/src/simplnx/DataStructure/DataStore.hpp +++ b/src/simplnx/DataStructure/DataStore.hpp @@ -1,6 +1,7 @@ #pragma once #include "simplnx/DataStructure/AbstractDataStore.hpp" +#include "simplnx/Utilities/Parsing/HDF5/IO/DatasetIO.hpp" #include #include diff --git a/src/simplnx/DataStructure/EmptyListStore.hpp b/src/simplnx/DataStructure/EmptyListStore.hpp new file mode 100644 index 0000000000..e6ba5f20df --- /dev/null +++ b/src/simplnx/DataStructure/EmptyListStore.hpp @@ -0,0 +1,213 @@ +#pragma once + +#include "AbstractListStore.hpp" + +#include "simplnx/Utilities/Parsing/HDF5/IO/DatasetIO.hpp" + +namespace nx::core +{ +template +class EmptyListStore : public AbstractListStore +{ +public: + using shape_type = typename std::vector; + using value_type = T; + using parent_type = AbstractListStore; + using vector_type = typename parent_type::vector_type; + using shared_vector_type = typename parent_type::shared_vector_type; + + EmptyListStore() = default; + /** + * @brief Constructs a ListStore using the specified tuple shape and list size. + * @param tupleShape + * @param listSize + */ + EmptyListStore(usize numTuples) + : AbstractListStore() + , m_NumTuples(numTuples) + { + } + + EmptyListStore(const EmptyListStore& rhs) = default; + EmptyListStore(EmptyListStore&& rhs) = default; + + ~EmptyListStore() override = default; + + /** + * @brief Returns a copy of the current list store. + * @return std::unique> + */ + std::unique_ptr deepCopy() const override + { + return std::make_unique(*this); + } + + /** + * @brief addEntry + * @param grainId + * @param value + */ + void addEntry(int32 grainId, value_type value) override + { + throw std::runtime_error("EmptyListStore cannot add values to list"); + } + + void resizeTuples(usize tupleCount) override + { + m_NumTuples = tupleCount; + } + + void clear() override + { + m_NumTuples = 0; + } + + /** + * @brief Clear All Lists + */ + void clearAllLists() override + { + m_NumTuples = 0; + } + + uint64 getNumberOfLists() const override + { + return m_NumTuples; + } + + /** + * @brief getList + * @param grainId + * @return shared_vector_type + */ + vector_type getList(int32 grainId) const override + { + return {}; + } + + /** + * @brief copyOfList + * @param grainId + * @return vector_type + */ + vector_type copyOfList(int32 grainId) const override + { + return {}; + } + + /** + * @brief setList + * @param grainId + * @param neighborList + */ + void setList(int32 grainId, const shared_vector_type& neighborList) override + { + throw std::runtime_error("EmptyListStore cannot set list values"); + } + + /** + * @brief setList + * @param grainId + * @param neighborList + */ + void setList(int32 grainId, const vector_type& neighborList) override + { + throw std::runtime_error("EmptyListStore cannot set list values"); + } + + usize getListSize(usize grainId) const override + { + return 0; + } + + /** + * @brief getValue + * @param grainId + * @param index + * @param ok + * @return T + */ + T getValue(int32 grainId, int32 index, bool& ok) const override + { + throw std::runtime_error("EmptyListStore cannot get list value"); + } + + void setValue(int32 grainId, usize index, T value) override + { + throw std::runtime_error("EmptyListStore cannot set list value"); + } + + /** + * @brief operator [] + * @param grainId + * @return vector_type& + */ + vector_type operator[](int32 grainId) const override + { + throw std::runtime_error("EmptyListStore cannot get list"); + } + + /** + * @brief operator [] + * @param grainId + * @return vector_type& + */ + vector_type operator[](usize grainId) const override + { + throw std::runtime_error("EmptyListStore cannot get list"); + } + + /** + * @brief Returns a const reference to the vector_type value found at the specified index. This cannot be used to edit the vector_type value found at the specified index. + * @param grainId + * @return vector_type + */ + vector_type at(int32 grainId) const override + { + throw std::runtime_error("EmptyListStore cannot get list"); + } + + /** + * @brief Returns a const reference to the vector_type value found at the specified index. This cannot be used to edit the vector_type value found at the specified index. + * @param grainId + * @return vector_type + */ + vector_type at(usize grainId) const override + { + throw std::runtime_error("EmptyListStore cannot get list"); + } + + void setData(const std::vector& lists) override + { + throw std::runtime_error("EmptyListStore cannot set lists"); + } + + void setData(const std::vector& lists) override + { + throw std::runtime_error("EmptyListStore cannot set lists"); + } + + void readHdf5(const HDF5::DatasetIO& datasetReader) override + { + auto tupleDimsResult = datasetReader.readVectorAttribute("TupleDimensions"); + if(tupleDimsResult.invalid()) + { + clear(); + } + else + { + std::vector tupleDims = tupleDimsResult.value(); + uint64 numTuples = std::accumulate(tupleDims.begin(), tupleDims.end(), static_cast(1), std::multiplies<>()); + resizeTuples(numTuples); + } + } + + void writeHdf5(HDF5::DatasetIO& datasetReader) override + { + throw std::runtime_error("EmptyListStore cannot write to HDF5"); + } + +private: + usize m_NumTuples = 0; +}; +} // namespace nx::core diff --git a/src/simplnx/DataStructure/IListStore.hpp b/src/simplnx/DataStructure/IListStore.hpp new file mode 100644 index 0000000000..e0e2b0bca6 --- /dev/null +++ b/src/simplnx/DataStructure/IListStore.hpp @@ -0,0 +1,69 @@ +#pragma once + +#include "simplnx/Common/Types.hpp" + +namespace nx::core +{ +namespace HDF5 +{ +class DatasetIO; +} + +class IListStore +{ +public: + virtual ~IListStore() = default; + + /** + * @brief This method sets the shape of the dimensions to `tupleShape`. + * + * There are 3 possibilities when using this function: + * [1] The number of tuples of the new shape is *LESS* than the original. In this + * case a memory allocation will take place and the first 'N' elements of data + * will be copied into the new array. The remaining data is *LOST* + * + * [2] The number of tuples of the new shape is *EQUAL* to the original. In this + * case the shape is set and the function returns. + * + * [3] The number of tuples of the new shape is *GREATER* than the original. In + * this case a new array is allocated and all the data from the original array + * is copied into the new array and the remaining elements are initialized to + * the default initialization value. + * + * @param tupleShape The new shape of the data where the dimensions are "C" ordered + * from *slowest* to *fastest*. + */ + virtual void resizeTuples(usize tupleCount) = 0; + + /** + * @brief Clear All Lists + */ + virtual void clearAllLists() = 0; + + virtual usize getListSize(usize grainId) const = 0; + + /** + * @brief getNumberOfLists + * @return int32 + */ + virtual uint64 getNumberOfLists() const = 0; + + uint64 size() const + { + return getNumberOfLists(); + } + + /** + * @brief Clears the array. + */ + virtual void clear() = 0; + + virtual void readHdf5(const HDF5::DatasetIO& datasetReader) = 0; + virtual void writeHdf5(HDF5::DatasetIO& datasetReader) = 0; + +protected: + IListStore() = default; + IListStore(const IListStore& rhs) = default; + IListStore(IListStore&& rhs) = default; +}; +} // namespace nx::core diff --git a/src/simplnx/DataStructure/IO/Generic/CoreDataIOManager.cpp b/src/simplnx/DataStructure/IO/Generic/CoreDataIOManager.cpp index 4746130f21..0e08973b2d 100644 --- a/src/simplnx/DataStructure/IO/Generic/CoreDataIOManager.cpp +++ b/src/simplnx/DataStructure/IO/Generic/CoreDataIOManager.cpp @@ -1,6 +1,7 @@ #include "CoreDataIOManager.hpp" #include "simplnx/DataStructure/DataStore.hpp" +#include "simplnx/DataStructure/ListStore.hpp" namespace nx::core::Generic { @@ -9,6 +10,7 @@ CoreDataIOManager::CoreDataIOManager() { addCoreFactories(); addDataStoreFnc(); + addListStoreFnc(); } CoreDataIOManager::~CoreDataIOManager() noexcept = default; @@ -67,4 +69,49 @@ void CoreDataIOManager::addDataStoreFnc() }; addDataStoreCreationFnc(formatName(), dataStoreFnc); } + +void CoreDataIOManager::addListStoreFnc() +{ + ListStoreCreateFnc listStoreFnc = [](nx::core::DataType numericType, usize tupleCount) { + std::unique_ptr listStore = nullptr; + switch(numericType) + { + case DataType::int8: + listStore = std::make_unique(tupleCount); + break; + case DataType::int16: + listStore = std::make_unique(tupleCount); + break; + case DataType::int32: + listStore = std::make_unique(tupleCount); + break; + case DataType::int64: + listStore = std::make_unique(tupleCount); + break; + case DataType::uint8: + listStore = std::make_unique(tupleCount); + break; + case DataType::uint16: + listStore = std::make_unique(tupleCount); + break; + case DataType::uint32: + listStore = std::make_unique(tupleCount); + break; + case DataType::uint64: + listStore = std::make_unique(tupleCount); + break; + case DataType::float32: + listStore = std::make_unique(tupleCount); + break; + case DataType::float64: + listStore = std::make_unique(tupleCount); + break; + case DataType::boolean: + listStore = nullptr; + break; + } + return listStore; + }; + addListStoreCreationFnc(formatName(), listStoreFnc); +} } // namespace nx::core::Generic diff --git a/src/simplnx/DataStructure/IO/Generic/CoreDataIOManager.hpp b/src/simplnx/DataStructure/IO/Generic/CoreDataIOManager.hpp index 2ec709a0b5..557b74f87c 100644 --- a/src/simplnx/DataStructure/IO/Generic/CoreDataIOManager.hpp +++ b/src/simplnx/DataStructure/IO/Generic/CoreDataIOManager.hpp @@ -31,6 +31,7 @@ class SIMPLNX_EXPORT CoreDataIOManager : public IDataIOManager void addCoreFactories(); void addDataStoreFnc(); + void addListStoreFnc(); factory_collection m_FactoryCollection; }; diff --git a/src/simplnx/DataStructure/IO/Generic/DataIOCollection.cpp b/src/simplnx/DataStructure/IO/Generic/DataIOCollection.cpp index 0242096f36..4b7e504404 100644 --- a/src/simplnx/DataStructure/IO/Generic/DataIOCollection.cpp +++ b/src/simplnx/DataStructure/IO/Generic/DataIOCollection.cpp @@ -60,6 +60,20 @@ std::unique_ptr DataIOCollection::createDataStore(const std::string& return coreManager.dataStoreCreationFnc(coreManager.formatName())(dataType, tupleShape, componentShape, {}); } +std::unique_ptr DataIOCollection::createListStore(const std::string& type, DataType dataType, usize tupleCount) const +{ + for(const auto& [ioType, ioManager] : m_ManagerMap) + { + if(ioManager->hasListStoreCreationFnc(type)) + { + return ioManager->listStoreCreationFnc(type)(dataType, tupleCount); + } + } + + nx::core::Generic::CoreDataIOManager coreManager; + return coreManager.listStoreCreationFnc(coreManager.formatName())(dataType, tupleCount); +} + void DataIOCollection::checkStoreDataFormat(uint64 dataSize, std::string& dataFormat) const { if(!dataFormat.empty()) diff --git a/src/simplnx/DataStructure/IO/Generic/DataIOCollection.hpp b/src/simplnx/DataStructure/IO/Generic/DataIOCollection.hpp index 61205652ca..9a630eb285 100644 --- a/src/simplnx/DataStructure/IO/Generic/DataIOCollection.hpp +++ b/src/simplnx/DataStructure/IO/Generic/DataIOCollection.hpp @@ -1,6 +1,7 @@ #pragma once #include "simplnx/DataStructure/AbstractDataStore.hpp" +#include "simplnx/DataStructure/AbstractListStore.hpp" #include "simplnx/simplnx_export.hpp" #include "simplnx/Common/Types.hpp" @@ -60,6 +61,15 @@ class SIMPLNX_EXPORT DataIOCollection return std::dynamic_pointer_cast>(dataStore); } + std::unique_ptr createListStore(const std::string& type, DataType numericType, usize tupleCount) const; + template + std::shared_ptr> createListStoreWithType(const std::string& dataFormat, usize tupleCount) const + { + DataType numericType = GetDataType(); + std::shared_ptr listStore = createListStore(dataFormat, numericType, tupleCount); + return std::dynamic_pointer_cast>(listStore); + } + /** * @brief Checks the */ diff --git a/src/simplnx/DataStructure/IO/Generic/IDataIOManager.cpp b/src/simplnx/DataStructure/IO/Generic/IDataIOManager.cpp index 44a1b0ef79..29b80f5bcc 100644 --- a/src/simplnx/DataStructure/IO/Generic/IDataIOManager.cpp +++ b/src/simplnx/DataStructure/IO/Generic/IDataIOManager.cpp @@ -38,4 +38,19 @@ void IDataIOManager::addDataStoreCreationFnc(const std::string& type, DataStoreC { m_DataStoreCreationMap[type] = creationFnc; } + +bool IDataIOManager::hasListStoreCreationFnc(const std::string& type) const +{ + return m_ListStoreCreationMap.find(type) != m_ListStoreCreationMap.end(); +} + +IDataIOManager::ListStoreCreateFnc IDataIOManager::listStoreCreationFnc(const std::string& type) const +{ + return m_ListStoreCreationMap.at(type); +} + +void IDataIOManager::addListStoreCreationFnc(const std::string& type, ListStoreCreateFnc creationFnc) +{ + m_ListStoreCreationMap[type] = creationFnc; +} } // namespace nx::core diff --git a/src/simplnx/DataStructure/IO/Generic/IDataIOManager.hpp b/src/simplnx/DataStructure/IO/Generic/IDataIOManager.hpp index e9b742cbce..aedcfeda5d 100644 --- a/src/simplnx/DataStructure/IO/Generic/IDataIOManager.hpp +++ b/src/simplnx/DataStructure/IO/Generic/IDataIOManager.hpp @@ -2,6 +2,7 @@ #include "simplnx/DataStructure/DataObject.hpp" #include "simplnx/DataStructure/IDataStore.hpp" +#include "simplnx/DataStructure/IListStore.hpp" #include "simplnx/DataStructure/IO/Generic/IDataFactory.hpp" #include "simplnx/simplnx_export.hpp" @@ -28,7 +29,9 @@ class SIMPLNX_EXPORT IDataIOManager using factory_collection = std::map; using DataStoreCreateFnc = std::function(DataType, const typename IDataStore::ShapeType&, const typename IDataStore::ShapeType&, const std::optional&)>; + using ListStoreCreateFnc = std::function(DataType, usize)>; using DataStoreCreationMap = std::map; + using ListStoreCreationMap = std::map; virtual ~IDataIOManager() noexcept; @@ -75,14 +78,18 @@ class SIMPLNX_EXPORT IDataIOManager bool hasDataStoreCreationFnc(const std::string& type) const; DataStoreCreateFnc dataStoreCreationFnc(const std::string& type) const; + bool hasListStoreCreationFnc(const std::string& type) const; + ListStoreCreateFnc listStoreCreationFnc(const std::string& type) const; protected: IDataIOManager(); void addDataStoreCreationFnc(const std::string& type, DataStoreCreateFnc creationFnc); + void addListStoreCreationFnc(const std::string& type, ListStoreCreateFnc creationFnc); private: factory_collection m_FactoryCollection; DataStoreCreationMap m_DataStoreCreationMap; + ListStoreCreationMap m_ListStoreCreationMap; }; } // namespace nx::core diff --git a/src/simplnx/DataStructure/IO/HDF5/DataArrayIO.hpp b/src/simplnx/DataStructure/IO/HDF5/DataArrayIO.hpp index 6cf8ed610a..f632fab9b4 100644 --- a/src/simplnx/DataStructure/IO/HDF5/DataArrayIO.hpp +++ b/src/simplnx/DataStructure/IO/HDF5/DataArrayIO.hpp @@ -47,6 +47,81 @@ class DataArrayIO : public IDataIO err = (data == nullptr) ? -400 : 0; } + template + static Result<> importDataStore(data_type* dataArray, const DataPath& dataPath, const nx::core::HDF5::DatasetIO& datasetReader) + { + std::shared_ptr> dataStore = DataStoreIO::ReadDataStore(datasetReader); + if(dataStore == nullptr) + { + return MakeErrorResult(-150202, fmt::format("Failed to import DataArray data at path '{}'.", dataPath.toString())); + } + dataArray->setDataStore(dataStore); + return {}; + } + + /** + * @brief Replaces the AbstractDataStore using data from the HDF5 dataset. + * @param dataStructure + * @param dataPath + * @param dataStructureReader + * @return Result<> + */ + Result<> finishImportingData(DataStructure& dataStructure, const DataPath& dataPath, const group_reader_type& parentGroupReader) const override + { + if(!dataStructure.containsData(dataPath)) + { + return MakeErrorResult(-150200, fmt::format("Imported DataStructure Object at path '{}' does not exist.", dataPath.toString())); + } + + auto* dataArray = dataStructure.getDataAs(dataPath); + if(dataArray == nullptr) + { + return MakeErrorResult(-150201, fmt::format("Imported DataStructure Object at path '{}' is not of the expected type.", dataPath.toString())); + } + + auto datasetReader = parentGroupReader.openDataset(dataPath.getTargetName()); + auto dataTypeStrResult = datasetReader.readStringAttribute(Constants::k_ObjectTypeTag); + std::string dataTypeStr = std::move(dataTypeStrResult.value()); + const bool isBoolArray = dataTypeStr == "DataArray"; + + auto typeResult = datasetReader.getDataType(); + const auto type = std::move(typeResult.value()); + switch(type) + { + case DataType::float32: + return importDataStore(dataArray, dataPath, datasetReader); + case DataType::float64: + return importDataStore(dataArray, dataPath, datasetReader); + case DataType::int8: + return importDataStore(dataArray, dataPath, datasetReader); + case DataType::int16: + return importDataStore(dataArray, dataPath, datasetReader); + case DataType::int32: + return importDataStore(dataArray, dataPath, datasetReader); + case DataType::int64: + return importDataStore(dataArray, dataPath, datasetReader); + case DataType::uint8: { + if(isBoolArray) + { + return importDataStore(dataArray, dataPath, datasetReader); + } + else + { + return importDataStore(dataArray, dataPath, datasetReader); + } + } + break; + case DataType::uint16: + return importDataStore(dataArray, dataPath, datasetReader); + case DataType::uint32: + return importDataStore(dataArray, dataPath, datasetReader); + case DataType::uint64: + return importDataStore(dataArray, dataPath, datasetReader); + default: + return MakeErrorResult(-150209, fmt::format("Undetermined DataArray type: '{}'", dataTypeStr)); + } + } + /** * @brief Attempts to read the DataArray from HDF5. * Returns a Result<> with any errors or warnings encountered during the process. diff --git a/src/simplnx/DataStructure/IO/HDF5/DataStructureReader.cpp b/src/simplnx/DataStructure/IO/HDF5/DataStructureReader.cpp index 6b64895866..73b93b0990 100644 --- a/src/simplnx/DataStructure/IO/HDF5/DataStructureReader.cpp +++ b/src/simplnx/DataStructure/IO/HDF5/DataStructureReader.cpp @@ -28,7 +28,79 @@ Result DataStructureReader::ReadFile(const nx::core::HDF5::FileIO { DataStructureReader dataStructureReader; auto groupReader = fileReader.openGroup(Constants::k_DataStructureTag); - return dataStructureReader.readGroup(groupReader, useEmptyDataStores); + auto result = dataStructureReader.readGroup(groupReader, useEmptyDataStores); + + if(result.valid()) + { + dataStructureReader.loadRequiredData(fileReader); + } + return result; +} + +Result> DataStructureReader::ReadObject(const nx::core::HDF5::FileIO& fileReader, const DataPath& dataPath) +{ + std::string parentPathString = Constants::k_DataStructureTag; + parentPathString += dataPath.getParent().toString(); + + DataStructureReader dataStructureReader; + auto parentGroupReader = fileReader.openGroup(parentPathString); + + if(Result<> importResult = dataStructureReader.readObjectFromGroup(parentGroupReader, dataPath.getTargetName()); importResult.invalid()) + { + return ConvertInvalidResult>(std::move(importResult)); + } + + const DataStructure& dataStructure = dataStructureReader.getDataStructure(); + const DataMap& dataMap = dataStructure.getDataMap(); + if(dataMap.getSize() == 0) + { + return MakeErrorResult>(-69040, fmt::format("Failed to import DataObject at path '{}'", dataPath.toString())); + } + + auto item = dataMap.begin(); + return {(*item).second}; +} + +Result<> DataStructureReader::FinishImportingObject(DataStructure& dataStructure, const nx::core::HDF5::FileIO& fileReader, const DataPath& dataPath) +{ + std::shared_ptr factory = nullptr; + + std::string parentPathString = Constants::k_DataStructureTag; + parentPathString += "/" + dataPath.getParent().toString(); + + DataStructureReader dataStructureReader; + auto parentGroupReader = fileReader.openGroup(parentPathString); + bool isGroup = parentGroupReader.isGroup(dataPath.getTargetName()); + if(isGroup) + { + auto childObj = parentGroupReader.openGroup(dataPath.getTargetName()); + auto attrResult = childObj.readStringAttribute(Constants::k_ObjectTypeTag); + if(attrResult.invalid()) + { + return ConvertResult(std::move(attrResult)); + } + std::string typeName = std::move(attrResult.value()); + + factory = dataStructureReader.getDataFactory(typeName); + } + else + { + auto childObj = parentGroupReader.openDataset(dataPath.getTargetName()); + auto typeNameResult = childObj.readStringAttribute(Constants::k_ObjectTypeTag); + if(typeNameResult.invalid()) + { + return ConvertResult(std::move(typeNameResult)); + } + std::string typeName = std::move(typeNameResult.value()); + + factory = dataStructureReader.getDataFactory(typeName); + } + + if(factory == nullptr) + { + return MakeErrorResult(-23405, fmt::format("Failed to determine import factory type for path '{}'", dataPath.toString())); + } + return factory->finishImportingData(dataStructure, dataPath, parentGroupReader); } Result DataStructureReader::readGroup(const nx::core::HDF5::GroupIO& groupReader, bool useEmptyDataStores) @@ -196,4 +268,38 @@ std::shared_ptr DataStructureReader::getDataFactory(typename IDataIOMan return getDataReader()->getFactoryAs(typeName); } +void DataStructureReader::addRequiredPath(const DataPath& requiredDataPath) +{ + m_RequiredPaths.push_back(requiredDataPath); +} + +void DataStructureReader::addRequiredId(DataObject::IdType requiredDataId) +{ + m_RequiredIds.push_back(requiredDataId); +} + +void DataStructureReader::addRequiredId(DataObject::OptionalId requiredDataId) +{ + if(requiredDataId.has_value()) + { + m_RequiredIds.push_back(requiredDataId.value()); + } +} + +void DataStructureReader::loadRequiredData(const nx::core::HDF5::FileIO& fileReader) +{ + for(auto& id : m_RequiredIds) + { + auto* requiredObject = m_CurrentStructure.getData(id); + if(requiredObject != nullptr) + { + addRequiredPath(requiredObject->getDataPaths()[0]); + } + } + + for(const auto& dataPath : m_RequiredPaths) + { + FinishImportingObject(m_CurrentStructure, fileReader, dataPath); + } +} } // namespace nx::core::HDF5 diff --git a/src/simplnx/DataStructure/IO/HDF5/DataStructureReader.hpp b/src/simplnx/DataStructure/IO/HDF5/DataStructureReader.hpp index d963070d68..f81c20701d 100644 --- a/src/simplnx/DataStructure/IO/HDF5/DataStructureReader.hpp +++ b/src/simplnx/DataStructure/IO/HDF5/DataStructureReader.hpp @@ -37,6 +37,10 @@ class SIMPLNX_EXPORT DataStructureReader */ static Result ReadFile(const nx::core::HDF5::FileIO& fileReader, bool useEmptyDataStores = false); + static Result> ReadObject(const nx::core::HDF5::FileIO& fileReader, const DataPath& dataPath); + + static Result<> FinishImportingObject(DataStructure& dataStructure, const nx::core::HDF5::FileIO& fileReader, const DataPath& dataPath); + /** * @brief Imports and returns a DataStructure from a target nx::core::HDF5::GroupIO. * Returns any HDF5 error code that occur by reference. Otherwise, this value @@ -70,6 +74,10 @@ class SIMPLNX_EXPORT DataStructureReader */ void clearDataStructure(); + void addRequiredPath(const DataPath& requiredDataPath); + void addRequiredId(DataObject::IdType requiredDataId); + void addRequiredId(DataObject::OptionalId requiredDataId); + protected: /** * @brief Returns a pointer to the nx::core::HDF5::DataFactoryManager used for finding the @@ -86,8 +94,12 @@ class SIMPLNX_EXPORT DataStructureReader */ std::shared_ptr getDataFactory(typename IDataIOManager::factory_id_type typeName) const; + void loadRequiredData(const nx::core::HDF5::FileIO& fileReader); + private: std::shared_ptr m_IOManager = nullptr; DataStructure m_CurrentStructure; + std::vector m_RequiredPaths; + std::vector m_RequiredIds; }; } // namespace nx::core::HDF5 diff --git a/src/simplnx/DataStructure/IO/HDF5/EdgeGeomIO.cpp b/src/simplnx/DataStructure/IO/HDF5/EdgeGeomIO.cpp index 11347c90e2..5100df19d0 100644 --- a/src/simplnx/DataStructure/IO/HDF5/EdgeGeomIO.cpp +++ b/src/simplnx/DataStructure/IO/HDF5/EdgeGeomIO.cpp @@ -39,9 +39,31 @@ Result<> EdgeGeomIO::readData(DataStructureReader& structureReader, const group_ geometry->setElementCentroidsId(ReadDataId(groupReader, IOConstants::k_ElementCentroidTag)); geometry->setElementSizesId(ReadDataId(groupReader, IOConstants::k_ElementSizesTag)); - // return BaseGroup::readHdf5(dataStructureReader, groupReader, useEmptyDataStore); + if(useEmptyDataStore) + { + // Add required data for preflight operations. + structureReader.addRequiredId(ReadDataId(groupReader, IOConstants::k_VertexListTag)); + structureReader.addRequiredId(ReadDataId(groupReader, IOConstants::k_EdgeListTag)); + structureReader.addRequiredId(ReadDataId(groupReader, IOConstants::k_ElementContainingVertTag)); + structureReader.addRequiredId(ReadDataId(groupReader, IOConstants::k_ElementNeighborsTag)); + structureReader.addRequiredId(ReadDataId(groupReader, IOConstants::k_ElementCentroidTag)); + structureReader.addRequiredId(ReadDataId(groupReader, IOConstants::k_ElementSizesTag)); + } + return {}; } + +Result<> EdgeGeomIO::finishImportingData(DataStructure& dataStructure, const DataPath& dataPath, const group_reader_type& dataStructureGroup) const +{ + auto* geometry = dataStructure.getDataAs(dataPath); + if(geometry == nullptr) + { + return MakeErrorResult(-25070, fmt::format("Failed to finish importing geometry at path '{}'. Geometry does not exist or is of wrong type.", dataPath.toString())); + } + + return {}; +} + Result<> EdgeGeomIO::writeData(DataStructureWriter& dataStructureWriter, const EdgeGeom& geometry, group_writer_type& parentGroupWriter, bool importable) const { auto groupWriter = parentGroupWriter.createGroup(geometry.getName()); diff --git a/src/simplnx/DataStructure/IO/HDF5/EdgeGeomIO.hpp b/src/simplnx/DataStructure/IO/HDF5/EdgeGeomIO.hpp index 36e02d49aa..a01b108378 100644 --- a/src/simplnx/DataStructure/IO/HDF5/EdgeGeomIO.hpp +++ b/src/simplnx/DataStructure/IO/HDF5/EdgeGeomIO.hpp @@ -34,6 +34,8 @@ class SIMPLNX_EXPORT EdgeGeomIO : public INodeGeom1dIO Result<> readData(DataStructureReader& dataStructureReader, const group_reader_type& parentGroup, const std::string& geomName, DataObject::IdType importId, const std::optional& parentId, bool useEmptyDataStore = false) const override; + Result<> finishImportingData(DataStructure& dataStructure, const DataPath& dataPath, const group_reader_type& dataStructureGroup) const override; + /** * @brief Attempts to write an EdgeGeom to HDF5. * @param dataStructureWriter diff --git a/src/simplnx/DataStructure/IO/HDF5/HexahedralGeomIO.cpp b/src/simplnx/DataStructure/IO/HDF5/HexahedralGeomIO.cpp index 1ac52e5df2..6693a37f98 100644 --- a/src/simplnx/DataStructure/IO/HDF5/HexahedralGeomIO.cpp +++ b/src/simplnx/DataStructure/IO/HDF5/HexahedralGeomIO.cpp @@ -26,6 +26,18 @@ Result<> HexahedralGeomIO::readData(DataStructureReader& structureReader, const auto* geom = HexahedralGeom::Import(structureReader.getDataStructure(), objectName, importId, parentId); return INodeGeom3dIO::ReadNodeGeom3dData(structureReader, *geom, parentGroup, objectName, importId, parentId, useEmptyDataStore); } + +Result<> HexahedralGeomIO::finishImportingData(DataStructure& dataStructure, const DataPath& dataPath, const group_reader_type& dataStructureGroup) const +{ + auto* geometry = dataStructure.getDataAs(dataPath); + if(geometry == nullptr) + { + return MakeErrorResult(-25070, fmt::format("Failed to finish importing geometry at path '{}'. Geometry does not exist or is of wrong type.", dataPath.toString())); + } + + return INodeGeom3dIO::FinishImportingNodeGeom3dData(dataStructure, dataPath, dataStructureGroup); +} + Result<> HexahedralGeomIO::writeData(DataStructureWriter& structureReader, const HexahedralGeom& geom, group_writer_type& parentGroup, bool importable) const { auto groupWriter = parentGroup.createGroup(geom.getName()); diff --git a/src/simplnx/DataStructure/IO/HDF5/HexahedralGeomIO.hpp b/src/simplnx/DataStructure/IO/HDF5/HexahedralGeomIO.hpp index 7caf60c2a1..58f6eb70f0 100644 --- a/src/simplnx/DataStructure/IO/HDF5/HexahedralGeomIO.hpp +++ b/src/simplnx/DataStructure/IO/HDF5/HexahedralGeomIO.hpp @@ -30,6 +30,8 @@ class SIMPLNX_EXPORT HexahedralGeomIO : public INodeGeom3dIO Result<> readData(DataStructureReader& dataStructureReader, const group_reader_type& parentGroup, const std::string& geomName, DataObject::IdType importId, const std::optional& parentId, bool useEmptyDataStore = false) const override; + Result<> finishImportingData(DataStructure& dataStructure, const DataPath& dataPath, const group_reader_type& dataStructureGroup) const override; + /** * @brief Attempts to write an EdgeGeom to HDF5. * @param dataStructureWriter diff --git a/src/simplnx/DataStructure/IO/HDF5/IDataIO.cpp b/src/simplnx/DataStructure/IO/HDF5/IDataIO.cpp index 61c8e3ec9d..28f9347957 100644 --- a/src/simplnx/DataStructure/IO/HDF5/IDataIO.cpp +++ b/src/simplnx/DataStructure/IO/HDF5/IDataIO.cpp @@ -1,5 +1,6 @@ #include "IDataIO.hpp" +#include "simplnx/DataStructure/DataStructure.hpp" #include "simplnx/DataStructure/IO/HDF5/DataStructureWriter.hpp" #include "simplnx/Utilities/Parsing/HDF5/IO/DatasetIO.hpp" #include "simplnx/Utilities/Parsing/HDF5/IO/GroupIO.hpp" @@ -53,4 +54,9 @@ Result<> IDataIO::WriteObjectAttributes(DataStructureWriter& dataStructureWriter return {}; } + +Result<> IDataIO::finishImportingData(DataStructure& dataStructure, const DataPath& dataPath, const group_reader_type& dataStructureGroup) const +{ + return {}; +} } // namespace nx::core::HDF5 diff --git a/src/simplnx/DataStructure/IO/HDF5/IDataIO.hpp b/src/simplnx/DataStructure/IO/HDF5/IDataIO.hpp index a33c597913..c4bd73d579 100644 --- a/src/simplnx/DataStructure/IO/HDF5/IDataIO.hpp +++ b/src/simplnx/DataStructure/IO/HDF5/IDataIO.hpp @@ -7,6 +7,8 @@ namespace nx::core { +class DataStructure; + namespace HDF5 { class DataStructureReader; @@ -38,6 +40,8 @@ class SIMPLNX_EXPORT IDataIO : public nx::core::IDataFactory virtual Result<> readData(DataStructureReader& dataStructureReader, const group_reader_type& parentGroup, const std::string& objectName, DataObject::IdType importId, const std::optional& parentId, bool useEmptyDataStore = false) const = 0; + virtual Result<> finishImportingData(DataStructure& dataStructure, const DataPath& dataPath, const group_reader_type& dataStructureGroup) const; + /** * @brief Attempts to write a DataObject to HDF5. * @param dataStructureWriter diff --git a/src/simplnx/DataStructure/IO/HDF5/IGeometryIO.cpp b/src/simplnx/DataStructure/IO/HDF5/IGeometryIO.cpp index fad51d80f7..f83b57d60e 100644 --- a/src/simplnx/DataStructure/IO/HDF5/IGeometryIO.cpp +++ b/src/simplnx/DataStructure/IO/HDF5/IGeometryIO.cpp @@ -24,6 +24,18 @@ Result<> IGeometryIO::ReadGeometryData(DataStructureReader& dataStructureReader, return {}; } + +Result<> IGeometryIO::FinishImportingGeomData(DataStructure& dataStructure, const DataPath& dataPath, const group_reader_type& dataStructureGroup) +{ + auto* geom = dataStructure.getDataAs(dataPath); + if(geom == nullptr) + { + return MakeErrorResult(-50590, fmt::format("Failed to finish importing IGeometry at path '{}'. Data not found or of incorrect type.", dataPath.toString())); + } + + return {}; +} + Result<> IGeometryIO::WriteGeometryData(DataStructureWriter& dataStructureWriter, const IGeometry& geometry, group_writer_type& parentGroup, bool importable) { auto groupWriter = parentGroup.createGroup(geometry.getName()); diff --git a/src/simplnx/DataStructure/IO/HDF5/IGeometryIO.hpp b/src/simplnx/DataStructure/IO/HDF5/IGeometryIO.hpp index 9aab08cf63..c8424aaff9 100644 --- a/src/simplnx/DataStructure/IO/HDF5/IGeometryIO.hpp +++ b/src/simplnx/DataStructure/IO/HDF5/IGeometryIO.hpp @@ -49,6 +49,8 @@ class SIMPLNX_EXPORT IGeometryIO : public BaseGroupIO * @return Result<> */ static Result<> WriteGeometryData(DataStructureWriter& dataStructureWriter, const IGeometry& geometry, group_writer_type& parentGroup, bool importable); + + static Result<> FinishImportingGeomData(DataStructure& dataStructure, const DataPath& dataPath, const group_reader_type& dataStructureGroup); }; } // namespace HDF5 } // namespace nx::core diff --git a/src/simplnx/DataStructure/IO/HDF5/IGridGeometryIO.cpp b/src/simplnx/DataStructure/IO/HDF5/IGridGeometryIO.cpp index d11854bfe3..5f5089fbf1 100644 --- a/src/simplnx/DataStructure/IO/HDF5/IGridGeometryIO.cpp +++ b/src/simplnx/DataStructure/IO/HDF5/IGridGeometryIO.cpp @@ -25,6 +25,18 @@ Result<> IGridGeometryIO::ReadGridGeometryData(DataStructureReader& dataStructur return {}; } + +Result<> IGridGeometryIO::FinishImportingGridGeometryData(DataStructure& dataStructure, const DataPath& dataPath, const group_reader_type& dataStructureGroup) +{ + auto* geom = dataStructure.getDataAs(dataPath); + if(geom == nullptr) + { + return MakeErrorResult(-50594, fmt::format("Failed to finish importing IGridGeometry at path '{}'. Data not found or of incorrect type.", dataPath.toString())); + } + + return {}; +} + Result<> IGridGeometryIO::WriteGridGeometryData(DataStructureWriter& dataStructureWriter, const IGridGeometry& geometry, group_writer_type& parentGroup, bool importable) { auto result = IGeometryIO::WriteGeometryData(dataStructureWriter, geometry, parentGroup, importable); diff --git a/src/simplnx/DataStructure/IO/HDF5/IGridGeometryIO.hpp b/src/simplnx/DataStructure/IO/HDF5/IGridGeometryIO.hpp index 111b1952e9..aae600b61b 100644 --- a/src/simplnx/DataStructure/IO/HDF5/IGridGeometryIO.hpp +++ b/src/simplnx/DataStructure/IO/HDF5/IGridGeometryIO.hpp @@ -45,6 +45,8 @@ class SIMPLNX_EXPORT IGridGeometryIO : public IGeometryIO * @return Result<> */ static Result<> WriteGridGeometryData(DataStructureWriter& dataStructureWriter, const IGridGeometry& geometry, group_writer_type& parentGroup, bool importable); + + static Result<> FinishImportingGridGeometryData(DataStructure& dataStructure, const DataPath& dataPath, const group_reader_type& dataStructureGroup); }; } // namespace HDF5 } // namespace nx::core diff --git a/src/simplnx/DataStructure/IO/HDF5/INodeGeom0dIO.cpp b/src/simplnx/DataStructure/IO/HDF5/INodeGeom0dIO.cpp index 8ce5f662fe..dc1ce0d40d 100644 --- a/src/simplnx/DataStructure/IO/HDF5/INodeGeom0dIO.cpp +++ b/src/simplnx/DataStructure/IO/HDF5/INodeGeom0dIO.cpp @@ -1,5 +1,6 @@ #include "INodeGeom0dIO.hpp" +#include "DataStructureReader.hpp" #include "DataStructureWriter.hpp" #include "simplnx/DataStructure/Geometry/INodeGeometry0D.hpp" #include "simplnx/DataStructure/IO/Generic/IOConstants.hpp" @@ -29,8 +30,36 @@ Result<> INodeGeom0dIO::ReadNodeGeom0dData(DataStructureReader& dataStructureRea geometry.setVertexListId(ReadDataId(groupReader, IOConstants::k_VertexListTag)); geometry.setVertexDataId(ReadDataId(groupReader, IOConstants::k_VertexDataTag)); + // Required data + if(useEmptyDataStore) + { + dataStructureReader.addRequiredId(ReadDataId(groupReader, IOConstants::k_VertexListTag)); + dataStructureReader.addRequiredId(ReadDataId(groupReader, IOConstants::k_VertexDataTag)); + } + return {}; } + +Result<> INodeGeom0dIO::FinishImportingNodeGeom0dData(DataStructure& dataStructure, const DataPath& dataPath, const group_reader_type& dataStructureGroup) +{ + auto* geom = dataStructure.getDataAs(dataPath); + if(geom == nullptr) + { + return MakeErrorResult(-50590, fmt::format("Failed to finish importing INodeGeometry0D at path '{}'. Data not found or of incorrect type.", dataPath.toString())); + } + + { + auto groupReader = dataStructureGroup.openGroup(dataPath.toString()); + if(const auto unitsAttr = groupReader.readScalarAttribute(IOConstants::k_H5_UNITS); unitsAttr.valid()) + { + auto value = unitsAttr.value(); + geom->setUnits(static_cast(value)); + } + } + + return IGeometryIO::FinishImportingGeomData(dataStructure, dataPath, dataStructureGroup); +} + Result<> INodeGeom0dIO::WriteNodeGeom0dData(DataStructureWriter& dataStructureWriter, const INodeGeometry0D& geometry, group_writer_type& parentGroupWriter, bool importable) { Result<> result = IGeometryIO::WriteGeometryData(dataStructureWriter, geometry, parentGroupWriter, importable); diff --git a/src/simplnx/DataStructure/IO/HDF5/INodeGeom0dIO.hpp b/src/simplnx/DataStructure/IO/HDF5/INodeGeom0dIO.hpp index 43c3348994..9395872900 100644 --- a/src/simplnx/DataStructure/IO/HDF5/INodeGeom0dIO.hpp +++ b/src/simplnx/DataStructure/IO/HDF5/INodeGeom0dIO.hpp @@ -45,6 +45,8 @@ class SIMPLNX_EXPORT INodeGeom0dIO : public IGeometryIO * @return Result<> */ static Result<> WriteNodeGeom0dData(DataStructureWriter& dataStructureWriter, const INodeGeometry0D& geometry, group_writer_type& parentGroup, bool importable); + + static Result<> FinishImportingNodeGeom0dData(DataStructure& dataStructure, const DataPath& dataPath, const group_reader_type& dataStructureGroup); }; } // namespace HDF5 } // namespace nx::core diff --git a/src/simplnx/DataStructure/IO/HDF5/INodeGeom1dIO.cpp b/src/simplnx/DataStructure/IO/HDF5/INodeGeom1dIO.cpp index 7be8712a0a..de57e39da8 100644 --- a/src/simplnx/DataStructure/IO/HDF5/INodeGeom1dIO.cpp +++ b/src/simplnx/DataStructure/IO/HDF5/INodeGeom1dIO.cpp @@ -1,5 +1,6 @@ #include "INodeGeom1dIO.hpp" +#include "DataStructureReader.hpp" #include "DataStructureWriter.hpp" #include "simplnx/DataStructure/Geometry/INodeGeometry1D.hpp" #include "simplnx/DataStructure/IO/Generic/IOConstants.hpp" @@ -25,8 +26,30 @@ Result<> INodeGeom1dIO::ReadNodeGeom1dData(DataStructureReader& dataStructureRea geometry.setElementNeighborsId(ReadDataId(groupReader, IOConstants::k_ElementNeighborsTag)); geometry.setElementCentroidsId(ReadDataId(groupReader, IOConstants::k_ElementCentroidTag)); + // Required data + if(useEmptyDataStore) + { + dataStructureReader.addRequiredId(ReadDataId(groupReader, IOConstants::k_EdgeListTag)); + dataStructureReader.addRequiredId(ReadDataId(groupReader, IOConstants::k_EdgeDataTag)); + dataStructureReader.addRequiredId(ReadDataId(groupReader, IOConstants::k_ElementContainingVertTag)); + dataStructureReader.addRequiredId(ReadDataId(groupReader, IOConstants::k_ElementNeighborsTag)); + dataStructureReader.addRequiredId(ReadDataId(groupReader, IOConstants::k_ElementCentroidTag)); + } + return {}; } + +Result<> INodeGeom1dIO::FinishImportingNodeGeom1dData(DataStructure& dataStructure, const DataPath& dataPath, const group_reader_type& dataStructureGroup) +{ + auto* geom = dataStructure.getDataAs(dataPath); + if(geom == nullptr) + { + return MakeErrorResult(-50590, fmt::format("Failed to finish importing INodeGeometry1D at path '{}'. Data not found or of incorrect type.", dataPath.toString())); + } + + return INodeGeom0dIO::FinishImportingNodeGeom0dData(dataStructure, dataPath, dataStructureGroup); +} + Result<> INodeGeom1dIO::WriteNodeGeom1dData(DataStructureWriter& dataStructureWriter, const INodeGeometry1D& geometry, group_writer_type& parentGroupWriter, bool importable) { Result<> result = INodeGeom0dIO::WriteNodeGeom0dData(dataStructureWriter, geometry, parentGroupWriter, importable); diff --git a/src/simplnx/DataStructure/IO/HDF5/INodeGeom1dIO.hpp b/src/simplnx/DataStructure/IO/HDF5/INodeGeom1dIO.hpp index 66ed27ee94..389fa8fc65 100644 --- a/src/simplnx/DataStructure/IO/HDF5/INodeGeom1dIO.hpp +++ b/src/simplnx/DataStructure/IO/HDF5/INodeGeom1dIO.hpp @@ -45,6 +45,8 @@ class SIMPLNX_EXPORT INodeGeom1dIO : public INodeGeom0dIO * @return Result<> */ static Result<> WriteNodeGeom1dData(DataStructureWriter& dataStructureWriter, const INodeGeometry1D& geometry, group_writer_type& parentGroup, bool importable); + + static Result<> FinishImportingNodeGeom1dData(DataStructure& dataStructure, const DataPath& dataPath, const group_reader_type& dataStructureGroup); }; } // namespace HDF5 } // namespace nx::core diff --git a/src/simplnx/DataStructure/IO/HDF5/INodeGeom2dIO.cpp b/src/simplnx/DataStructure/IO/HDF5/INodeGeom2dIO.cpp index 3a4623608c..28771b7790 100644 --- a/src/simplnx/DataStructure/IO/HDF5/INodeGeom2dIO.cpp +++ b/src/simplnx/DataStructure/IO/HDF5/INodeGeom2dIO.cpp @@ -1,5 +1,6 @@ #include "INodeGeom2dIO.hpp" +#include "DataStructureReader.hpp" #include "DataStructureWriter.hpp" #include "simplnx/DataStructure/Geometry/INodeGeometry2D.hpp" #include "simplnx/DataStructure/IO/Generic/IOConstants.hpp" @@ -24,9 +25,28 @@ Result<> INodeGeom2dIO::ReadNodeGeom2dData(DataStructureReader& dataStructureRea geometry.setFaceDataId(ReadDataId(groupReader, IOConstants::k_FaceDataTag)); geometry.setUnsharedEdgesId(ReadDataId(groupReader, IOConstants::k_UnsharedEdgeListTag)); + // Required data + if(useEmptyDataStore) + { + dataStructureReader.addRequiredId(ReadDataId(groupReader, IOConstants::k_FaceListTag)); + dataStructureReader.addRequiredId(ReadDataId(groupReader, IOConstants::k_FaceDataTag)); + dataStructureReader.addRequiredId(ReadDataId(groupReader, IOConstants::k_UnsharedEdgeListTag)); + } + return {}; } +Result<> INodeGeom2dIO::FinishImportingNodeGeom2dData(DataStructure& dataStructure, const DataPath& dataPath, const group_reader_type& dataStructureGroup) +{ + auto* geom = dataStructure.getDataAs(dataPath); + if(geom == nullptr) + { + return MakeErrorResult(-50591, fmt::format("Failed to finish importing INodeGeometry2D at path '{}'. Data not found or of incorrect type.", dataPath.toString())); + } + + return INodeGeom1dIO::FinishImportingNodeGeom1dData(dataStructure, dataPath, dataStructureGroup); +} + Result<> INodeGeom2dIO::WriteNodeGeom2dData(DataStructureWriter& dataStructureWriter, const INodeGeometry2D& geometry, group_writer_type& parentGroupWriter, bool importable) { Result<> result = INodeGeom1dIO::WriteNodeGeom1dData(dataStructureWriter, geometry, parentGroupWriter, importable); diff --git a/src/simplnx/DataStructure/IO/HDF5/INodeGeom2dIO.hpp b/src/simplnx/DataStructure/IO/HDF5/INodeGeom2dIO.hpp index 67da7f6dfc..eef43d03ee 100644 --- a/src/simplnx/DataStructure/IO/HDF5/INodeGeom2dIO.hpp +++ b/src/simplnx/DataStructure/IO/HDF5/INodeGeom2dIO.hpp @@ -45,6 +45,8 @@ class SIMPLNX_EXPORT INodeGeom2dIO : public INodeGeom1dIO * @return Result<> */ static Result<> WriteNodeGeom2dData(DataStructureWriter& dataStructureWriter, const INodeGeometry2D& geometry, group_writer_type& parentGroup, bool importable); + + static Result<> FinishImportingNodeGeom2dData(DataStructure& dataStructure, const DataPath& dataPath, const group_reader_type& dataStructureGroup); }; } // namespace HDF5 } // namespace nx::core diff --git a/src/simplnx/DataStructure/IO/HDF5/INodeGeom3dIO.cpp b/src/simplnx/DataStructure/IO/HDF5/INodeGeom3dIO.cpp index a0388ffbd6..017bcd4d81 100644 --- a/src/simplnx/DataStructure/IO/HDF5/INodeGeom3dIO.cpp +++ b/src/simplnx/DataStructure/IO/HDF5/INodeGeom3dIO.cpp @@ -1,5 +1,6 @@ #include "INodeGeom3dIO.hpp" +#include "DataStructureReader.hpp" #include "DataStructureWriter.hpp" #include "simplnx/DataStructure/Geometry/INodeGeometry3D.hpp" #include "simplnx/DataStructure/IO/Generic/IOConstants.hpp" @@ -24,8 +25,28 @@ Result<> INodeGeom3dIO::ReadNodeGeom3dData(DataStructureReader& dataStructureRea geom.setPolyhedraDataId(ReadDataId(groupReader, IOConstants::k_PolyhedronDataTag)); geom.setUnsharedFacedId(ReadDataId(groupReader, IOConstants::k_UnsharedFaceListTag)); + // Required data + if(useEmptyDataStore) + { + dataStructureReader.addRequiredId(ReadDataId(groupReader, IOConstants::k_PolyhedronListTag)); + dataStructureReader.addRequiredId(ReadDataId(groupReader, IOConstants::k_PolyhedronDataTag)); + dataStructureReader.addRequiredId(ReadDataId(groupReader, IOConstants::k_UnsharedFaceListTag)); + } + return {}; } + +Result<> INodeGeom3dIO::FinishImportingNodeGeom3dData(DataStructure& dataStructure, const DataPath& dataPath, const group_reader_type& dataStructureGroup) +{ + auto* geom = dataStructure.getDataAs(dataPath); + if(geom == nullptr) + { + return MakeErrorResult(-50592, fmt::format("Failed to finish importing INodeGeometry3D at path '{}'. Data not found or of incorrect type.", dataPath.toString())); + } + + return INodeGeom2dIO::FinishImportingNodeGeom2dData(dataStructure, dataPath, dataStructureGroup); +} + Result<> INodeGeom3dIO::WriteNodeGeom3dData(DataStructureWriter& dataStructureWriter, const INodeGeometry3D& geom, group_writer_type& parentGroup, bool importable) { Result<> result = INodeGeom2dIO::WriteNodeGeom2dData(dataStructureWriter, geom, parentGroup, importable); diff --git a/src/simplnx/DataStructure/IO/HDF5/INodeGeom3dIO.hpp b/src/simplnx/DataStructure/IO/HDF5/INodeGeom3dIO.hpp index 46f526baa9..c3622ca66b 100644 --- a/src/simplnx/DataStructure/IO/HDF5/INodeGeom3dIO.hpp +++ b/src/simplnx/DataStructure/IO/HDF5/INodeGeom3dIO.hpp @@ -45,6 +45,8 @@ class SIMPLNX_EXPORT INodeGeom3dIO : public INodeGeom2dIO * @return Result<> */ static Result<> WriteNodeGeom3dData(DataStructureWriter& dataStructureWriter, const INodeGeometry3D& geometry, group_writer_type& parentGroup, bool importable); + + static Result<> FinishImportingNodeGeom3dData(DataStructure& dataStructure, const DataPath& dataPath, const group_reader_type& dataStructureGroup); }; } // namespace HDF5 } // namespace nx::core diff --git a/src/simplnx/DataStructure/IO/HDF5/NeighborListIO.hpp b/src/simplnx/DataStructure/IO/HDF5/NeighborListIO.hpp index cb88f85e72..26a585decd 100644 --- a/src/simplnx/DataStructure/IO/HDF5/NeighborListIO.hpp +++ b/src/simplnx/DataStructure/IO/HDF5/NeighborListIO.hpp @@ -4,6 +4,7 @@ #include "simplnx/Common/Result.hpp" #include "simplnx/DataStructure/DataArray.hpp" #include "simplnx/DataStructure/DataStore.hpp" +#include "simplnx/DataStructure/EmptyListStore.hpp" #include "simplnx/DataStructure/IO/HDF5/DataArrayIO.hpp" #include "simplnx/DataStructure/IO/HDF5/DataStoreIO.hpp" #include "simplnx/DataStructure/IO/HDF5/IDataIO.hpp" @@ -20,6 +21,7 @@ class NeighborListIO : public IDataIO { public: using data_type = NeighborList; + using store_type = typename data_type::store_type; using shared_vector_type = typename data_type::SharedVectorType; NeighborListIO() = default; @@ -32,7 +34,7 @@ class NeighborListIO : public IDataIO * @param dataReader * @return Result<> */ - static std::vector ReadHdf5Data(const nx::core::HDF5::GroupIO& parentGroup, const nx::core::HDF5::DatasetIO& dataReader) + static std::shared_ptr ReadHdf5Data(const nx::core::HDF5::GroupIO& parentGroup, const nx::core::HDF5::DatasetIO& dataReader, bool useEmptyDataStore = false) { try { @@ -43,38 +45,56 @@ class NeighborListIO : public IDataIO return {}; } numNeighborsName = std::move(numNeighborsNameResult.value()); - auto numNeighborsReader = parentGroup.openDataset(numNeighborsName); + + if(useEmptyDataStore) + { + auto tupleDimsResult = numNeighborsReader.readVectorAttribute("TupleDimensions"); + if(tupleDimsResult.invalid()) + { + return nullptr; + } + std::vector tupleDims = tupleDimsResult.value(); + uint64 numTuples = std::accumulate(tupleDims.begin(), tupleDims.end(), static_cast(1), std::multiplies<>()); + return std::make_shared>(numTuples); + } + auto numNeighborsPtr = DataStoreIO::ReadDataStore(numNeighborsReader); auto& numNeighborsStore = *numNeighborsPtr.get(); - std::vector flatDataStore = dataReader.template readAsVector(); + auto flatDataStorePtr = dataReader.template readAsDataStore(); + if(flatDataStorePtr == nullptr) + { + throw std::runtime_error(fmt::format("Error reading neighbor list from DataStore from HDF5 at '{}' called '{}'", dataReader.getFilePath().string(), dataReader.getName())); + } + + const AbstractDataStore& flatDataStore = *flatDataStorePtr.get(); if(flatDataStore.empty()) { - throw std::runtime_error(fmt::format("Error reading neighbor list from DataStore from HDF5 at {} called {}", dataReader.getFilePath().string(), dataReader.getName())); + throw std::runtime_error(fmt::format("Error reading neighbor list from DataStore from HDF5 at '{}' called '{}'", dataReader.getFilePath().string(), dataReader.getName())); } - std::vector dataVector; usize offset = 0; const auto numTuples = numNeighborsStore.getNumberOfTuples(); + auto listStorePtr = DataStoreUtilities::CreateListStore(numTuples); + AbstractListStore& listStore = *listStorePtr.get(); for(usize i = 0; i < numTuples; i++) { const auto numNeighbors = numNeighborsStore[i]; - auto sharedVector = std::make_shared>(numNeighbors); - std::vector& vector = *sharedVector.get(); + std::vector vector(numNeighbors); size_t neighborListStart = offset; size_t neighborListEnd = offset + numNeighbors; - sharedVector->assign(flatDataStore.begin() + neighborListStart, flatDataStore.begin() + neighborListEnd); + vector.assign(flatDataStore.begin() + neighborListStart, flatDataStore.begin() + neighborListEnd); offset += numNeighbors; - dataVector.push_back(sharedVector); + listStore.setList(i, vector); } - return dataVector; + return listStorePtr; } catch(const std::exception& e) { std::cout << "Cannot Read Neighborlist Dataset at path '" << dataReader.getObjectPath() << "' with error '" << e.what() << "'" << std::endl; - return {}; + return nullptr; } } @@ -93,8 +113,8 @@ class NeighborListIO : public IDataIO const std::optional& parentId, bool useEmptyDataStore = false) const override { auto datasetReader = parentGroup.openDataset(objectName); - auto dataVector = ReadHdf5Data(parentGroup, datasetReader); - auto* dataObject = data_type::Import(dataStructureReader.getDataStructure(), objectName, importId, dataVector, parentId); + auto listStorePtr = ReadHdf5Data(parentGroup, datasetReader, useEmptyDataStore); + auto* dataObject = data_type::Import(dataStructureReader.getDataStructure(), objectName, importId, listStorePtr, parentId); if(dataObject == nullptr) { std::string ss = "Failed to import NeighborList from HDF5"; @@ -103,6 +123,66 @@ class NeighborListIO : public IDataIO return {}; } + /** + * @brief Replaces the AbstractListStore using data from the HDF5 dataset. + * @param dataStructure + * @param dataPath + * @param dataStructureReader + * @return Result<> + */ + Result<> finishImportingData(DataStructure& dataStructure, const DataPath& dataPath, const group_reader_type& parentGroup) const override + { + if(!dataStructure.containsData(dataPath)) + { + return MakeErrorResult(-150200, fmt::format("Imported DataStructure Object at path '{}' does not exist.", dataPath.toString())); + } + + NeighborList& neighborList = dataStructure.getDataRefAs>(dataPath); + auto dataReader = parentGroup.openDataset(dataPath.getTargetName()); + + std::string numNeighborsName; + auto numNeighborsNameResult = dataReader.readStringAttribute("Linked NumNeighbors Dataset"); + if(numNeighborsNameResult.invalid()) + { + return {}; + } + numNeighborsName = std::move(numNeighborsNameResult.value()); + + auto numNeighborsReader = parentGroup.openDataset(numNeighborsName); + auto numNeighborsPtr = DataStoreIO::ReadDataStore(numNeighborsReader); + auto& numNeighborsStore = *numNeighborsPtr.get(); + + auto flatDataStorePtr = dataReader.template readAsDataStore(); + if(flatDataStorePtr == nullptr) + { + return MakeErrorResult(-150201, fmt::format("Imported DataStructure Object at path '{}' is not of the expected type.", dataPath.toString())); + } + AbstractDataStore& flatDataStore = *(flatDataStorePtr.get()); + if(flatDataStore.empty()) + { + throw std::runtime_error(fmt::format("Error reading neighbor list from DataStore from HDF5 at '{}' called '{}'", dataReader.getFilePath().string(), dataReader.getName())); + } + + usize offset = 0; + const auto numTuples = numNeighborsStore.getNumberOfTuples(); + auto listStorePtr = DataStoreUtilities::CreateListStore(numTuples); + AbstractListStore& listStore = *listStorePtr.get(); + for(usize i = 0; i < numTuples; i++) + { + const auto numNeighbors = numNeighborsStore[i]; + std::vector vector(numNeighbors); + + size_t neighborListStart = offset; + size_t neighborListEnd = offset + numNeighbors; + vector.assign(flatDataStore.begin() + neighborListStart, flatDataStore.begin() + neighborListEnd); + offset += numNeighbors; + listStore.setList(i, vector); + } + + neighborList.setStore(listStorePtr); + return {}; + } + /** * @brief Attempts to write the NeighborList to HDF5. * @param dataStructureWriter diff --git a/src/simplnx/DataStructure/IO/HDF5/QuadGeomIO.cpp b/src/simplnx/DataStructure/IO/HDF5/QuadGeomIO.cpp index 01bfb9b1ab..576124bcff 100644 --- a/src/simplnx/DataStructure/IO/HDF5/QuadGeomIO.cpp +++ b/src/simplnx/DataStructure/IO/HDF5/QuadGeomIO.cpp @@ -26,6 +26,18 @@ Result<> QuadGeomIO::readData(DataStructureReader& structureReader, const group_ auto* geometry = QuadGeom::Import(structureReader.getDataStructure(), objectName, importId, parentId); return INodeGeom2dIO::ReadNodeGeom2dData(structureReader, *geometry, parentGroup, objectName, importId, parentId, useEmptyDataStore); } + +Result<> QuadGeomIO::finishImportingData(DataStructure& dataStructure, const DataPath& dataPath, const group_reader_type& dataStructureGroup) const +{ + auto* geom = dataStructure.getDataAs(dataPath); + if(geom == nullptr) + { + return MakeErrorResult(-50590, fmt::format("Failed to finish importing QuadGeom at path '{}'. Data not found or of incorrect type.", dataPath.toString())); + } + + return INodeGeom2dIO::FinishImportingNodeGeom2dData(dataStructure, dataPath, dataStructureGroup); +} + Result<> QuadGeomIO::writeData(DataStructureWriter& dataStructureWriter, const QuadGeom& geom, group_writer_type& parentGroup, bool importable) const { return INodeGeom2dIO::WriteNodeGeom2dData(dataStructureWriter, geom, parentGroup, importable); diff --git a/src/simplnx/DataStructure/IO/HDF5/QuadGeomIO.hpp b/src/simplnx/DataStructure/IO/HDF5/QuadGeomIO.hpp index ed4051e9d3..55d68cb3a4 100644 --- a/src/simplnx/DataStructure/IO/HDF5/QuadGeomIO.hpp +++ b/src/simplnx/DataStructure/IO/HDF5/QuadGeomIO.hpp @@ -30,6 +30,8 @@ class SIMPLNX_EXPORT QuadGeomIO : public INodeGeom2dIO Result<> readData(DataStructureReader& dataStructureReader, const group_reader_type& parentGroup, const std::string& geomName, DataObject::IdType importId, const std::optional& parentId, bool useEmptyDataStore = false) const override; + Result<> finishImportingData(DataStructure& dataStructure, const DataPath& dataPath, const group_reader_type& dataStructureGroup) const override; + /** * @brief Attempts to write an QuadGeom to HDF5. * @param dataStructureWriter diff --git a/src/simplnx/DataStructure/IO/HDF5/RectGridGeomIO.cpp b/src/simplnx/DataStructure/IO/HDF5/RectGridGeomIO.cpp index df772431e9..66a587a3b4 100644 --- a/src/simplnx/DataStructure/IO/HDF5/RectGridGeomIO.cpp +++ b/src/simplnx/DataStructure/IO/HDF5/RectGridGeomIO.cpp @@ -58,9 +58,48 @@ Result<> RectGridGeomIO::readData(DataStructureReader& dataStructureReader, cons geometry->setYBoundsId(ReadDataId(groupReader, IOConstants::k_YBoundsTag)); geometry->setZBoundsId(ReadDataId(groupReader, IOConstants::k_ZBoundsTag)); + // Required data + if(useEmptyDataStore) + { + dataStructureReader.addRequiredId(ReadDataId(groupReader, IOConstants::k_XBoundsTag)); + dataStructureReader.addRequiredId(ReadDataId(groupReader, IOConstants::k_YBoundsTag)); + dataStructureReader.addRequiredId(ReadDataId(groupReader, IOConstants::k_ZBoundsTag)); + } + return {}; } +Result<> RectGridGeomIO::finishImportingData(DataStructure& dataStructure, const DataPath& dataPath, const group_reader_type& dataStructureGroup) const +{ + auto* geom = dataStructure.getDataAs(dataPath); + if(geom == nullptr) + { + return MakeErrorResult(-50590, fmt::format("Failed to finish importing RectGridGeom at path '{}'. Data not found or of incorrect type.", dataPath.toString())); + } + + { + auto groupReader = dataStructureGroup.openGroup(dataPath.toString()); + + if(const auto unitsAttr = groupReader.readScalarAttribute(IOConstants::k_H5_UNITS); unitsAttr.valid()) + { + auto value = unitsAttr.value(); + geom->setUnits(static_cast(value)); + } + + // Read Dimensions + auto volumeDimensionsResult = groupReader.readVectorAttribute("Dimensions"); + if(volumeDimensionsResult.invalid()) + { + return ConvertInvalidResult(std::move(volumeDimensionsResult)); + } + const std::vector volumeDimensions = std::move(volumeDimensionsResult.value()); + + geom->setDimensions(volumeDimensions); + } + + return IGridGeometryIO::FinishImportingGridGeometryData(dataStructure, dataPath, dataStructureGroup); +} + Result<> RectGridGeomIO::writeData(DataStructureWriter& dataStructureWriter, const RectGridGeom& geometry, group_writer_type& parentGroup, bool importable) const { Result<> result = IGridGeometryIO::WriteGridGeometryData(dataStructureWriter, geometry, parentGroup, importable); diff --git a/src/simplnx/DataStructure/IO/HDF5/RectGridGeomIO.hpp b/src/simplnx/DataStructure/IO/HDF5/RectGridGeomIO.hpp index 272aca4e6d..90fd4fcd88 100644 --- a/src/simplnx/DataStructure/IO/HDF5/RectGridGeomIO.hpp +++ b/src/simplnx/DataStructure/IO/HDF5/RectGridGeomIO.hpp @@ -30,6 +30,8 @@ class SIMPLNX_EXPORT RectGridGeomIO : public IGridGeometryIO Result<> readData(DataStructureReader& dataStructureReader, const group_reader_type& parentGroup, const std::string& geomName, DataObject::IdType importId, const std::optional& parentId, bool useEmptyDataStore = false) const override; + Result<> finishImportingData(DataStructure& dataStructure, const DataPath& dataPath, const group_reader_type& dataStructureGroup) const override; + /** * @brief Attempts to write an RectGridGeom to HDF5. * @param dataStructureWriter diff --git a/src/simplnx/DataStructure/IO/HDF5/TetrahedralGeomIO.cpp b/src/simplnx/DataStructure/IO/HDF5/TetrahedralGeomIO.cpp index 5240f4fec3..72a5337637 100644 --- a/src/simplnx/DataStructure/IO/HDF5/TetrahedralGeomIO.cpp +++ b/src/simplnx/DataStructure/IO/HDF5/TetrahedralGeomIO.cpp @@ -27,6 +27,17 @@ Result<> TetrahedralGeomIO::readData(DataStructureReader& structureReader, const auto* geometry = TetrahedralGeom::Import(structureReader.getDataStructure(), objectName, importId, parentId); return INodeGeom3dIO::ReadNodeGeom3dData(structureReader, *geometry, parentGroup, objectName, importId, parentId, useEmptyDataStore); } + +Result<> TetrahedralGeomIO::finishImportingData(DataStructure& dataStructure, const DataPath& dataPath, const group_reader_type& dataStructureGroup) const +{ + auto* geom = dataStructure.getDataAs(dataPath); + if(geom == nullptr) + { + return MakeErrorResult(-50595, fmt::format("Failed to finish importing TetrahedraldGeom at path '{}'. Data not found or of incorrect type.", dataPath.toString())); + } + return INodeGeom3dIO::FinishImportingNodeGeom3dData(dataStructure, dataPath, dataStructureGroup); +} + Result<> TetrahedralGeomIO::writeData(DataStructureWriter& dataStructureWriter, const TetrahedralGeom& geometry, group_writer_type& parentGroup, bool importable) const { return INodeGeom3dIO::WriteNodeGeom3dData(dataStructureWriter, geometry, parentGroup, importable); diff --git a/src/simplnx/DataStructure/IO/HDF5/TetrahedralGeomIO.hpp b/src/simplnx/DataStructure/IO/HDF5/TetrahedralGeomIO.hpp index abf2119527..a4c67b6ae0 100644 --- a/src/simplnx/DataStructure/IO/HDF5/TetrahedralGeomIO.hpp +++ b/src/simplnx/DataStructure/IO/HDF5/TetrahedralGeomIO.hpp @@ -30,6 +30,8 @@ class SIMPLNX_EXPORT TetrahedralGeomIO : public INodeGeom3dIO Result<> readData(DataStructureReader& dataStructureReader, const group_reader_type& parentGroup, const std::string& geomName, DataObject::IdType importId, const std::optional& parentId, bool useEmptyDataStore = false) const override; + Result<> finishImportingData(DataStructure& dataStructure, const DataPath& dataPath, const group_reader_type& dataStructureGroup) const override; + /** * @brief Attempts to write an TetrahedralGeom to HDF5. * @param dataStructureWriter diff --git a/src/simplnx/DataStructure/IO/HDF5/TriangleGeomIO.cpp b/src/simplnx/DataStructure/IO/HDF5/TriangleGeomIO.cpp index 2cba9c3208..888d698945 100644 --- a/src/simplnx/DataStructure/IO/HDF5/TriangleGeomIO.cpp +++ b/src/simplnx/DataStructure/IO/HDF5/TriangleGeomIO.cpp @@ -27,6 +27,17 @@ Result<> TriangleGeomIO::readData(DataStructureReader& structureReader, const gr auto* geometry = TriangleGeom::Import(structureReader.getDataStructure(), objectName, importId, parentId); return INodeGeom2dIO::ReadNodeGeom2dData(structureReader, *geometry, parentGroup, objectName, importId, parentId, useEmptyDataStore); } + +Result<> TriangleGeomIO::finishImportingData(DataStructure& dataStructure, const DataPath& dataPath, const group_reader_type& dataStructureGroup) const +{ + auto* geom = dataStructure.getDataAs(dataPath); + if(geom == nullptr) + { + return MakeErrorResult(-50595, fmt::format("Failed to finish importing TriangleGeom at path '{}'. Data not found or of incorrect type.", dataPath.toString())); + } + return INodeGeom2dIO::FinishImportingNodeGeom2dData(dataStructure, dataPath, dataStructureGroup); +} + Result<> TriangleGeomIO::writeData(DataStructureWriter& dataStructureWriter, const TriangleGeom& geometry, group_writer_type& parentGroupWriter, bool importable) const { return INodeGeom2dIO::WriteNodeGeom2dData(dataStructureWriter, geometry, parentGroupWriter, importable); diff --git a/src/simplnx/DataStructure/IO/HDF5/TriangleGeomIO.hpp b/src/simplnx/DataStructure/IO/HDF5/TriangleGeomIO.hpp index 9bb62b5834..24162823ed 100644 --- a/src/simplnx/DataStructure/IO/HDF5/TriangleGeomIO.hpp +++ b/src/simplnx/DataStructure/IO/HDF5/TriangleGeomIO.hpp @@ -30,6 +30,8 @@ class SIMPLNX_EXPORT TriangleGeomIO : public INodeGeom3dIO Result<> readData(DataStructureReader& dataStructureReader, const group_reader_type& parentGroup, const std::string& geomName, DataObject::IdType importId, const std::optional& parentId, bool useEmptyDataStore = false) const override; + Result<> finishImportingData(DataStructure& dataStructure, const DataPath& dataPath, const group_reader_type& dataStructureGroup) const override; + /** * @brief Attempts to write an TriangleGeom to HDF5. * @param dataStructureWriter diff --git a/src/simplnx/DataStructure/IO/HDF5/VertexGeomIO.cpp b/src/simplnx/DataStructure/IO/HDF5/VertexGeomIO.cpp index 55eaffbd13..7491a0c358 100644 --- a/src/simplnx/DataStructure/IO/HDF5/VertexGeomIO.cpp +++ b/src/simplnx/DataStructure/IO/HDF5/VertexGeomIO.cpp @@ -26,6 +26,17 @@ Result<> VertexGeomIO::readData(DataStructureReader& dataStructureReader, const auto* geometry = VertexGeom::Import(dataStructureReader.getDataStructure(), objectName, importId, parentId); return INodeGeom0dIO::ReadNodeGeom0dData(dataStructureReader, *geometry, parentGroup, objectName, importId, parentId, useEmptyDataStore); } + +Result<> VertexGeomIO::finishImportingData(DataStructure& dataStructure, const DataPath& dataPath, const group_reader_type& dataStructureGroup) const +{ + auto* geom = dataStructure.getDataAs(dataPath); + if(geom == nullptr) + { + return MakeErrorResult(-50595, fmt::format("Failed to finish importing VertexGeom at path '{}'. Data not found or of incorrect type.", dataPath.toString())); + } + return INodeGeom0dIO::FinishImportingNodeGeom0dData(dataStructure, dataPath, dataStructureGroup); +} + Result<> VertexGeomIO::writeData(DataStructureWriter& structureReader, const VertexGeom& geometry, group_writer_type& parentGroupWriter, bool importable) const { return INodeGeom0dIO::WriteNodeGeom0dData(structureReader, geometry, parentGroupWriter, importable); diff --git a/src/simplnx/DataStructure/IO/HDF5/VertexGeomIO.hpp b/src/simplnx/DataStructure/IO/HDF5/VertexGeomIO.hpp index 8578d35f09..566dae96ef 100644 --- a/src/simplnx/DataStructure/IO/HDF5/VertexGeomIO.hpp +++ b/src/simplnx/DataStructure/IO/HDF5/VertexGeomIO.hpp @@ -30,6 +30,8 @@ class SIMPLNX_EXPORT VertexGeomIO : public INodeGeom0dIO Result<> readData(DataStructureReader& dataStructureReader, const group_reader_type& parentGroup, const std::string& geomName, DataObject::IdType importId, const std::optional& parentId, bool useEmptyDataStore = false) const override; + Result<> finishImportingData(DataStructure& dataStructure, const DataPath& dataPath, const group_reader_type& dataStructureGroup) const override; + /** * @brief Attempts to write an VertexGeom to HDF5. * @param dataStructureWriter diff --git a/src/simplnx/DataStructure/ListStore.hpp b/src/simplnx/DataStructure/ListStore.hpp index eaed4bc5f2..a5135ad6f5 100644 --- a/src/simplnx/DataStructure/ListStore.hpp +++ b/src/simplnx/DataStructure/ListStore.hpp @@ -1,6 +1,7 @@ #pragma once #include "simplnx/DataStructure/AbstractListStore.hpp" +#include "simplnx/Utilities/Parsing/HDF5/IO/DatasetIO.hpp" #include #include @@ -258,7 +259,30 @@ class ListStore : public AbstractListStore m_Array = lists; } + void readHdf5(const HDF5::DatasetIO& datasetReader) override + { + throw std::runtime_error("ListStore cannot read from HDF5"); + } + + void writeHdf5(HDF5::DatasetIO& datasetReader) override + { + throw std::runtime_error("ListStore cannot write to HDF5"); + } + private: std::vector> m_Array; }; + +using UInt8ListStore = ListStore; +using UInt16ListStore = ListStore; +using UInt32ListStore = ListStore; +using UInt64ListStore = ListStore; + +using Int8ListStore = ListStore; +using Int16ListStore = ListStore; +using Int32ListStore = ListStore; +using Int64ListStore = ListStore; + +using Float32ListStore = ListStore; +using Float64ListStore = ListStore; } // namespace nx::core diff --git a/src/simplnx/DataStructure/NeighborList.cpp b/src/simplnx/DataStructure/NeighborList.cpp index 3b5dd77460..a5a2cebe0b 100644 --- a/src/simplnx/DataStructure/NeighborList.cpp +++ b/src/simplnx/DataStructure/NeighborList.cpp @@ -25,6 +25,24 @@ NeighborList::NeighborList(DataStructure& dataStructure, const std::string& n { } +template +NeighborList::NeighborList(DataStructure& dataStructure, const std::string& name, const std::shared_ptr& dataStore, IdType importId) +: INeighborList(dataStructure, name, dataStore->size(), importId) +, m_Store(dataStore) +, m_IsAllocated(true) +, m_InitValue(static_cast(0.0)) +{ +} + +template +NeighborList::NeighborList(DataStructure& dataStructure, const std::string& name, const std::shared_ptr& dataStore) +: INeighborList(dataStructure, name, dataStore->size()) +, m_Store(dataStore) +, m_IsAllocated(true) +, m_InitValue(static_cast(0.0)) +{ +} + template NeighborList* NeighborList::Create(DataStructure& dataStructure, const std::string& name, usize numTuples, const std::optional& parentId) { @@ -36,6 +54,22 @@ NeighborList* NeighborList::Create(DataStructure& dataStructure, const std return data.get(); } +template +NeighborList* NeighborList::Create(DataStructure& dataStructure, const std::string& name, const std::shared_ptr& listStore, const std::optional& parentId) +{ + if(listStore == nullptr) + { + return nullptr; + } + + auto data = std::shared_ptr(new NeighborList(dataStructure, name, listStore)); + if(!AttemptToAddObject(dataStructure, data, parentId)) + { + return nullptr; + } + return data.get(); +} + template NeighborList* NeighborList::Import(DataStructure& dataStructure, const std::string& name, IdType importId, const std::vector& dataVector, const std::optional& parentId) { @@ -47,6 +81,17 @@ NeighborList* NeighborList::Import(DataStructure& dataStructure, const std return data.get(); } +template +NeighborList* NeighborList::Import(DataStructure& dataStructure, const std::string& name, IdType importId, const std::shared_ptr& dataStore, const std::optional& parentId) +{ + auto data = std::shared_ptr(new NeighborList(dataStructure, name, dataStore, importId)); + if(!AttemptToAddObject(dataStructure, data, parentId)) + { + return nullptr; + } + return data.get(); +} + template NeighborList::NeighborList(const NeighborList& other) : INeighborList(other) @@ -396,6 +441,12 @@ std::shared_ptr::store_type> NeighborList::getStore( return m_Store; } +template +void NeighborList::setStore(const std::shared_ptr& store) +{ + m_Store = store; +} + template std::vector::VectorType> NeighborList::getVectors() const { diff --git a/src/simplnx/DataStructure/NeighborList.hpp b/src/simplnx/DataStructure/NeighborList.hpp index 811b885817..94603af9c0 100644 --- a/src/simplnx/DataStructure/NeighborList.hpp +++ b/src/simplnx/DataStructure/NeighborList.hpp @@ -43,6 +43,17 @@ class NeighborList : public INeighborList */ static NeighborList* Create(DataStructure& dataStructure, const std::string& name, usize numTuples, const std::optional& parentId = {}); + /** + * @brief + * @param dataStructure + * @param name + * @param numTuples + * @param parentId = {} + * @tparam T + * @return NeighborList* + */ + static NeighborList* Create(DataStructure& dataStructure, const std::string& name, const std::shared_ptr& listStore, const std::optional& parentId = {}); + /** * @brief * @param dataStructure @@ -54,6 +65,17 @@ class NeighborList : public INeighborList */ static NeighborList* Import(DataStructure& dataStructure, const std::string& name, IdType importId, const std::vector& data, const std::optional& parentId = {}); + /** + * @brief + * @param dataStructure + * @param name + * @param importId + * @param storeData + * @param parentId + * @return NeighborList* + */ + static NeighborList* Import(DataStructure& dataStructure, const std::string& name, IdType importId, const std::shared_ptr& storeData, const std::optional& parentId = {}); + ~NeighborList() override = default; /** @@ -363,6 +385,12 @@ class NeighborList : public INeighborList */ std::shared_ptr getStore() const; + /** + * @brief Replaces the AbstractListStore used to store values. + * @param store + */ + void setStore(const std::shared_ptr& store); + /** * @brief Returns a vector of vectors containing the current values. */ @@ -384,11 +412,21 @@ class NeighborList : public INeighborList */ NeighborList(DataStructure& dataStructure, const std::string& name, usize numTuples); + /** + * @brief NeighborList + */ + NeighborList(DataStructure& dataStructure, const std::string& name, const std::shared_ptr& dataStore); + /** * @brief NeighborList */ NeighborList(DataStructure& dataStructure, const std::string& name, const std::vector& dataVector, IdType importId); + /** + * @brief NeighborList + */ + NeighborList(DataStructure& dataStructure, const std::string& name, const std::shared_ptr& listStore, IdType importId); + private: std::shared_ptr m_Store; bool m_IsAllocated; diff --git a/src/simplnx/DataStructure/StringArray.cpp b/src/simplnx/DataStructure/StringArray.cpp index efbc406bc5..fc1e6c7f70 100644 --- a/src/simplnx/DataStructure/StringArray.cpp +++ b/src/simplnx/DataStructure/StringArray.cpp @@ -234,4 +234,8 @@ void StringArray::swapTuples(usize index0, usize index1) (*m_Strings)[index1] = value; } +void StringArray::setStore(const std::shared_ptr& newStore) +{ + m_Strings = newStore; +} } // namespace nx::core diff --git a/src/simplnx/DataStructure/StringArray.hpp b/src/simplnx/DataStructure/StringArray.hpp index 6a0adc3882..db3d1c9289 100644 --- a/src/simplnx/DataStructure/StringArray.hpp +++ b/src/simplnx/DataStructure/StringArray.hpp @@ -124,6 +124,8 @@ class SIMPLNX_EXPORT StringArray : public IArray */ void resizeTuples(const std::vector& tupleShape) override; + void setStore(const std::shared_ptr& newStore); + protected: StringArray(DataStructure& dataStructure, std::string name); StringArray(DataStructure& dataStructure, std::string name, collection_type strings); diff --git a/src/simplnx/Filter/Actions/ImportH5ObjectPathsAction.cpp b/src/simplnx/Filter/Actions/ImportH5ObjectPathsAction.cpp index 8d7d0f14d7..6379440d1c 100644 --- a/src/simplnx/Filter/Actions/ImportH5ObjectPathsAction.cpp +++ b/src/simplnx/Filter/Actions/ImportH5ObjectPathsAction.cpp @@ -41,7 +41,7 @@ Result<> ImportH5ObjectPathsAction::apply(DataStructure& dataStructure, Mode mod bool preflighting = (mode == Mode::Preflight); auto fileReader = nx::core::HDF5::FileIO::ReadFile(m_H5FilePath); - Result dataStructureResult = DREAM3D::ImportDataStructureFromFile(fileReader, preflighting); + Result dataStructureResult = DREAM3D::ImportDataStructureFromFile(fileReader, true); if(dataStructureResult.invalid()) { return ConvertResult(std::move(dataStructureResult)); @@ -67,15 +67,17 @@ Result<> ImportH5ObjectPathsAction::apply(DataStructure& dataStructure, Mode mod importGroup->clear(); } - if(dataStructure.getDataAs(targetPath) != nullptr) - { - return MakeErrorResult(-6203, fmt::format("{}Unable to import DataObject at '{}' because an object already exists there. Consider a rename of existing object.", prefix, targetPath.toString())); - } - if(!dataStructure.insert(importData, targetPath.getParent())) { return MakeErrorResult(k_InsertFailureError, fmt::format("{}Unable to import DataObject at '{}'", prefix, targetPath.toString())); } + if(mode == Mode::Execute) + { + if(auto result = DREAM3D::FinishImportingObject(dataStructure, targetPath, fileReader); result.invalid()) + { + return result; + } + } } if(!errorMessages.str().empty()) { diff --git a/src/simplnx/Utilities/DataStoreUtilities.hpp b/src/simplnx/Utilities/DataStoreUtilities.hpp index baf8cb8c6e..f0da633f1c 100644 --- a/src/simplnx/Utilities/DataStoreUtilities.hpp +++ b/src/simplnx/Utilities/DataStoreUtilities.hpp @@ -4,6 +4,7 @@ #include "simplnx/DataStructure/AbstractDataStore.hpp" #include "simplnx/DataStructure/EmptyDataStore.hpp" +#include "simplnx/DataStructure/EmptyListStore.hpp" #include "simplnx/DataStructure/IO/Generic/DataIOCollection.hpp" #include "simplnx/Filter/Output.hpp" @@ -62,6 +63,27 @@ std::shared_ptr> CreateDataStore(const typename IDataStore: } } +template +std::shared_ptr> CreateListStore(usize tupleCount, IDataAction::Mode mode = IDataAction::Mode::Execute, std::string dataFormat = "") +{ + switch(mode) + { + case IDataAction::Mode::Preflight: { + return std::make_unique>(tupleCount); + } + case IDataAction::Mode::Execute: { + uint64 dataSize = CalculateDataSize({tupleCount}, {10}); + TryForceLargeDataFormatFromPrefs(dataFormat); + auto ioCollection = GetIOCollection(); + ioCollection->checkStoreDataFormat(dataSize, dataFormat); + return ioCollection->createListStoreWithType(dataFormat, tupleCount); + } + default: { + throw std::runtime_error("Invalid mode"); + } + } +} + template std::shared_ptr> ConvertDataStore(const AbstractDataStore& dataStore, const std::string& dataFormat) { diff --git a/src/simplnx/Utilities/Parsing/DREAM3D/Dream3dIO.cpp b/src/simplnx/Utilities/Parsing/DREAM3D/Dream3dIO.cpp index 38b7754e4a..1cc96fd16e 100644 --- a/src/simplnx/Utilities/Parsing/DREAM3D/Dream3dIO.cpp +++ b/src/simplnx/Utilities/Parsing/DREAM3D/Dream3dIO.cpp @@ -16,9 +16,11 @@ #include "simplnx/DataStructure/Geometry/VertexGeom.hpp" #include "simplnx/DataStructure/IO/HDF5/DataStructureReader.hpp" #include "simplnx/DataStructure/IO/HDF5/DataStructureWriter.hpp" +#include "simplnx/DataStructure/IO/HDF5/IDataStoreIO.hpp" #include "simplnx/DataStructure/IO/HDF5/NeighborListIO.hpp" #include "simplnx/DataStructure/NeighborList.hpp" #include "simplnx/DataStructure/StringArray.hpp" +#include "simplnx/DataStructure/StringStore.hpp" #include "simplnx/Pipeline/Pipeline.hpp" #include "simplnx/Utilities/Parsing/HDF5/IO/FileIO.hpp" @@ -884,6 +886,19 @@ Result<> readLegacyStringArray(DataStructure& dataStructure, const nx::core::HDF return {}; } +Result<> finishImportingLegacyStringArray(DataStructure& dataStructure, const nx::core::HDF5::DatasetIO& dataArrayReader, const DataPath& dataPath) +{ + auto* existingArray = dataStructure.getDataAs(dataPath); + if(existingArray == nullptr) + { + return MakeErrorResult(-4210428, fmt::format("Failed to finish importing legacy StringArray at path '{}'. Imported StringArray not found.", dataPath.toString())); + } + + const std::vector strings = dataArrayReader.readAsVectorOfStrings(); + existingArray->setStore(std::make_shared(strings)); + return {}; +} + Result readLegacyDataArray(DataStructure& dataStructure, const nx::core::HDF5::DatasetIO& dataArrayReader, DataObject::IdType parentId, bool preflight = false) { auto dataTypeResult = dataArrayReader.getDataType(); @@ -958,6 +973,90 @@ Result readLegacyDataArray(DataStructure& dataStructure, const nx:: return daResult; } +template +Result<> finishImportingLegacyDataArrayImpl(DataStructure& dataStructure, const HDF5::DatasetIO& dataSetIO, const DataPath& dataPath) +{ + auto* existingArray = dataStructure.getDataAs>(dataPath); + if(existingArray == nullptr) + { + return MakeErrorResult(-4210423, fmt::format("Failed to finish importing legacy DataArray at path '{}'. Imported DataArray not found.", dataPath.toString())); + } + + auto tupleShape = nx::core::HDF5::IDataStoreIO::ReadTupleShape(dataSetIO); + auto componentShape = nx::core::HDF5::IDataStoreIO::ReadComponentShape(dataSetIO); + + auto dataStorePtr = dataSetIO.readAsDataStore(tupleShape, componentShape); + if(dataStorePtr == nullptr) + { + return MakeErrorResult(-4210424, fmt::format("Failed to finish importing legacy DataArray at path '{}'. Could not import data from HDF5.", dataPath.toString())); + } + + existingArray->setDataStore(dataStorePtr); + return {}; +} + +Result<> finishImportingLegacyDataArray(DataStructure& dataStructure, const HDF5::DatasetIO& dataSetIO, const DataPath& dataPath) +{ + auto dataTypeResult = dataSetIO.getDataType(); + if(dataTypeResult.invalid()) + { + auto errors = dataTypeResult.errors(); + return MakeErrorResult(errors[0].code, errors[0].message); + } + auto dataType = std::move(dataTypeResult.value()); + switch(dataType) + { + case DataType::float32: + return finishImportingLegacyDataArrayImpl(dataStructure, dataSetIO, dataPath); + case DataType::float64: + return finishImportingLegacyDataArrayImpl(dataStructure, dataSetIO, dataPath); + break; + case DataType::int8: + return finishImportingLegacyDataArrayImpl(dataStructure, dataSetIO, dataPath); + break; + case DataType::int16: + return finishImportingLegacyDataArrayImpl(dataStructure, dataSetIO, dataPath); + break; + case DataType::int32: + return finishImportingLegacyDataArrayImpl(dataStructure, dataSetIO, dataPath); + break; + case DataType::int64: + return finishImportingLegacyDataArrayImpl(dataStructure, dataSetIO, dataPath); + break; + case DataType::boolean: + [[fallthrough]]; + case DataType::uint8: { + std::string typeTag; + auto typeTagResult = dataSetIO.readStringAttribute(Constants::k_ObjectTypeTag); + if(typeTagResult.invalid()) + { + return ConvertInvalidResult(std::move(typeTagResult)); + } + typeTag = std::move(typeTagResult.value()); + if(typeTag == "DataArray") + { + return finishImportingLegacyDataArrayImpl(dataStructure, dataSetIO, dataPath); + } + else + { + return finishImportingLegacyDataArrayImpl(dataStructure, dataSetIO, dataPath); + } + break; + } + case DataType::uint16: + return finishImportingLegacyDataArrayImpl(dataStructure, dataSetIO, dataPath); + break; + case DataType::uint32: + return finishImportingLegacyDataArrayImpl(dataStructure, dataSetIO, dataPath); + break; + case DataType::uint64: + return finishImportingLegacyDataArrayImpl(dataStructure, dataSetIO, dataPath); + break; + } + + return {}; +} + Result readLegacyNodeConnectivityList(DataStructure& dataStructure, IGeometry* geometry, const HDF5::GroupIO& geomGroup, const std::string& arrayName, bool preflight = false) { HDF5::DatasetIO dataArrayReader = geomGroup.openDataset(arrayName); @@ -987,16 +1086,13 @@ template Result<> createLegacyNeighborList(DataStructure& dataStructure, DataObject ::IdType parentId, const nx::core::HDF5::GroupIO& parentReader, const nx::core::HDF5::DatasetIO& datasetReader, const std::vector& tupleDims) { - auto numTuples = std::accumulate(tupleDims.cbegin(), tupleDims.cend(), static_cast(1), std::multiplies<>()); - - auto data = HDF5::NeighborListIO::ReadHdf5Data(parentReader, datasetReader); - auto* neighborList = NeighborList::Create(dataStructure, datasetReader.getName(), numTuples, parentId); + auto listStore = HDF5::NeighborListIO::ReadHdf5Data(parentReader, datasetReader); + auto* neighborList = NeighborList::Create(dataStructure, datasetReader.getName(), listStore, parentId); if(neighborList == nullptr) { std::string ss = fmt::format("Failed to create NeighborList: '{}'", datasetReader.getName()); return MakeErrorResult(Legacy::k_FailedCreatingNeighborList_Code, ss); } - neighborList->getStore()->setData(data); return {}; } @@ -1054,6 +1150,71 @@ Result<> readLegacyNeighborList(DataStructure& dataStructure, const nx::core::HD return result; } +template +Result<> finishImportingLegacyNeighborListImpl(DataStructure& dataStructure, const nx::core::HDF5::GroupIO& parentReader, const HDF5::DatasetIO& datasetReader, const DataPath& dataPath) +{ + auto* existingList = dataStructure.getDataAs>(dataPath); + if(existingList == nullptr) + { + return MakeErrorResult(-4210426, fmt::format("Failed to finish importing legacy NeighborList at path '{}'. Imported NeighborList not found.", dataPath.toString())); + } + + auto listStore = HDF5::NeighborListIO::ReadHdf5Data(parentReader, datasetReader); + if(listStore == nullptr) + { + return MakeErrorResult(-4210427, fmt::format("Failed to finish importing legacy NeighborList at path '{}'. Failed to import HDF5 data.", dataPath.toString())); + } + existingList->setStore(listStore); + return {}; +} + +Result<> finishImportingLegacyNeighborList(DataStructure& dataStructure, const nx::core::HDF5::GroupIO& parentReader, const HDF5::DatasetIO& datasetReader, const DataPath& dataPath) +{ + auto dataTypeResult = datasetReader.getDataType(); + if(dataTypeResult.invalid()) + { + return ConvertResult(std::move(dataTypeResult)); + } + auto dataType = dataTypeResult.value(); + switch(dataType) + { + case DataType::float32: + return finishImportingLegacyNeighborListImpl(dataStructure, parentReader, datasetReader, dataPath); + break; + case DataType::float64: + return finishImportingLegacyNeighborListImpl(dataStructure, parentReader, datasetReader, dataPath); + break; + case DataType::boolean: + [[fallthrough]]; + case DataType::int8: + return finishImportingLegacyNeighborListImpl(dataStructure, parentReader, datasetReader, dataPath); + break; + case DataType::int16: + return finishImportingLegacyNeighborListImpl(dataStructure, parentReader, datasetReader, dataPath); + break; + case DataType::int32: + return finishImportingLegacyNeighborListImpl(dataStructure, parentReader, datasetReader, dataPath); + break; + case DataType::int64: + return finishImportingLegacyNeighborListImpl(dataStructure, parentReader, datasetReader, dataPath); + break; + case DataType::uint8: + return finishImportingLegacyNeighborListImpl(dataStructure, parentReader, datasetReader, dataPath); + break; + case DataType::uint16: + return finishImportingLegacyNeighborListImpl(dataStructure, parentReader, datasetReader, dataPath); + break; + case DataType::uint32: + return finishImportingLegacyNeighborListImpl(dataStructure, parentReader, datasetReader, dataPath); + break; + case DataType::uint64: + return finishImportingLegacyNeighborListImpl(dataStructure, parentReader, datasetReader, dataPath); + break; + } + + return MakeErrorResult(-4210429, fmt::format("Failed to finish importing legacy NeighborList at path '{}'. Type could not be determined", dataPath.toString())); +} + bool isLegacyNeighborList(const nx::core::HDF5::DatasetIO& arrayReader) { auto objectTypeResult = arrayReader.readStringAttribute("ObjectType"); @@ -1074,7 +1235,43 @@ bool isLegacyStringArray(const nx::core::HDF5::DatasetIO& arrayReader) return objectTypeResult.value() == "StringDataArray"; } -Result<> readLegacyAttributeMatrix(DataStructure& dataStructure, const nx::core::HDF5::GroupIO& amGroupReader, DataObject& parent, bool preflight = false) +Result<> readLegacyArray(DataStructure& dataStructure, const nx::core::HDF5::GroupIO& amGroupReader, const std::string& arrayName, bool preflight) +{ + auto dataArraySet = amGroupReader.openDataset(arrayName); + if(isLegacyNeighborList(dataArraySet)) + { + return readLegacyNeighborList(dataStructure, amGroupReader, dataArraySet, 0); + } + else if(isLegacyStringArray(dataArraySet)) + { + return readLegacyStringArray(dataStructure, dataArraySet, preflight); + } + else + { + return ConvertResult<>(std::move(readLegacyDataArray(dataStructure, dataArraySet, preflight))); + } +} + +Result<> finishImportingLegacyArray(DataStructure& dataStructure, const nx::core::HDF5::GroupIO& parentReader, const DataPath& dataPath) +{ + auto dcGroup = parentReader.openGroup(dataPath[0]); + auto amGroup = dcGroup.openGroup(dataPath[1]); + auto dataArraySet = amGroup.openDataset(dataPath.getTargetName()); + if(isLegacyNeighborList(dataArraySet)) + { + return finishImportingLegacyNeighborList(dataStructure, parentReader, dataArraySet, dataPath); + } + else if(isLegacyStringArray(dataArraySet)) + { + return finishImportingLegacyStringArray(dataStructure, dataArraySet, dataPath); + } + else + { + return finishImportingLegacyDataArray(dataStructure, dataArraySet, dataPath); + } +} + +Result<> readLegacyAttributeMatrix(DataStructure& dataStructure, const nx::core::HDF5::GroupIO& amGroupReader, DataObject& parent, bool preflight = false, bool importChildren = true) { DataObject::IdType parentId = parent.getId(); const std::string amName = amGroupReader.getName(); @@ -1090,10 +1287,12 @@ Result<> readLegacyAttributeMatrix(DataStructure& dataStructure, const nx::core: auto* attributeMatrix = AttributeMatrix::Create(dataStructure, amName, reversedTDims, parentId); std::vector> daResults; - auto dataArrayNames = amGroupReader.getChildNames(); - for(const auto& daName : dataArrayNames) + if(importChildren) { - auto dataArraySet = amGroupReader.openDataset(daName); + auto dataArrayNames = amGroupReader.getChildNames(); + for(const auto& daName : dataArrayNames) + { + auto dataArraySet = amGroupReader.openDataset(daName); #if 0 if(!dataArraySet.isValid()) { @@ -1104,18 +1303,19 @@ Result<> readLegacyAttributeMatrix(DataStructure& dataStructure, const nx::core: } #endif - if(isLegacyNeighborList(dataArraySet)) - { - daResults.push_back(readLegacyNeighborList(dataStructure, amGroupReader, dataArraySet, attributeMatrix->getId())); - } - else if(isLegacyStringArray(dataArraySet)) - { - daResults.push_back(readLegacyStringArray(dataStructure, dataArraySet, attributeMatrix->getId(), preflight)); - } - else - { - Result<> result = ConvertResult(readLegacyDataArray(dataStructure, dataArraySet, attributeMatrix->getId(), preflight)); - daResults.push_back(result); + if(isLegacyNeighborList(dataArraySet)) + { + daResults.push_back(readLegacyNeighborList(dataStructure, amGroupReader, dataArraySet, attributeMatrix->getId())); + } + else if(isLegacyStringArray(dataArraySet)) + { + daResults.push_back(readLegacyStringArray(dataStructure, dataArraySet, attributeMatrix->getId(), preflight)); + } + else + { + Result<> result = ConvertResult(readLegacyDataArray(dataStructure, dataArraySet, attributeMatrix->getId(), preflight)); + daResults.push_back(result); + } } } @@ -1333,7 +1533,7 @@ DataObject* readLegacyImageGeom(DataStructure& dataStructure, const nx::core::HD } // End legacy Geometry importing -Result<> readLegacyDataContainer(DataStructure& dataStructure, const nx::core::HDF5::GroupIO& dcGroup, bool preflight = false) +Result<> readLegacyDataContainer(DataStructure& dataStructure, const nx::core::HDF5::GroupIO& dcGroup, bool preflight = false, bool importChildren = true) { DataObject* container = nullptr; const std::string dcName = dcGroup.getName(); @@ -1355,31 +1555,31 @@ Result<> readLegacyDataContainer(DataStructure& dataStructure, const nx::core::H } else if(geomName == Legacy::Type::EdgeGeom) { - container = readLegacyEdgeGeom(dataStructure, geomGroup, dcName, preflight); + container = readLegacyEdgeGeom(dataStructure, geomGroup, dcName, false); } else if(geomName == Legacy::Type::HexGeom) { - container = readLegacyHexGeom(dataStructure, geomGroup, dcName, preflight); + container = readLegacyHexGeom(dataStructure, geomGroup, dcName, false); } else if(geomName == Legacy::Type::QuadGeom) { - container = readLegacyQuadGeom(dataStructure, geomGroup, dcName, preflight); + container = readLegacyQuadGeom(dataStructure, geomGroup, dcName, false); } else if(geomName == Legacy::Type::RectGridGeom) { - container = readLegacyRectGridGeom(dataStructure, geomGroup, dcName, preflight); + container = readLegacyRectGridGeom(dataStructure, geomGroup, dcName, false); } else if(geomName == Legacy::Type::TetrahedralGeom) { - container = readLegacyTetrahedralGeom(dataStructure, geomGroup, dcName, preflight); + container = readLegacyTetrahedralGeom(dataStructure, geomGroup, dcName, false); } else if(geomName == Legacy::Type::TriangleGeom) { - container = readLegacyTriangleGeom(dataStructure, geomGroup, dcName, preflight); + container = readLegacyTriangleGeom(dataStructure, geomGroup, dcName, false); } else if(geomName == Legacy::Type::VertexGeom) { - container = readLegacyVertexGeom(dataStructure, geomGroup, dcName, preflight); + container = readLegacyVertexGeom(dataStructure, geomGroup, dcName, false); } } @@ -1389,6 +1589,11 @@ Result<> readLegacyDataContainer(DataStructure& dataStructure, const nx::core::H container = DataGroup::Create(dataStructure, dcName); } + if(!importChildren) + { + return {}; + } + std::vector> amResults; auto attribMatrixNames = dcGroup.getChildNames(); for(const auto& amName : attribMatrixNames) @@ -1405,6 +1610,234 @@ Result<> readLegacyDataContainer(DataStructure& dataStructure, const nx::core::H return nx::core::MergeResults(amResults); } +Result<> finishImportingLegacyImageGeom(DataStructure& dataStructure, IGeometry* geometry, const HDF5::GroupIO& geometryReader) +{ + auto* imageGeom = dynamic_cast(geometry); + if(imageGeom == nullptr) + { + return MakeErrorResult(-502678, "Failed to finish importing legacy Image Geometry. Existing geometry is not of the correct type"); + } + + return {}; +} + +Result<> finishImportingLegacyEdgeGeom(DataStructure& dataStructure, IGeometry* geometryPtr, const HDF5::GroupIO& geomGroup) +{ + auto* edgeGeom = dynamic_cast(geometryPtr); + if(edgeGeom == nullptr) + { + return MakeErrorResult(-502677, "Failed to finish importing legacy Edge Geometry. Existing geometry is not of the correct type"); + } + + readGenericGeomDims(edgeGeom, geomGroup); + return {}; +} + +Result<> finishImportingLegacyHexGeom(DataStructure& dataStructure, IGeometry* geometryPtr, const HDF5::GroupIO& geomGroup) +{ + auto* hexGeom = dynamic_cast(geometryPtr); + if(hexGeom == nullptr) + { + return MakeErrorResult(-502676, "Failed to finish importing legacy Hex Geometry. Existing geometry is not of the correct type"); + } + + readGenericGeomDims(hexGeom, geomGroup); + return {}; +} + +Result<> finishImportingLegacyQuadGeom(DataStructure& dataStructure, IGeometry* geometryPtr, const HDF5::GroupIO& geomGroup) +{ + auto* quadGeom = dynamic_cast(geometryPtr); + if(quadGeom == nullptr) + { + return MakeErrorResult(-502675, "Failed to finish importing legacy Quad Geometry. Existing geometry is not of the correct type"); + } + + readGenericGeomDims(quadGeom, geomGroup); + return {}; +} + +Result<> finishImportingLegacyRectGridGeom(DataStructure& dataStructure, IGeometry* geometryPtr, const HDF5::GroupIO& geomGroup) +{ + auto* rectGridGeom = dynamic_cast(geometryPtr); + if(rectGridGeom == nullptr) + { + return MakeErrorResult(-502674, "Failed to finish importing legacy RectGrid Geometry. Existing geometry is not of the correct type"); + } + + readGenericGeomDims(rectGridGeom, geomGroup); + + // DIMENSIONS array + { + auto dimsDataset = geomGroup.openDataset("DIMENSIONS"); + auto dims = dimsDataset.readAsVector(); + rectGridGeom->setDimensions(SizeVec3(dims[0], dims[1], dims[2])); + } + + return {}; +} + +Result<> finishImportingLegacyTetrahedralGeom(DataStructure& dataStructure, IGeometry* geometryPtr, const HDF5::GroupIO& geomGroup) +{ + auto* tetrahedralGeom = dynamic_cast(geometryPtr); + if(tetrahedralGeom == nullptr) + { + return MakeErrorResult(-502673, "Failed to finish importing legacy Tetrahedral Geometry. Existing geometry is not of the correct type"); + } + + readGenericGeomDims(tetrahedralGeom, geomGroup); + return {}; +} + +Result<> finishImportingLegacyTriangleGeom(DataStructure& dataStructure, IGeometry* geometryPtr, const HDF5::GroupIO& geomGroup) +{ + auto* triangleGeom = dynamic_cast(geometryPtr); + if(triangleGeom == nullptr) + { + return MakeErrorResult(-502672, "Failed to finish importing legacy Triangle Geometry. Existing geometry is not of the correct type"); + } + + readGenericGeomDims(triangleGeom, geomGroup); + return {}; +} + +Result<> finishImportingLegacyVertexGeom(DataStructure& dataStructure, IGeometry* geometryPtr, const HDF5::GroupIO& geomGroup) +{ + auto* vertexGeom = dynamic_cast(geometryPtr); + if(vertexGeom == nullptr) + { + return MakeErrorResult(-502671, "Failed to finish importing legacy Vertex Geometry. Existing geometry is not of the correct type"); + } + + readGenericGeomDims(vertexGeom, geomGroup); + return {}; +} + +Result<> finishImportingLegacyDataContainer(DataStructure& dataStructure, const HDF5::GroupIO& parentReader, const DataPath& dataPath) +{ + std::string dcName = dataPath[0]; + auto dcGroup = parentReader.openGroup(dcName); + + // Check for geometry + auto geomGroup = dcGroup.openGroup(Legacy::GeometryTag.c_str()); + if(geomGroup.isValid()) + { + auto* geometryPtr = dataStructure.getDataAs(dataPath); + if(geometryPtr == nullptr) + { + return MakeErrorResult(-502679, fmt::format("Failed to finish importing of geometry at path '{}'. Existing geometry not found.", dataPath.toString())); + } + + std::string geomName; + auto geomNameResult = geomGroup.readStringAttribute(Legacy::GeometryTypeNameTag); + if(geomNameResult.invalid()) + { + return ConvertResult(std::move(geomNameResult)); + } + geomName = std::move(geomNameResult.value()); + if(geomName == Legacy::Type::ImageGeom) + { + return finishImportingLegacyImageGeom(dataStructure, geometryPtr, geomGroup); + } + else if(geomName == Legacy::Type::EdgeGeom) + { + return finishImportingLegacyEdgeGeom(dataStructure, geometryPtr, geomGroup); + } + else if(geomName == Legacy::Type::HexGeom) + { + return finishImportingLegacyHexGeom(dataStructure, geometryPtr, geomGroup); + } + else if(geomName == Legacy::Type::QuadGeom) + { + return finishImportingLegacyQuadGeom(dataStructure, geometryPtr, geomGroup); + } + else if(geomName == Legacy::Type::RectGridGeom) + { + return finishImportingLegacyRectGridGeom(dataStructure, geometryPtr, geomGroup); + } + else if(geomName == Legacy::Type::TetrahedralGeom) + { + return finishImportingLegacyTetrahedralGeom(dataStructure, geometryPtr, geomGroup); + } + else if(geomName == Legacy::Type::TriangleGeom) + { + return finishImportingLegacyTriangleGeom(dataStructure, geometryPtr, geomGroup); + } + else if(geomName == Legacy::Type::VertexGeom) + { + return finishImportingLegacyVertexGeom(dataStructure, geometryPtr, geomGroup); + } + } + + return {}; +} + +Result>> ImportLegacyDataObjectFromFile(const nx::core::HDF5::FileIO& fileReader, const DataPath& dataPath) +{ + DataStructure dataStructure; + auto dcaGroup = fileReader.openGroup(k_LegacyDataStructureGroupTag); + + Result<> result; + switch(dataPath.getLength()) + { + case 1: { + auto dcGroup = dcaGroup.openGroup(dataPath.toString()); + result = readLegacyDataContainer(dataStructure, dcGroup, false, false); + break; + } + case 2: { + auto attributeMatrixGroup = dcaGroup.openGroup(dataPath.toString()); + DataPath dcPath({dataPath[0]}); + dataStructure.makePath(dcPath); + auto& container = dataStructure.getDataRef(dcPath); + result = readLegacyAttributeMatrix(dataStructure, attributeMatrixGroup, container, false, false); + break; + } + case 3: { + auto dcGroup = dcaGroup.openGroup(dataPath[0]); + auto attributeMatrixGroup = dcGroup.openGroup(dataPath[1]); + result = readLegacyArray(dataStructure, attributeMatrixGroup, dataPath[2], false); + break; + } + default: + return MakeErrorResult>>(-59040, + fmt::format("Failed to import DataObject at path '{}'. DataPath not supported by legacy DataStructure.", dataPath.toString())); + } + + if(result.invalid()) + { + return ConvertInvalidResult>>(std::move(result)); + } + + const DataMap& dataMap = dataStructure.getDataMap(); + if(dataMap.getSize() == 0) + { + return MakeErrorResult>>(-69040, fmt::format("Failed to import DataObject at path '{}'", dataPath.toString())); + } + + auto item = dataMap.begin(); + return {std::vector>{(*item).second}}; +} + +Result<> FinishImportingLegacyDataObject(DataStructure& dataStructure, const nx::core::HDF5::GroupIO& parentReader, const DataPath& dataPath) +{ + switch(dataPath.getLength()) + { + case 1: + finishImportingLegacyDataContainer(dataStructure, parentReader, dataPath); + break; + case 2: + break; + case 3: + finishImportingLegacyArray(dataStructure, parentReader, dataPath); + break; + default: + return MakeErrorResult(-520156, fmt::format("Could not read legacy DREAM3D data at path '{}'", dataPath.toString())); + break; + } + return {}; +} + Result ImportLegacyDataStructure(const nx::core::HDF5::FileIO& fileReader, bool preflight) { DataStructure dataStructure; @@ -1517,6 +1950,67 @@ Result DREAM3D::ImportPipelineJsonFromFile(const std::filesystem return ImportPipelineJsonFromFile(fileReader); } +Result> DREAM3D::ImportDataObjectFromFile(const nx::core::HDF5::FileIO& fileReader, const DataPath& dataPath) +{ + const auto fileVersion = GetFileVersion(fileReader); + if(fileVersion == k_CurrentFileVersion) + { + return HDF5::DataStructureReader::ReadObject(fileReader, dataPath); + } + else if(fileVersion == k_LegacyFileVersion) + { + auto result = ImportLegacyDataObjectFromFile(fileReader, dataPath); + if(result.invalid()) + { + return ConvertInvalidResult>(std::move(result)); + } + std::vector> value = result.value(); + if(value.size() != 0) + { + return MakeErrorResult>(-48264, fmt::format("Error extracting a single DataObject from legacy DREAM3D file at path '{}'", dataPath.toString())); + } + return {result.value().front()}; + } + return MakeErrorResult>(-523242, fmt::format("Error extracting a single DataObject from legacy DREAM3D file at path '{}'", dataPath.toString())); +} + +Result>> DREAM3D::ImportSelectDataObjectsFromFile(const nx::core::HDF5::FileIO& fileReader, const std::vector& dataPaths) +{ + std::vector> dataObjects; + for(const DataPath& dataPath : dataPaths) + { + auto importResult = ImportDataObjectFromFile(fileReader, dataPath); + if(importResult.invalid()) + { + return ConvertInvalidResult>>(std::move(importResult)); + } + dataObjects.push_back(std::move(importResult.value())); + } + + return {dataObjects}; +} + +Result<> DREAM3D::FinishImportingObject(DataStructure& dataStructure, const DataPath& dataPath, const nx::core::HDF5::FileIO& fileReader) +{ + auto dataPtr = dataStructure.getSharedData(dataPath); + if(dataPtr == nullptr) + { + return MakeErrorResult(-1502234, fmt::format("Cannot finish importing HDF5 data at path '{}'. DataObject does not exist to copy data into.", dataPath.toString())); + } + + const auto fileVersion = GetFileVersion(fileReader); + if(fileVersion == k_CurrentFileVersion) + { + return HDF5::DataStructureReader::FinishImportingObject(dataStructure, fileReader, dataPath); + } + else if(fileVersion == k_LegacyFileVersion) + { + auto dataStructureReader = fileReader.openGroup(k_LegacyDataStructureGroupTag); + return FinishImportingLegacyDataObject(dataStructure, dataStructureReader, dataPath); + } + return {}; +} + Result DREAM3D::ReadFile(const nx::core::HDF5::FileIO& fileReader, bool preflight) { // Pipeline pipeline; diff --git a/src/simplnx/Utilities/Parsing/DREAM3D/Dream3dIO.hpp b/src/simplnx/Utilities/Parsing/DREAM3D/Dream3dIO.hpp index e4cb31bcc6..9aa7cb44c7 100644 --- a/src/simplnx/Utilities/Parsing/DREAM3D/Dream3dIO.hpp +++ b/src/simplnx/Utilities/Parsing/DREAM3D/Dream3dIO.hpp @@ -118,6 +118,12 @@ SIMPLNX_EXPORT Result<> AppendFile(const std::filesystem::path& path, const Data */ SIMPLNX_EXPORT Result ImportDataStructureFromFile(const nx::core::HDF5::FileIO& fileReader, bool preflight = false); +SIMPLNX_EXPORT Result> ImportDataObjectFromFile(const nx::core::HDF5::FileIO& fileReader, const DataPath& dataPath); + +SIMPLNX_EXPORT Result>> ImportSelectDataObjectsFromFile(const nx::core::HDF5::FileIO& fileReader, const std::vector& dataPaths); + +SIMPLNX_EXPORT Result<> FinishImportingObject(DataStructure& dataStructure, const DataPath& dataPath, const nx::core::HDF5::FileIO& fileReader); + /** * @brief Imports and returns the DataStructure from the target .dream3d file. * This method imports both current and legacy DataStructures. diff --git a/src/simplnx/Utilities/Parsing/HDF5/IO/DatasetIO.cpp b/src/simplnx/Utilities/Parsing/HDF5/IO/DatasetIO.cpp index 21092cf728..5765526ae7 100644 --- a/src/simplnx/Utilities/Parsing/HDF5/IO/DatasetIO.cpp +++ b/src/simplnx/Utilities/Parsing/HDF5/IO/DatasetIO.cpp @@ -1,5 +1,6 @@ #include "DatasetIO.hpp" +#include "simplnx/Utilities/DataStoreUtilities.hpp" #include "simplnx/Utilities/Parsing/HDF5/H5.hpp" #include "simplnx/Utilities/Parsing/HDF5/IO/GroupIO.hpp" @@ -453,6 +454,42 @@ std::vector DatasetIO::readAsVectorOfStrings() const return strings; } +template +std::shared_ptr> DatasetIO::readAsDataStore() const +{ + using ShapeType = typename IDataStore::ShapeType; + + auto dataset = open(); + size_t numElements = getNumElements(); + + ShapeType tupleShape{numElements}; + ShapeType componentShape{1}; + + std::shared_ptr> dataStorePtr = DataStoreUtilities::CreateDataStore(tupleShape, componentShape, IDataAction::Mode::Execute); + dataStorePtr->readHdf5(*this); + return dataStorePtr; +} + +template +std::shared_ptr> DatasetIO::readAsDataStore(const IDataStore::ShapeType& tupleShape, const IDataStore::ShapeType& componentShape) const +{ + using ShapeType = typename IDataStore::ShapeType; + + auto dataset = open(); + size_t numElements = getNumElements(); + + size_t numTuples = std::accumulate(tupleShape.begin(), tupleShape.end(), static_cast(1), std::multiplies<>()); + size_t numComponents = std::accumulate(componentShape.begin(), componentShape.end(), static_cast(1), std::multiplies<>()); + if(numTuples * numComponents != numElements) + { + return nullptr; + } + + std::shared_ptr> dataStorePtr = DataStoreUtilities::CreateDataStore(tupleShape, componentShape, IDataAction::Mode::Execute); + dataStorePtr->readHdf5(*this); + return dataStorePtr; +} + template std::vector DatasetIO::readAsVector() const { @@ -1402,6 +1439,36 @@ template SIMPLNX_EXPORT std::vector DatasetIO::readAsVector() co template SIMPLNX_EXPORT std::vector DatasetIO::readAsVector() const; #endif +template SIMPLNX_EXPORT std::shared_ptr> DatasetIO::readAsDataStore() const; +template SIMPLNX_EXPORT std::shared_ptr> DatasetIO::readAsDataStore() const; +template SIMPLNX_EXPORT std::shared_ptr> DatasetIO::readAsDataStore() const; +template SIMPLNX_EXPORT std::shared_ptr> DatasetIO::readAsDataStore() const; +template SIMPLNX_EXPORT std::shared_ptr> DatasetIO::readAsDataStore() const; +template SIMPLNX_EXPORT std::shared_ptr> DatasetIO::readAsDataStore() const; +template SIMPLNX_EXPORT std::shared_ptr> DatasetIO::readAsDataStore() const; +template SIMPLNX_EXPORT std::shared_ptr> DatasetIO::readAsDataStore() const; +#ifdef __APPLE__ +// template SIMPLNX_EXPORT std::shared_ptr> DatasetIO::readAsDataStore() const; +#endif +template SIMPLNX_EXPORT std::shared_ptr> DatasetIO::readAsDataStore() const; +template SIMPLNX_EXPORT std::shared_ptr> DatasetIO::readAsDataStore() const; +template SIMPLNX_EXPORT std::shared_ptr> DatasetIO::readAsDataStore() const; + +template SIMPLNX_EXPORT std::shared_ptr> DatasetIO::readAsDataStore(const IDataStore::ShapeType&, const IDataStore::ShapeType&) const; +template SIMPLNX_EXPORT std::shared_ptr> DatasetIO::readAsDataStore(const IDataStore::ShapeType&, const IDataStore::ShapeType&) const; +template SIMPLNX_EXPORT std::shared_ptr> DatasetIO::readAsDataStore(const IDataStore::ShapeType&, const IDataStore::ShapeType&) const; +template SIMPLNX_EXPORT std::shared_ptr> DatasetIO::readAsDataStore(const IDataStore::ShapeType&, const IDataStore::ShapeType&) const; +template SIMPLNX_EXPORT std::shared_ptr> DatasetIO::readAsDataStore(const IDataStore::ShapeType&, const IDataStore::ShapeType&) const; +template SIMPLNX_EXPORT std::shared_ptr> DatasetIO::readAsDataStore(const IDataStore::ShapeType&, const IDataStore::ShapeType&) const; +template SIMPLNX_EXPORT std::shared_ptr> DatasetIO::readAsDataStore(const IDataStore::ShapeType&, const IDataStore::ShapeType&) const; +template SIMPLNX_EXPORT std::shared_ptr> DatasetIO::readAsDataStore(const IDataStore::ShapeType&, const IDataStore::ShapeType&) const; +#ifdef __APPLE__ +// template SIMPLNX_EXPORT std::shared_ptr> DatasetIO::readAsDataStore(const IDataStore::ShapeType&, const IDataStore::ShapeType&) const; +#endif +template SIMPLNX_EXPORT std::shared_ptr> DatasetIO::readAsDataStore(const IDataStore::ShapeType&, const IDataStore::ShapeType&) const; +template SIMPLNX_EXPORT std::shared_ptr> DatasetIO::readAsDataStore(const IDataStore::ShapeType&, const IDataStore::ShapeType&) const; +template SIMPLNX_EXPORT std::shared_ptr> DatasetIO::readAsDataStore(const IDataStore::ShapeType&, const IDataStore::ShapeType&) const; + template SIMPLNX_EXPORT Result<> DatasetIO::readIntoSpan(nonstd::span) const; template SIMPLNX_EXPORT Result<> DatasetIO::readIntoSpan(nonstd::span) const; template SIMPLNX_EXPORT Result<> DatasetIO::readIntoSpan(nonstd::span) const; diff --git a/src/simplnx/Utilities/Parsing/HDF5/IO/DatasetIO.hpp b/src/simplnx/Utilities/Parsing/HDF5/IO/DatasetIO.hpp index 01d96e7374..7e63509907 100644 --- a/src/simplnx/Utilities/Parsing/HDF5/IO/DatasetIO.hpp +++ b/src/simplnx/Utilities/Parsing/HDF5/IO/DatasetIO.hpp @@ -5,12 +5,7 @@ #include "simplnx/Common/Result.hpp" #include "simplnx/Common/Types.hpp" - -// #include "highfive/H5Attribute.hpp" -// #include "highfive/H5DataSet.hpp" -// #include "highfive/H5DataType.hpp" -// #include "highfive/H5File.hpp" -// #include "highfive/H5Group.hpp" +#include "simplnx/DataStructure/AbstractDataStore.hpp" #include #include @@ -120,6 +115,25 @@ class SIMPLNX_EXPORT DatasetIO : public ObjectIO template nx::core::Result<> readIntoSpan(nonstd::span data) const; + /** + * @brief Returns an AbstractDataStore of values for the existing data. + * @tparam T + * @return std::shared_ptr> + */ + template + std::shared_ptr> readAsDataStore() const; + + /** + * @brief Returns an AbstractDataStore of values for the existing data. + * Returns nullptr if the data does not match the specified number of elements. + * @tparam T + * @param tupleDims + * @param componentDims + * @return std::shared_ptr> + */ + template + std::shared_ptr> readAsDataStore(const IDataStore::ShapeType& tupleDims, const IDataStore::ShapeType& componentDims) const; + /** * @brief Reads the dataset into the given span. Requires the span to be the * correct size. Returns false if unable to read. @@ -509,6 +523,36 @@ extern template std::vector DatasetIO::readAsVector() const; extern template std::vector DatasetIO::readAsVector() const; #endif +extern template std::shared_ptr> DatasetIO::readAsDataStore() const; +extern template std::shared_ptr> DatasetIO::readAsDataStore() const; +extern template std::shared_ptr> DatasetIO::readAsDataStore() const; +extern template std::shared_ptr> DatasetIO::readAsDataStore() const; +extern template std::shared_ptr> DatasetIO::readAsDataStore() const; +extern template std::shared_ptr> DatasetIO::readAsDataStore() const; +extern template std::shared_ptr> DatasetIO::readAsDataStore() const; +extern template std::shared_ptr> DatasetIO::readAsDataStore() const; +#ifdef __APPLE__ +// extern template std::shared_ptr> DatasetIO::readAsDataStore() const; +#endif +extern template std::shared_ptr> DatasetIO::readAsDataStore() const; +extern template std::shared_ptr> DatasetIO::readAsDataStore() const; +extern template std::shared_ptr> DatasetIO::readAsDataStore() const; + +extern template std::shared_ptr> DatasetIO::readAsDataStore(const IDataStore::ShapeType&, const IDataStore::ShapeType&) const; +extern template std::shared_ptr> DatasetIO::readAsDataStore(const IDataStore::ShapeType&, const IDataStore::ShapeType&) const; +extern template std::shared_ptr> DatasetIO::readAsDataStore(const IDataStore::ShapeType&, const IDataStore::ShapeType&) const; +extern template std::shared_ptr> DatasetIO::readAsDataStore(const IDataStore::ShapeType&, const IDataStore::ShapeType&) const; +extern template std::shared_ptr> DatasetIO::readAsDataStore(const IDataStore::ShapeType&, const IDataStore::ShapeType&) const; +extern template std::shared_ptr> DatasetIO::readAsDataStore(const IDataStore::ShapeType&, const IDataStore::ShapeType&) const; +extern template std::shared_ptr> DatasetIO::readAsDataStore(const IDataStore::ShapeType&, const IDataStore::ShapeType&) const; +extern template std::shared_ptr> DatasetIO::readAsDataStore(const IDataStore::ShapeType&, const IDataStore::ShapeType&) const; +#ifdef __APPLE__ +// extern template std::shared_ptr> DatasetIO::readAsDataStore(const IDataStore::ShapeType&, const IDataStore::ShapeType&) const; +#endif +extern template std::shared_ptr> DatasetIO::readAsDataStore(const IDataStore::ShapeType&, const IDataStore::ShapeType&) const; +extern template std::shared_ptr> DatasetIO::readAsDataStore(const IDataStore::ShapeType&, const IDataStore::ShapeType&) const; +extern template std::shared_ptr> DatasetIO::readAsDataStore(const IDataStore::ShapeType&, const IDataStore::ShapeType&) const; + extern template nx::core::Result<> DatasetIO::readIntoSpan(nonstd::span) const; extern template nx::core::Result<> DatasetIO::readIntoSpan(nonstd::span) const; extern template nx::core::Result<> DatasetIO::readIntoSpan(nonstd::span) const; diff --git a/src/simplnx/Utilities/Parsing/HDF5/IO/GroupIO.cpp b/src/simplnx/Utilities/Parsing/HDF5/IO/GroupIO.cpp index ea39740467..5071a64525 100644 --- a/src/simplnx/Utilities/Parsing/HDF5/IO/GroupIO.cpp +++ b/src/simplnx/Utilities/Parsing/HDF5/IO/GroupIO.cpp @@ -144,6 +144,7 @@ bool GroupIO::exists(const std::string& childName) const ObjectIO::ObjectType GroupIO::getObjectType(const std::string& childName) const { + open(); if(!isValid()) { return ObjectType::Unknown; diff --git a/src/simplnx/Utilities/Parsing/HDF5/IO/ObjectIO.cpp b/src/simplnx/Utilities/Parsing/HDF5/IO/ObjectIO.cpp index 8482e2e277..9d5845505c 100644 --- a/src/simplnx/Utilities/Parsing/HDF5/IO/ObjectIO.cpp +++ b/src/simplnx/Utilities/Parsing/HDF5/IO/ObjectIO.cpp @@ -51,6 +51,7 @@ bool ObjectIO::isValid() const std::string ObjectIO::getName() const { + open(); return nx::core::HDF5::GetNameFromBuffer(m_ObjectName); } @@ -210,6 +211,7 @@ Result ObjectIO::readStringAttribute(const std::string& attributeNa std::vector attributeOutput; Result returnResult = {}; + open(); if(!hasAttribute(attributeName)) { return MakeErrorResult(-445, fmt::format("Attribute '{}' does not exist in Object '{}'", attributeName, getName()));